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