1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-11-26 GuEe-GUI first version
9 */
10
11 #include <rtthread.h>
12 #include <rtservice.h>
13
14 #define DBG_TAG "rtdm.reset"
15 #define DBG_LVL DBG_INFO
16 #include <rtdbg.h>
17
18 #include <drivers/ofw.h>
19 #include <drivers/misc.h>
20 #include <drivers/reset.h>
21 #include <drivers/platform.h>
22
23 struct reset_control_array
24 {
25 struct rt_reset_control captain;
26
27 rt_size_t count;
28 struct rt_reset_control *rstcs[];
29 };
30
31 #define reset_control_to_array(rstc) rt_container_of(rstc, struct reset_control_array, captain)
32
rt_reset_controller_register(struct rt_reset_controller * rstcer)33 rt_err_t rt_reset_controller_register(struct rt_reset_controller *rstcer)
34 {
35 if (!rstcer)
36 {
37 return -RT_EINVAL;
38 }
39
40 #if RT_NAME_MAX > 0
41 rt_strncpy(rstcer->parent.name, RT_RESET_CONTROLLER_OBJ_NAME, RT_NAME_MAX);
42 #else
43 rstcer->parent.name = RT_RESET_CONTROLLER_OBJ_NAME;
44 #endif
45
46 rt_list_init(&rstcer->rstc_nodes);
47 rt_spin_lock_init(&rstcer->spinlock);
48
49 if (rstcer->ofw_node)
50 {
51 if (!rt_ofw_data(rstcer->ofw_node))
52 {
53 rt_ofw_data(rstcer->ofw_node) = rstcer;
54 }
55 }
56
57 return RT_EOK;
58 }
59
rt_reset_controller_unregister(struct rt_reset_controller * rstcer)60 rt_err_t rt_reset_controller_unregister(struct rt_reset_controller *rstcer)
61 {
62 rt_err_t err = RT_EOK;
63
64 if (!rstcer)
65 {
66 return -RT_EINVAL;
67 }
68
69 rt_spin_lock(&rstcer->spinlock);
70
71 if (!rt_list_isempty(&rstcer->rstc_nodes))
72 {
73 err = -RT_EBUSY;
74 goto _out_lock;
75 }
76
77 _out_lock:
78 rt_spin_unlock(&rstcer->spinlock);
79
80 return err;
81 }
82
rt_reset_control_reset(struct rt_reset_control * rstc)83 rt_err_t rt_reset_control_reset(struct rt_reset_control *rstc)
84 {
85 rt_err_t err;
86
87 if (!rstc)
88 {
89 return RT_EOK;
90 }
91
92 if (rstc->rstcer->ops->reset)
93 {
94 if ((err = rstc->rstcer->ops->reset(rstc)))
95 {
96 return err;
97 }
98 }
99
100 if (rstc->is_array)
101 {
102 struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
103
104 for (int i = 0; i < rstc_arr->count; ++i)
105 {
106 if ((err = rt_reset_control_reset(rstc_arr->rstcs[i])))
107 {
108 return err;
109 }
110 }
111 }
112
113 return RT_EOK;
114 }
115
rt_reset_control_assert(struct rt_reset_control * rstc)116 rt_err_t rt_reset_control_assert(struct rt_reset_control *rstc)
117 {
118 rt_err_t err;
119
120 if (!rstc)
121 {
122 return RT_EOK;
123 }
124
125 if (rstc->rstcer->ops->assert)
126 {
127 if ((err = rstc->rstcer->ops->assert(rstc)))
128 {
129 return err;
130 }
131 }
132
133 if (rstc->is_array)
134 {
135 struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
136
137 for (int i = 0; i < rstc_arr->count; ++i)
138 {
139 if ((err = rt_reset_control_assert(rstc_arr->rstcs[i])))
140 {
141 if (rstc->rstcer->ops->deassert)
142 {
143 rstc->rstcer->ops->deassert(rstc);
144 }
145
146 while (i --> 0)
147 {
148 rt_reset_control_deassert(rstc_arr->rstcs[i]);
149 }
150
151 return err;
152 }
153 }
154 }
155
156 return RT_EOK;
157 }
158
rt_reset_control_deassert(struct rt_reset_control * rstc)159 rt_err_t rt_reset_control_deassert(struct rt_reset_control *rstc)
160 {
161 rt_err_t err;
162
163 if (!rstc)
164 {
165 return RT_EOK;
166 }
167
168 if (rstc->rstcer->ops->deassert)
169 {
170 if ((err = rstc->rstcer->ops->deassert(rstc)))
171 {
172 return err;
173 }
174 }
175
176 if (rstc->is_array)
177 {
178 struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
179
180 for (int i = 0; i < rstc_arr->count; ++i)
181 {
182 if ((err = rt_reset_control_deassert(rstc_arr->rstcs[i])))
183 {
184 if (rstc->rstcer->ops->assert)
185 {
186 rstc->rstcer->ops->assert(rstc);
187 }
188
189 while (i --> 0)
190 {
191 rt_reset_control_assert(rstc_arr->rstcs[i]);
192 }
193
194 return err;
195 }
196 }
197 }
198
199 return RT_EOK;
200 }
201
rt_reset_control_status(struct rt_reset_control * rstc)202 int rt_reset_control_status(struct rt_reset_control *rstc)
203 {
204 if (!rstc)
205 {
206 return RT_EOK;
207 }
208
209 if (rstc->rstcer->ops->status)
210 {
211 return rstc->rstcer->ops->status(rstc);
212 }
213
214 return -RT_ENOSYS;
215 }
216
reset_free(struct rt_reset_control * rstc)217 static void reset_free(struct rt_reset_control *rstc)
218 {
219 if (rstc->is_array)
220 {
221 struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
222
223 for (int i = 0; i < rstc_arr->count; ++i)
224 {
225 rt_reset_control_put(rstc_arr->rstcs[i]);
226 }
227 }
228
229 rt_free(rstc);
230 }
231
rt_reset_control_get_array(struct rt_device * dev)232 struct rt_reset_control *rt_reset_control_get_array(struct rt_device *dev)
233 {
234 return rt_ofw_get_reset_control_array(dev->ofw_node);
235 }
236
rt_reset_control_get_by_index(struct rt_device * dev,int index)237 struct rt_reset_control *rt_reset_control_get_by_index(struct rt_device *dev, int index)
238 {
239 return rt_ofw_get_reset_control_by_index(dev->ofw_node, index);
240 }
241
rt_reset_control_get_by_name(struct rt_device * dev,const char * name)242 struct rt_reset_control *rt_reset_control_get_by_name(struct rt_device *dev, const char *name)
243 {
244 return rt_ofw_get_reset_control_by_name(dev->ofw_node, name);
245 }
246
rt_reset_control_put(struct rt_reset_control * rstc)247 void rt_reset_control_put(struct rt_reset_control *rstc)
248 {
249 struct rt_reset_controller *rstcer;
250
251 if (!rstc)
252 {
253 return;
254 }
255
256 rstcer = rstc->rstcer;
257
258 rt_spin_lock(&rstcer->spinlock);
259
260 rt_list_remove(&rstc->list);
261
262 rt_spin_unlock(&rstcer->spinlock);
263
264 reset_free(rstc);
265 }
266
ofw_get_reset_control(struct rt_ofw_node * np,int index,const char * name,rt_bool_t is_array)267 static struct rt_reset_control *ofw_get_reset_control(struct rt_ofw_node *np, int index,
268 const char *name, rt_bool_t is_array)
269 {
270 rt_err_t err = RT_EOK;
271 struct rt_reset_control *rstc;
272 struct rt_ofw_cell_args reset_args = {};
273 struct rt_reset_controller *rstcer = RT_NULL;
274
275 if (is_array)
276 {
277 rt_size_t rstc_nr;
278 struct reset_control_array *rstc_arr;
279
280 rstc_nr = rt_ofw_count_phandle_cells(np, "resets", "#reset-cells");
281
282 if (!rstc_nr)
283 {
284 return RT_NULL;
285 }
286
287 rstc_arr = rt_calloc(1, sizeof(*rstc_arr) + sizeof(struct rt_reset_control *) * rstc_nr);
288
289 if (!rstc_arr)
290 {
291 LOG_E("No memory to create %s[%d] reset control",
292 rt_ofw_node_full_name(np), index);
293
294 return rt_err_ptr(-RT_ENOMEM);
295 }
296
297 rstc_arr->count = rstc_nr - 1;
298
299 for (int i = 0; i < rstc_arr->count; ++i)
300 {
301 rstc_arr->rstcs[i] = ofw_get_reset_control(np, i + 1, RT_NULL, RT_FALSE);
302
303 if (rt_is_err(rstc_arr->rstcs[i]))
304 {
305 err = rt_ptr_err(rstc_arr->rstcs[i]);
306
307 while (i --> 0)
308 {
309 rt_reset_control_put(rstc_arr->rstcs[i]);
310 }
311
312 rt_free(rstc_arr);
313
314 return rt_err_ptr(err);
315 }
316 }
317
318 rstc = &rstc_arr->captain;
319 rstc->is_array = RT_TRUE;
320 }
321 else
322 {
323 rstc = rt_calloc(1, sizeof(*rstc));
324
325 if (!rstc)
326 {
327 LOG_E("No memory to create %s[%d] reset control",
328 rt_ofw_node_full_name(np), index);
329
330 return rt_err_ptr(-RT_ENOMEM);
331 }
332 }
333
334 if (!rt_ofw_parse_phandle_cells(np, "resets", "#reset-cells", index, &reset_args))
335 {
336 void *rt_data;
337 struct rt_object *obj;
338 struct rt_ofw_node *reset_np = reset_args.data;
339
340 if (!rt_ofw_data(reset_np))
341 {
342 rt_platform_ofw_request(reset_np);
343 }
344
345 rt_data = rt_ofw_data(reset_np);
346
347 if (rt_data && (obj = rt_ofw_parse_object(reset_args.data,
348 RT_RESET_CONTROLLER_OBJ_NAME, "#reset-cells")))
349 {
350 rstcer = rt_container_of(obj, struct rt_reset_controller, parent);
351 }
352
353 rt_ofw_node_put(reset_np);
354
355 if (!rstcer)
356 {
357 err = -RT_EINVAL;
358 goto _fail;
359 }
360 }
361 else
362 {
363 /* Not reset */
364 goto _fail;
365 }
366
367 if (!name && rt_ofw_prop_read_bool(np, "reset-names"))
368 {
369 rt_ofw_prop_read_string_index(np, "reset-names", index, &name);
370 }
371
372 rstc->con_id = name;
373 rstc->rstcer = rstcer;
374
375 if (rstcer->ops->ofw_parse)
376 {
377 err = rstcer->ops->ofw_parse(rstc, &reset_args);
378
379 if (err)
380 {
381 LOG_E("Parse %s reset control error = %s",
382 rt_ofw_node_full_name(np), rt_strerror(err));
383
384 goto _fail;
385 }
386 }
387
388 rstc->id = reset_args.args[0];
389
390 rt_list_init(&rstc->list);
391
392 rt_spin_lock(&rstcer->spinlock);
393
394 rt_list_insert_after(&rstcer->rstc_nodes, &rstc->list);
395
396 rt_spin_unlock(&rstcer->spinlock);
397
398 return rstc;
399
400 _fail:
401 if (rstc && !rstc->is_array)
402 {
403 rt_free(rstc);
404 }
405
406 return rt_err_ptr(err);
407 }
408
rt_ofw_get_reset_control_array(struct rt_ofw_node * np)409 struct rt_reset_control *rt_ofw_get_reset_control_array(struct rt_ofw_node *np)
410 {
411 return ofw_get_reset_control(np, 0, RT_NULL, RT_TRUE);
412 }
413
rt_ofw_get_reset_control_by_index(struct rt_ofw_node * np,int index)414 struct rt_reset_control *rt_ofw_get_reset_control_by_index(struct rt_ofw_node *np, int index)
415 {
416 return ofw_get_reset_control(np, index, RT_NULL, RT_FALSE);
417 }
418
rt_ofw_get_reset_control_by_name(struct rt_ofw_node * np,const char * name)419 struct rt_reset_control *rt_ofw_get_reset_control_by_name(struct rt_ofw_node *np, const char *name)
420 {
421 if (np)
422 {
423 int index = rt_ofw_prop_index_of_string(np, "reset-names", name);
424
425 if (index >= 0)
426 {
427 return ofw_get_reset_control(np, index, name, RT_FALSE);
428 }
429 }
430
431 return RT_NULL;
432 }
433