1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-09-23     GuEe-GUI     first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtservice.h>
13 
14 #define DBG_TAG "rtdm.regulator"
15 #define DBG_LVL DBG_INFO
16 #include <rtdbg.h>
17 
18 #include <drivers/ofw.h>
19 #include <drivers/platform.h>
20 #include <drivers/regulator.h>
21 
22 struct rt_regulator
23 {
24     struct rt_regulator_node *reg_np;
25 };
26 
27 static RT_DEFINE_SPINLOCK(_regulator_lock);
28 
29 static rt_err_t regulator_enable(struct rt_regulator_node *reg_np);
30 static rt_err_t regulator_disable(struct rt_regulator_node *reg_np);
31 
rt_regulator_register(struct rt_regulator_node * reg_np)32 rt_err_t rt_regulator_register(struct rt_regulator_node *reg_np)
33 {
34     const struct rt_regulator_param *param;
35 
36     if (!reg_np || !reg_np->dev || !reg_np->param || !reg_np->ops)
37     {
38         return -RT_EINVAL;
39     }
40 
41     rt_list_init(&reg_np->list);
42     rt_list_init(&reg_np->children_nodes);
43     rt_list_init(&reg_np->notifier_nodes);
44     rt_ref_init(&reg_np->ref);
45     rt_atomic_store(&reg_np->enabled_count, 0);
46 
47     param = reg_np->param;
48 
49     reg_np->parent = RT_NULL;
50 
51 #ifdef RT_USING_OFW
52     if (reg_np->dev->ofw_node)
53     {
54         rt_ofw_data(reg_np->dev->ofw_node) = reg_np;
55     }
56 #endif /* RT_USING_OFW */
57 
58     if (param->boot_on || param->always_on)
59     {
60         regulator_enable(reg_np);
61     }
62 
63     return RT_EOK;
64 }
65 
rt_regulator_unregister(struct rt_regulator_node * reg_np)66 rt_err_t rt_regulator_unregister(struct rt_regulator_node *reg_np)
67 {
68     rt_err_t err = RT_EOK;
69 
70     if (!reg_np)
71     {
72         return -RT_EINVAL;
73     }
74 
75     rt_hw_spin_lock(&_regulator_lock.lock);
76 
77     if (rt_atomic_load(&reg_np->enabled_count) != 0)
78     {
79         err = -RT_EBUSY;
80 
81         LOG_E("%s was enabled by consumer", reg_np->supply_name);
82 
83         goto _unlock;
84     }
85 
86     if (!(reg_np->param->boot_on || reg_np->param->always_on))
87     {
88         regulator_disable(reg_np);
89     }
90 
91     if (!rt_list_isempty(&reg_np->children_nodes) || rt_ref_read(&reg_np->ref) > 1)
92     {
93         err = -RT_EBUSY;
94 
95         goto _unlock;
96     }
97 
98     reg_np->parent = RT_NULL;
99     rt_list_remove(&reg_np->list);
100 
101 _unlock:
102     rt_hw_spin_unlock(&_regulator_lock.lock);
103 
104     return err;
105 }
106 
rt_regulator_notifier_register(struct rt_regulator * reg,struct rt_regulator_notifier * notifier)107 rt_err_t rt_regulator_notifier_register(struct rt_regulator *reg,
108         struct rt_regulator_notifier *notifier)
109 {
110     struct rt_regulator_node *reg_np;
111 
112     if (!reg || !notifier)
113     {
114         return -RT_EINVAL;
115     }
116 
117     rt_hw_spin_lock(&_regulator_lock.lock);
118 
119     reg_np = reg->reg_np;
120     notifier->regulator = reg;
121 
122     rt_list_init(&notifier->list);
123     rt_list_insert_after(&reg_np->notifier_nodes, &notifier->list);
124 
125     rt_hw_spin_unlock(&_regulator_lock.lock);
126 
127     return RT_EOK;
128 }
129 
rt_regulator_notifier_unregister(struct rt_regulator * reg,struct rt_regulator_notifier * notifier)130 rt_err_t rt_regulator_notifier_unregister(struct rt_regulator *reg,
131         struct rt_regulator_notifier *notifier)
132 {
133     if (!reg || !notifier)
134     {
135         return -RT_EINVAL;
136     }
137 
138     rt_hw_spin_lock(&_regulator_lock.lock);
139 
140     rt_list_remove(&notifier->list);
141 
142     rt_hw_spin_unlock(&_regulator_lock.lock);
143 
144     return RT_EOK;
145 }
146 
regulator_notifier_call_chain(struct rt_regulator_node * reg_np,rt_ubase_t msg,void * data)147 static rt_err_t regulator_notifier_call_chain(struct rt_regulator_node *reg_np,
148         rt_ubase_t msg, void *data)
149 {
150     rt_err_t err = RT_EOK;
151     struct rt_regulator_notifier *notifier;
152     rt_list_t *head = &reg_np->notifier_nodes;
153 
154     if (rt_list_isempty(head))
155     {
156         return err;
157     }
158 
159     rt_list_for_each_entry(notifier, head, list)
160     {
161         err = notifier->callback(notifier, msg, data);
162 
163         if (err == -RT_EIO)
164         {
165             break;
166         }
167     }
168 
169     return err;
170 }
171 
regulator_get_enable_time(struct rt_regulator_node * reg_np)172 static rt_uint32_t regulator_get_enable_time(struct rt_regulator_node *reg_np)
173 {
174     if (reg_np->param->enable_delay)
175     {
176         return reg_np->param->enable_delay;
177     }
178 
179     if (reg_np->ops->enable_time)
180     {
181         return reg_np->ops->enable_time(reg_np);
182     }
183 
184     return 0;
185 }
186 
regulator_delay(rt_uint32_t delay)187 static void regulator_delay(rt_uint32_t delay)
188 {
189     rt_uint32_t ms = delay / 1000;
190     rt_uint32_t us = delay % 1000;
191 
192     if (ms > 0)
193     {
194         /*
195          * For small enough values, handle super-millisecond
196          * delays in the usleep_range() call below.
197          */
198         if (ms < 20)
199         {
200             us += ms * 1000;
201         }
202         else if (rt_thread_self())
203         {
204             rt_thread_mdelay(ms);
205         }
206         else
207         {
208             rt_hw_us_delay(ms * 1000);
209         }
210     }
211 
212     /*
213      * Give the scheduler some room to coalesce with any other
214      * wakeup sources. For delays shorter than 10 us, don't even
215      * bother setting up high-resolution timers and just busy-loop.
216      */
217     if (us >= 10)
218     {
219         rt_hw_us_delay((us + 100) >> 1);
220     }
221     else
222     {
223         rt_hw_us_delay(us);
224     }
225 }
226 
regulator_enable(struct rt_regulator_node * reg_np)227 static rt_err_t regulator_enable(struct rt_regulator_node *reg_np)
228 {
229     rt_err_t err = RT_EOK;
230     rt_uint32_t enable_delay = regulator_get_enable_time(reg_np);
231 
232     if (reg_np->ops->enable)
233     {
234         err = reg_np->ops->enable(reg_np);
235 
236         if (!err)
237         {
238             if (enable_delay)
239             {
240                 regulator_delay(enable_delay);
241             }
242 
243             rt_atomic_add(&reg_np->enabled_count, 1);
244             err = regulator_notifier_call_chain(reg_np, RT_REGULATOR_MSG_ENABLE, RT_NULL);
245         }
246     }
247 
248     if (!err && reg_np->parent)
249     {
250         err = regulator_enable(reg_np->parent);
251     }
252 
253     return err;
254 }
255 
rt_regulator_enable(struct rt_regulator * reg)256 rt_err_t rt_regulator_enable(struct rt_regulator *reg)
257 {
258     rt_err_t err;
259 
260     if (!reg)
261     {
262         return -RT_EINVAL;
263     }
264 
265     if (rt_regulator_is_enabled(reg))
266     {
267         return RT_EOK;
268     }
269 
270     rt_hw_spin_lock(&_regulator_lock.lock);
271 
272     err = regulator_enable(reg->reg_np);
273 
274     rt_hw_spin_unlock(&_regulator_lock.lock);
275 
276     return err;
277 }
278 
regulator_disable(struct rt_regulator_node * reg_np)279 static rt_err_t regulator_disable(struct rt_regulator_node *reg_np)
280 {
281     rt_err_t err = RT_EOK;
282 
283     if (reg_np->ops->disable)
284     {
285         err = reg_np->ops->disable(reg_np);
286 
287         if (!err)
288         {
289             if (reg_np->param->off_on_delay)
290             {
291                 regulator_delay(reg_np->param->off_on_delay);
292             }
293 
294             err = regulator_notifier_call_chain(reg_np, RT_REGULATOR_MSG_DISABLE, RT_NULL);
295         }
296     }
297 
298     if (!err && reg_np->parent)
299     {
300         err = regulator_disable(reg_np->parent);
301     }
302 
303     return err;
304 }
305 
rt_regulator_disable(struct rt_regulator * reg)306 rt_err_t rt_regulator_disable(struct rt_regulator *reg)
307 {
308     rt_err_t err;
309 
310     if (!reg)
311     {
312         return -RT_EINVAL;
313     }
314 
315     if (!rt_regulator_is_enabled(reg))
316     {
317         return RT_EOK;
318     }
319 
320     if (rt_atomic_load(&reg->reg_np->enabled_count) != 0)
321     {
322         rt_atomic_sub(&reg->reg_np->enabled_count, 1);
323 
324         return RT_EOK;
325     }
326 
327     rt_hw_spin_lock(&_regulator_lock.lock);
328 
329     err = regulator_disable(reg->reg_np);
330 
331     rt_hw_spin_unlock(&_regulator_lock.lock);
332 
333     return err;
334 }
335 
rt_regulator_is_enabled(struct rt_regulator * reg)336 rt_bool_t rt_regulator_is_enabled(struct rt_regulator *reg)
337 {
338     if (!reg)
339     {
340         return -RT_EINVAL;
341     }
342 
343     if (reg->reg_np->ops->is_enabled)
344     {
345         return reg->reg_np->ops->is_enabled(reg->reg_np);
346     }
347 
348     return rt_atomic_load(&reg->reg_np->enabled_count) > 0;
349 }
350 
regulator_set_voltage(struct rt_regulator_node * reg_np,int min_uvolt,int max_uvolt)351 static rt_err_t regulator_set_voltage(struct rt_regulator_node *reg_np, int min_uvolt, int max_uvolt)
352 {
353     rt_err_t err = RT_EOK;
354 
355     if (reg_np->ops->set_voltage)
356     {
357         union rt_regulator_notifier_args args;
358 
359         RT_ASSERT(reg_np->ops->get_voltage != RT_NULL);
360 
361         args.old_uvolt = reg_np->ops->get_voltage(reg_np);
362         args.min_uvolt = min_uvolt;
363         args.max_uvolt = max_uvolt;
364 
365         err = regulator_notifier_call_chain(reg_np, RT_REGULATOR_MSG_VOLTAGE_CHANGE, &args);
366 
367         if (!err)
368         {
369             err = reg_np->ops->set_voltage(reg_np, min_uvolt, max_uvolt);
370         }
371 
372         if (err)
373         {
374             regulator_notifier_call_chain(reg_np, RT_REGULATOR_MSG_VOLTAGE_CHANGE_ERR,
375                     (void *)(rt_base_t)args.old_uvolt);
376         }
377     }
378 
379     if (!err && reg_np->parent)
380     {
381         err = regulator_set_voltage(reg_np->parent, min_uvolt, max_uvolt);
382     }
383 
384     return err;
385 }
386 
rt_regulator_is_supported_voltage(struct rt_regulator * reg,int min_uvolt,int max_uvolt)387 rt_bool_t rt_regulator_is_supported_voltage(struct rt_regulator *reg, int min_uvolt, int max_uvolt)
388 {
389     const struct rt_regulator_param *param;
390 
391     RT_ASSERT(reg != RT_NULL);
392 
393     param = reg->reg_np->param;
394 
395     if (!param)
396     {
397         return RT_FALSE;
398     }
399 
400     return param->min_uvolt <= min_uvolt && param->max_uvolt >= max_uvolt;
401 }
402 
rt_regulator_set_voltage(struct rt_regulator * reg,int min_uvolt,int max_uvolt)403 rt_err_t rt_regulator_set_voltage(struct rt_regulator *reg, int min_uvolt, int max_uvolt)
404 {
405     rt_err_t err;
406 
407     if (!reg)
408     {
409         return -RT_EINVAL;
410     }
411 
412     rt_hw_spin_lock(&_regulator_lock.lock);
413 
414     err = regulator_set_voltage(reg->reg_np, min_uvolt, max_uvolt);
415 
416     rt_hw_spin_unlock(&_regulator_lock.lock);
417 
418     return err;
419 }
420 
rt_regulator_get_voltage(struct rt_regulator * reg)421 int rt_regulator_get_voltage(struct rt_regulator *reg)
422 {
423     int uvolt = RT_REGULATOR_UVOLT_INVALID;
424     struct rt_regulator_node *reg_np;
425 
426     if (!reg)
427     {
428         return -RT_EINVAL;
429     }
430 
431     rt_hw_spin_lock(&_regulator_lock.lock);
432 
433     reg_np = reg->reg_np;
434 
435     if (reg_np->ops->get_voltage)
436     {
437         uvolt = reg_np->ops->get_voltage(reg->reg_np);
438     }
439     else
440     {
441         uvolt = -RT_ENOSYS;
442     }
443 
444     rt_hw_spin_unlock(&_regulator_lock.lock);
445 
446     return uvolt;
447 }
448 
rt_regulator_set_mode(struct rt_regulator * reg,rt_uint32_t mode)449 rt_err_t rt_regulator_set_mode(struct rt_regulator *reg, rt_uint32_t mode)
450 {
451     rt_err_t err;
452     struct rt_regulator_node *reg_np;
453 
454     if (!reg)
455     {
456         return -RT_EINVAL;
457     }
458 
459     rt_hw_spin_lock(&_regulator_lock.lock);
460 
461     reg_np = reg->reg_np;
462 
463     if (reg_np->ops->set_mode)
464     {
465         err = reg_np->ops->set_mode(reg_np, mode);
466     }
467     else
468     {
469         err = -RT_ENOSYS;
470     }
471 
472     rt_hw_spin_unlock(&_regulator_lock.lock);
473 
474     return err;
475 }
476 
rt_regulator_get_mode(struct rt_regulator * reg)477 rt_int32_t rt_regulator_get_mode(struct rt_regulator *reg)
478 {
479     rt_int32_t mode;
480     struct rt_regulator_node *reg_np;
481 
482     if (!reg)
483     {
484         return -RT_EINVAL;
485     }
486 
487     rt_hw_spin_lock(&_regulator_lock.lock);
488 
489     reg_np = reg->reg_np;
490 
491     if (reg_np->ops->get_mode)
492     {
493         mode = reg_np->ops->get_mode(reg_np);
494     }
495     else
496     {
497         mode = -RT_ENOSYS;
498     }
499 
500     rt_hw_spin_unlock(&_regulator_lock.lock);
501 
502     return mode;
503 }
504 
regulator_check_parent(struct rt_regulator_node * reg_np)505 static void regulator_check_parent(struct rt_regulator_node *reg_np)
506 {
507     if (reg_np->parent)
508     {
509         return;
510     }
511     else
512     {
513     #ifdef RT_USING_OFW
514         rt_phandle parent_phandle = 0;
515         struct rt_ofw_node *np = reg_np->dev->ofw_node;
516 
517         while (np)
518         {
519             if (rt_ofw_prop_read_u32(np, "vin-supply", &parent_phandle))
520             {
521                 break;
522             }
523 
524             if (!(np = rt_ofw_find_node_by_phandle(parent_phandle)))
525             {
526                 break;
527             }
528 
529             if (!(reg_np->parent = rt_ofw_data(np)))
530             {
531                 LOG_W("%s parent ofw node = %s not init",
532                         reg_np->supply_name, rt_ofw_node_full_name(np));
533 
534                 rt_ofw_node_put(np);
535                 break;
536             }
537 
538             rt_list_insert_after(&reg_np->parent->children_nodes, &reg_np->list);
539             rt_ofw_node_put(np);
540         }
541     #endif
542     }
543 }
544 
rt_regulator_get(struct rt_device * dev,const char * id)545 struct rt_regulator *rt_regulator_get(struct rt_device *dev, const char *id)
546 {
547     struct rt_regulator *reg = RT_NULL;
548     struct rt_regulator_node *reg_np = RT_NULL;
549 
550     if (!dev || !id)
551     {
552         reg = rt_err_ptr(-RT_EINVAL);
553         goto _end;
554     }
555 
556 #ifdef RT_USING_OFW
557     if (dev->ofw_node)
558     {
559         rt_phandle supply_phandle;
560         struct rt_ofw_node *np = dev->ofw_node;
561         char supply_name[64];
562 
563         rt_snprintf(supply_name, sizeof(supply_name), "%s-supply", id);
564 
565         if (rt_ofw_prop_read_u32(np, supply_name, &supply_phandle))
566         {
567             goto _end;
568         }
569 
570         if (!(np = rt_ofw_find_node_by_phandle(supply_phandle)))
571         {
572             reg = rt_err_ptr(-RT_EIO);
573             goto _end;
574         }
575 
576         if (!rt_ofw_data(np))
577         {
578             rt_platform_ofw_request(np);
579         }
580 
581         reg_np = rt_ofw_data(np);
582         rt_ofw_node_put(np);
583     }
584 #endif
585 
586     if (!reg_np)
587     {
588         reg = rt_err_ptr(-RT_ENOSYS);
589         goto _end;
590     }
591 
592     rt_hw_spin_lock(&_regulator_lock.lock);
593 
594     regulator_check_parent(reg_np);
595 
596     rt_hw_spin_unlock(&_regulator_lock.lock);
597 
598     reg = rt_calloc(1, sizeof(*reg));
599 
600     if (!reg)
601     {
602         reg = rt_err_ptr(-RT_ENOMEM);
603         goto _end;
604     }
605 
606     reg->reg_np = reg_np;
607     rt_ref_get(&reg_np->ref);
608 
609 _end:
610     return reg;
611 }
612 
regulator_release(struct rt_ref * r)613 static void regulator_release(struct rt_ref *r)
614 {
615     struct rt_regulator_node *reg_np = rt_container_of(r, struct rt_regulator_node, ref);
616 
617     rt_regulator_unregister(reg_np);
618 }
619 
rt_regulator_put(struct rt_regulator * reg)620 void rt_regulator_put(struct rt_regulator *reg)
621 {
622     if (!reg)
623     {
624         return;
625     }
626 
627     rt_ref_put(&reg->reg_np->ref, &regulator_release);
628     rt_free(reg);
629 }
630