uboot/drivers/reset/reset-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2016, NVIDIA CORPORATION.
   4 */
   5
   6#define LOG_CATEGORY UCLASS_RESET
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <fdtdec.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <reset.h>
  14#include <reset-uclass.h>
  15#include <dm/devres.h>
  16#include <dm/lists.h>
  17
  18static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
  19{
  20        return (struct reset_ops *)dev->driver->ops;
  21}
  22
  23static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
  24                                  struct ofnode_phandle_args *args)
  25{
  26        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
  27
  28        if (args->args_count != 1) {
  29                debug("Invalid args_count: %d\n", args->args_count);
  30                return -EINVAL;
  31        }
  32
  33        reset_ctl->id = args->args[0];
  34
  35        return 0;
  36}
  37
  38static int reset_get_by_index_tail(int ret, ofnode node,
  39                                   struct ofnode_phandle_args *args,
  40                                   const char *list_name, int index,
  41                                   struct reset_ctl *reset_ctl)
  42{
  43        struct udevice *dev_reset;
  44        struct reset_ops *ops;
  45
  46        assert(reset_ctl);
  47        reset_ctl->dev = NULL;
  48        if (ret)
  49                return ret;
  50
  51        ret = uclass_get_device_by_ofnode(UCLASS_RESET, args->node,
  52                                          &dev_reset);
  53        if (ret) {
  54                debug("%s: uclass_get_device_by_ofnode() failed: %d\n",
  55                      __func__, ret);
  56                debug("%s %d\n", ofnode_get_name(args->node), args->args[0]);
  57                return ret;
  58        }
  59        ops = reset_dev_ops(dev_reset);
  60
  61        reset_ctl->dev = dev_reset;
  62        if (ops->of_xlate)
  63                ret = ops->of_xlate(reset_ctl, args);
  64        else
  65                ret = reset_of_xlate_default(reset_ctl, args);
  66        if (ret) {
  67                debug("of_xlate() failed: %d\n", ret);
  68                return ret;
  69        }
  70
  71        ret = ops->request ? ops->request(reset_ctl) : 0;
  72        if (ret) {
  73                debug("ops->request() failed: %d\n", ret);
  74                return ret;
  75        }
  76
  77        return 0;
  78}
  79
  80int reset_get_by_index(struct udevice *dev, int index,
  81                       struct reset_ctl *reset_ctl)
  82{
  83        struct ofnode_phandle_args args;
  84        int ret;
  85
  86        ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
  87                                         index, &args);
  88
  89        return reset_get_by_index_tail(ret, dev_ofnode(dev), &args, "resets",
  90                                       index > 0, reset_ctl);
  91}
  92
  93int reset_get_by_index_nodev(ofnode node, int index,
  94                             struct reset_ctl *reset_ctl)
  95{
  96        struct ofnode_phandle_args args;
  97        int ret;
  98
  99        ret = ofnode_parse_phandle_with_args(node, "resets", "#reset-cells", 0,
 100                                             index, &args);
 101
 102        return reset_get_by_index_tail(ret, node, &args, "resets",
 103                                       index > 0, reset_ctl);
 104}
 105
 106static int __reset_get_bulk(struct udevice *dev, ofnode node,
 107                            struct reset_ctl_bulk *bulk)
 108{
 109        int i, ret, err, count;
 110
 111        bulk->count = 0;
 112
 113        count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells",
 114                                               0);
 115        if (count < 1)
 116                return count;
 117
 118        bulk->resets = devm_kcalloc(dev, count, sizeof(struct reset_ctl),
 119                                    GFP_KERNEL);
 120        if (!bulk->resets)
 121                return -ENOMEM;
 122
 123        for (i = 0; i < count; i++) {
 124                ret = reset_get_by_index_nodev(node, i, &bulk->resets[i]);
 125                if (ret < 0)
 126                        goto bulk_get_err;
 127
 128                ++bulk->count;
 129        }
 130
 131        return 0;
 132
 133bulk_get_err:
 134        err = reset_release_all(bulk->resets, bulk->count);
 135        if (err)
 136                debug("%s: could release all resets for %p\n",
 137                      __func__, dev);
 138
 139        return ret;
 140}
 141
 142int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
 143{
 144        return __reset_get_bulk(dev, dev_ofnode(dev), bulk);
 145}
 146
 147int reset_get_by_name(struct udevice *dev, const char *name,
 148                     struct reset_ctl *reset_ctl)
 149{
 150        int index;
 151
 152        debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
 153              reset_ctl);
 154        reset_ctl->dev = NULL;
 155
 156        index = dev_read_stringlist_search(dev, "reset-names", name);
 157        if (index < 0) {
 158                debug("fdt_stringlist_search() failed: %d\n", index);
 159                return index;
 160        }
 161
 162        return reset_get_by_index(dev, index, reset_ctl);
 163}
 164
 165int reset_request(struct reset_ctl *reset_ctl)
 166{
 167        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 168
 169        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 170
 171        return ops->request ? ops->request(reset_ctl) : 0;
 172}
 173
 174int reset_free(struct reset_ctl *reset_ctl)
 175{
 176        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 177
 178        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 179
 180        return ops->rfree ? ops->rfree(reset_ctl) : 0;
 181}
 182
 183int reset_assert(struct reset_ctl *reset_ctl)
 184{
 185        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 186
 187        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 188
 189        return ops->rst_assert ? ops->rst_assert(reset_ctl) : 0;
 190}
 191
 192int reset_assert_bulk(struct reset_ctl_bulk *bulk)
 193{
 194        int i, ret;
 195
 196        for (i = 0; i < bulk->count; i++) {
 197                ret = reset_assert(&bulk->resets[i]);
 198                if (ret < 0)
 199                        return ret;
 200        }
 201
 202        return 0;
 203}
 204
 205int reset_deassert(struct reset_ctl *reset_ctl)
 206{
 207        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 208
 209        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 210
 211        return ops->rst_deassert ? ops->rst_deassert(reset_ctl) : 0;
 212}
 213
 214int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
 215{
 216        int i, ret;
 217
 218        for (i = 0; i < bulk->count; i++) {
 219                ret = reset_deassert(&bulk->resets[i]);
 220                if (ret < 0)
 221                        return ret;
 222        }
 223
 224        return 0;
 225}
 226
 227int reset_status(struct reset_ctl *reset_ctl)
 228{
 229        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 230
 231        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 232
 233        return ops->rst_status ? ops->rst_status(reset_ctl) : 0;
 234}
 235
 236int reset_release_all(struct reset_ctl *reset_ctl, int count)
 237{
 238        int i, ret;
 239
 240        for (i = 0; i < count; i++) {
 241                debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]);
 242
 243                /* check if reset has been previously requested */
 244                if (!reset_ctl[i].dev)
 245                        continue;
 246
 247                ret = reset_assert(&reset_ctl[i]);
 248                if (ret)
 249                        return ret;
 250
 251                ret = reset_free(&reset_ctl[i]);
 252                if (ret)
 253                        return ret;
 254        }
 255
 256        return 0;
 257}
 258
 259static void devm_reset_release(struct udevice *dev, void *res)
 260{
 261        reset_free(res);
 262}
 263
 264struct reset_ctl *devm_reset_control_get_by_index(struct udevice *dev,
 265                                                  int index)
 266{
 267        int rc;
 268        struct reset_ctl *reset_ctl;
 269
 270        reset_ctl = devres_alloc(devm_reset_release, sizeof(struct reset_ctl),
 271                                 __GFP_ZERO);
 272        if (unlikely(!reset_ctl))
 273                return ERR_PTR(-ENOMEM);
 274
 275        rc = reset_get_by_index(dev, index, reset_ctl);
 276        if (rc)
 277                return ERR_PTR(rc);
 278
 279        devres_add(dev, reset_ctl);
 280        return reset_ctl;
 281}
 282
 283struct reset_ctl *devm_reset_control_get(struct udevice *dev, const char *id)
 284{
 285        int rc;
 286        struct reset_ctl *reset_ctl;
 287
 288        reset_ctl = devres_alloc(devm_reset_release, sizeof(struct reset_ctl),
 289                                 __GFP_ZERO);
 290        if (unlikely(!reset_ctl))
 291                return ERR_PTR(-ENOMEM);
 292
 293        rc = reset_get_by_name(dev, id, reset_ctl);
 294        if (rc)
 295                return ERR_PTR(rc);
 296
 297        devres_add(dev, reset_ctl);
 298        return reset_ctl;
 299}
 300
 301struct reset_ctl *devm_reset_control_get_optional(struct udevice *dev,
 302                                                  const char *id)
 303{
 304        struct reset_ctl *r = devm_reset_control_get(dev, id);
 305
 306        if (IS_ERR(r))
 307                return NULL;
 308
 309        return r;
 310}
 311
 312static void devm_reset_bulk_release(struct udevice *dev, void *res)
 313{
 314        struct reset_ctl_bulk *bulk = res;
 315
 316        reset_release_all(bulk->resets, bulk->count);
 317}
 318
 319struct reset_ctl_bulk *devm_reset_bulk_get_by_node(struct udevice *dev,
 320                                                   ofnode node)
 321{
 322        int rc;
 323        struct reset_ctl_bulk *bulk;
 324
 325        bulk = devres_alloc(devm_reset_bulk_release,
 326                            sizeof(struct reset_ctl_bulk),
 327                            __GFP_ZERO);
 328
 329        /* this looks like a leak, but devres takes care of it */
 330        if (unlikely(!bulk))
 331                return ERR_PTR(-ENOMEM);
 332
 333        rc = __reset_get_bulk(dev, node, bulk);
 334        if (rc)
 335                return ERR_PTR(rc);
 336
 337        devres_add(dev, bulk);
 338        return bulk;
 339}
 340
 341struct reset_ctl_bulk *devm_reset_bulk_get_optional_by_node(struct udevice *dev,
 342                                                            ofnode node)
 343{
 344        struct reset_ctl_bulk *bulk;
 345
 346        bulk = devm_reset_bulk_get_by_node(dev, node);
 347
 348        if (IS_ERR(bulk))
 349                return NULL;
 350
 351        return bulk;
 352}
 353
 354struct reset_ctl_bulk *devm_reset_bulk_get(struct udevice *dev)
 355{
 356        return devm_reset_bulk_get_by_node(dev, dev_ofnode(dev));
 357}
 358
 359struct reset_ctl_bulk *devm_reset_bulk_get_optional(struct udevice *dev)
 360{
 361        return devm_reset_bulk_get_optional_by_node(dev, dev_ofnode(dev));
 362}
 363
 364UCLASS_DRIVER(reset) = {
 365        .id             = UCLASS_RESET,
 366        .name           = "reset",
 367};
 368