uboot/drivers/reset/reset-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2016, NVIDIA CORPORATION.
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <fdtdec.h>
   9#include <reset.h>
  10#include <reset-uclass.h>
  11
  12static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
  13{
  14        return (struct reset_ops *)dev->driver->ops;
  15}
  16
  17static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
  18                                  struct ofnode_phandle_args *args)
  19{
  20        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
  21
  22        if (args->args_count != 1) {
  23                debug("Invaild args_count: %d\n", args->args_count);
  24                return -EINVAL;
  25        }
  26
  27        reset_ctl->id = args->args[0];
  28
  29        return 0;
  30}
  31
  32static int reset_get_by_index_tail(int ret, ofnode node,
  33                                   struct ofnode_phandle_args *args,
  34                                   const char *list_name, int index,
  35                                   struct reset_ctl *reset_ctl)
  36{
  37        struct udevice *dev_reset;
  38        struct reset_ops *ops;
  39
  40        assert(reset_ctl);
  41        reset_ctl->dev = NULL;
  42        if (ret)
  43                return ret;
  44
  45        ret = uclass_get_device_by_ofnode(UCLASS_RESET, args->node,
  46                                          &dev_reset);
  47        if (ret) {
  48                debug("%s: uclass_get_device_by_ofnode() failed: %d\n",
  49                      __func__, ret);
  50                debug("%s %d\n", ofnode_get_name(args->node), args->args[0]);
  51                return ret;
  52        }
  53        ops = reset_dev_ops(dev_reset);
  54
  55        reset_ctl->dev = dev_reset;
  56        if (ops->of_xlate)
  57                ret = ops->of_xlate(reset_ctl, args);
  58        else
  59                ret = reset_of_xlate_default(reset_ctl, args);
  60        if (ret) {
  61                debug("of_xlate() failed: %d\n", ret);
  62                return ret;
  63        }
  64
  65        ret = ops->request(reset_ctl);
  66        if (ret) {
  67                debug("ops->request() failed: %d\n", ret);
  68                return ret;
  69        }
  70
  71        return 0;
  72}
  73
  74int reset_get_by_index(struct udevice *dev, int index,
  75                       struct reset_ctl *reset_ctl)
  76{
  77        struct ofnode_phandle_args args;
  78        int ret;
  79
  80        ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
  81                                         index, &args);
  82
  83        return reset_get_by_index_tail(ret, dev_ofnode(dev), &args, "resets",
  84                                       index > 0, reset_ctl);
  85}
  86
  87int reset_get_by_index_nodev(ofnode node, int index,
  88                             struct reset_ctl *reset_ctl)
  89{
  90        struct ofnode_phandle_args args;
  91        int ret;
  92
  93        ret = ofnode_parse_phandle_with_args(node, "resets", "#reset-cells", 0,
  94                                             index > 0, &args);
  95
  96        return reset_get_by_index_tail(ret, node, &args, "resets",
  97                                       index > 0, reset_ctl);
  98}
  99
 100int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
 101{
 102        int i, ret, err, count;
 103        
 104        bulk->count = 0;
 105
 106        count = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
 107        if (count < 1)
 108                return count;
 109
 110        bulk->resets = devm_kcalloc(dev, count, sizeof(struct reset_ctl),
 111                                    GFP_KERNEL);
 112        if (!bulk->resets)
 113                return -ENOMEM;
 114
 115        for (i = 0; i < count; i++) {
 116                ret = reset_get_by_index(dev, i, &bulk->resets[i]);
 117                if (ret < 0)
 118                        goto bulk_get_err;
 119
 120                ++bulk->count;
 121        }
 122
 123        return 0;
 124
 125bulk_get_err:
 126        err = reset_release_all(bulk->resets, bulk->count);
 127        if (err)
 128                debug("%s: could release all resets for %p\n",
 129                      __func__, dev);
 130
 131        return ret;
 132}
 133
 134int reset_get_by_name(struct udevice *dev, const char *name,
 135                     struct reset_ctl *reset_ctl)
 136{
 137        int index;
 138
 139        debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
 140              reset_ctl);
 141        reset_ctl->dev = NULL;
 142
 143        index = dev_read_stringlist_search(dev, "reset-names", name);
 144        if (index < 0) {
 145                debug("fdt_stringlist_search() failed: %d\n", index);
 146                return index;
 147        }
 148
 149        return reset_get_by_index(dev, index, reset_ctl);
 150}
 151
 152int reset_request(struct reset_ctl *reset_ctl)
 153{
 154        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 155
 156        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 157
 158        return ops->request(reset_ctl);
 159}
 160
 161int reset_free(struct reset_ctl *reset_ctl)
 162{
 163        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 164
 165        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 166
 167        return ops->free(reset_ctl);
 168}
 169
 170int reset_assert(struct reset_ctl *reset_ctl)
 171{
 172        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 173
 174        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 175
 176        return ops->rst_assert(reset_ctl);
 177}
 178
 179int reset_assert_bulk(struct reset_ctl_bulk *bulk)
 180{
 181        int i, ret;
 182
 183        for (i = 0; i < bulk->count; i++) {
 184                ret = reset_assert(&bulk->resets[i]);
 185                if (ret < 0)
 186                        return ret;
 187        }
 188
 189        return 0;
 190}
 191
 192int reset_deassert(struct reset_ctl *reset_ctl)
 193{
 194        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 195
 196        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 197
 198        return ops->rst_deassert(reset_ctl);
 199}
 200
 201int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
 202{
 203        int i, ret;
 204
 205        for (i = 0; i < bulk->count; i++) {
 206                ret = reset_deassert(&bulk->resets[i]);
 207                if (ret < 0)
 208                        return ret;
 209        }
 210
 211        return 0;
 212}
 213
 214int reset_status(struct reset_ctl *reset_ctl)
 215{
 216        struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
 217
 218        debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 219
 220        return ops->rst_status(reset_ctl);
 221}
 222
 223int reset_release_all(struct reset_ctl *reset_ctl, int count)
 224{
 225        int i, ret;
 226
 227        for (i = 0; i < count; i++) {
 228                debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]);
 229
 230                /* check if reset has been previously requested */
 231                if (!reset_ctl[i].dev)
 232                        continue;
 233
 234                ret = reset_assert(&reset_ctl[i]);
 235                if (ret)
 236                        return ret;
 237
 238                ret = reset_free(&reset_ctl[i]);
 239                if (ret)
 240                        return ret;
 241        }
 242
 243        return 0;
 244}
 245
 246UCLASS_DRIVER(reset) = {
 247        .id             = UCLASS_RESET,
 248        .name           = "reset",
 249};
 250