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(®_np->list);
42 rt_list_init(®_np->children_nodes);
43 rt_list_init(®_np->notifier_nodes);
44 rt_ref_init(®_np->ref);
45 rt_atomic_store(®_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(®_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(®_np->children_nodes) || rt_ref_read(®_np->ref) > 1)
92 {
93 err = -RT_EBUSY;
94
95 goto _unlock;
96 }
97
98 reg_np->parent = RT_NULL;
99 rt_list_remove(®_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(¬ifier->list);
123 rt_list_insert_after(®_np->notifier_nodes, ¬ifier->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(¬ifier->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 = ®_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(®_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_np->enabled_count) != 0)
321 {
322 rt_atomic_sub(®->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_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(®_np->parent->children_nodes, ®_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(®_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_np->ref, ®ulator_release);
628 rt_free(reg);
629 }
630