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