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