blob: 2a5d0f7aea20f83605ca2f027d018e9c2c7d41e6 [file] [log] [blame]
Pascal Paillet79503b82020-12-15 18:26:39 +01001/*
Pascal Pailletc30b6d02022-01-28 13:40:36 +01002 * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
Pascal Paillet79503b82020-12-15 18:26:39 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9#include <limits.h>
10#include <stdint.h>
11#include <string.h>
12
13#include <common/debug.h>
14#include <drivers/delay_timer.h>
15#include <drivers/st/regulator.h>
16#include <libfdt.h>
17
18#define MAX_PROPERTY_LEN 64
19
Yann Gautier3086df82022-11-25 15:29:38 +010020CASSERT(PLAT_NB_RDEVS >= 1U, plat_nb_rdevs_must_be_higher);
21
Pascal Paillet79503b82020-12-15 18:26:39 +010022static struct rdev rdev_array[PLAT_NB_RDEVS];
23
24#define for_each_rdev(rdev) \
Yann Gautier045d8082022-11-25 16:25:46 +010025 for ((rdev) = rdev_array; (rdev) <= &rdev_array[PLAT_NB_RDEVS - 1U]; (rdev)++)
Pascal Paillet79503b82020-12-15 18:26:39 +010026
27#define for_each_registered_rdev(rdev) \
Yann Gautier045d8082022-11-25 16:25:46 +010028 for ((rdev) = rdev_array; \
29 ((rdev) <= &rdev_array[PLAT_NB_RDEVS - 1U]) && ((rdev)->desc != NULL); (rdev)++)
Pascal Paillet79503b82020-12-15 18:26:39 +010030
31static void lock_driver(const struct rdev *rdev)
32{
33 if (rdev->desc->ops->lock != NULL) {
34 rdev->desc->ops->lock(rdev->desc);
35 }
36}
37
38static void unlock_driver(const struct rdev *rdev)
39{
40 if (rdev->desc->ops->unlock != NULL) {
41 rdev->desc->ops->unlock(rdev->desc);
42 }
43}
44
45static struct rdev *regulator_get_by_phandle(int32_t phandle)
46{
47 struct rdev *rdev;
48
49 for_each_registered_rdev(rdev) {
50 if (rdev->phandle == phandle) {
51 return rdev;
52 }
53 }
54
55 WARN("%s: phandle %d not found\n", __func__, phandle);
56 return NULL;
57}
58
59/*
60 * Get a regulator from its node name
61 *
62 * @fdt - pointer to device tree memory
63 * @node_name - name of the node "ldo1"
64 * Return pointer to rdev if succeed, NULL else.
65 */
66struct rdev *regulator_get_by_name(const char *node_name)
67{
68 struct rdev *rdev;
69
70 assert(node_name != NULL);
71 VERBOSE("get %s\n", node_name);
72
73 for_each_registered_rdev(rdev) {
74 if (strcmp(rdev->desc->node_name, node_name) == 0) {
75 return rdev;
76 }
77 }
78
79 WARN("%s: %s not found\n", __func__, node_name);
80 return NULL;
81}
82
83static int32_t get_supply_phandle(const void *fdt, int node, const char *name)
84{
85 const fdt32_t *cuint;
86 int len __unused;
87 int supply_phandle = -FDT_ERR_NOTFOUND;
88 char prop_name[MAX_PROPERTY_LEN];
89
90 len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name);
Yann Gautier909c7082022-11-28 14:55:14 +010091 assert((len >= 0) && (len < (MAX_PROPERTY_LEN - 1)));
Pascal Paillet79503b82020-12-15 18:26:39 +010092
93 cuint = fdt_getprop(fdt, node, prop_name, NULL);
94 if (cuint != NULL) {
95 supply_phandle = fdt32_to_cpu(*cuint);
96 VERBOSE("%s: supplied by %d\n", name, supply_phandle);
97 }
98
99 return supply_phandle;
100}
101
102/*
103 * Get a regulator from a supply name
104 *
105 * @fdt - pointer to device tree memory
106 * @node - offset of the node that contains the supply description
107 * @name - name of the supply "vdd" for "vdd-supply'
108 * Return pointer to rdev if succeed, NULL else.
109 */
110struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name)
111{
112 const int p = get_supply_phandle(fdt, node, name);
113
114 if (p < 0) {
115 return NULL;
116 }
117
118 return regulator_get_by_phandle(p);
119}
120
121static int __regulator_set_state(struct rdev *rdev, bool state)
122{
123 if (rdev->desc->ops->set_state == NULL) {
124 return -ENODEV;
125 }
126
127 return rdev->desc->ops->set_state(rdev->desc, state);
128}
129
130/*
131 * Enable regulator
132 *
133 * @rdev - pointer to rdev struct
134 * Return 0 if succeed, non 0 else.
135 */
136int regulator_enable(struct rdev *rdev)
137{
138 int ret;
139
140 assert(rdev != NULL);
141
142 ret = __regulator_set_state(rdev, STATE_ENABLE);
143
144 udelay(rdev->enable_ramp_delay);
145
146 return ret;
147}
148
149/*
150 * Disable regulator
151 *
152 * @rdev - pointer to rdev struct
153 * Return 0 if succeed, non 0 else.
154 */
155int regulator_disable(struct rdev *rdev)
156{
157 int ret;
158
159 assert(rdev != NULL);
160
Yann Gautiere8f67d32022-11-28 14:57:06 +0100161 if ((rdev->flags & REGUL_ALWAYS_ON) != 0U) {
Pascal Pailletc30b6d02022-01-28 13:40:36 +0100162 return 0;
163 }
164
Pascal Paillet79503b82020-12-15 18:26:39 +0100165 ret = __regulator_set_state(rdev, STATE_DISABLE);
166
167 udelay(rdev->enable_ramp_delay);
168
169 return ret;
170}
171
172/*
173 * Regulator enabled query
174 *
175 * @rdev - pointer to rdev struct
176 * Return 0 if disabled, 1 if enabled, <0 else.
177 */
178int regulator_is_enabled(const struct rdev *rdev)
179{
180 int ret;
181
182 assert(rdev != NULL);
183
184 VERBOSE("%s: is en\n", rdev->desc->node_name);
185
186 if (rdev->desc->ops->get_state == NULL) {
187 return -ENODEV;
188 }
189
190 lock_driver(rdev);
191
192 ret = rdev->desc->ops->get_state(rdev->desc);
193 if (ret < 0) {
194 ERROR("regul %s get state failed: err:%d\n",
195 rdev->desc->node_name, ret);
196 }
197
198 unlock_driver(rdev);
199
200 return ret;
201}
202
203/*
204 * Set regulator voltage
205 *
206 * @rdev - pointer to rdev struct
207 * @mvolt - Target voltage level in millivolt
208 * Return 0 if succeed, non 0 else.
209 */
210int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt)
211{
212 int ret;
213
214 assert(rdev != NULL);
215
216 VERBOSE("%s: set mvolt\n", rdev->desc->node_name);
217
218 if (rdev->desc->ops->set_voltage == NULL) {
219 return -ENODEV;
220 }
221
222 if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) {
223 return -EPERM;
224 }
225
226 lock_driver(rdev);
227
228 ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt);
229 if (ret < 0) {
230 ERROR("regul %s set volt failed: err:%d\n",
231 rdev->desc->node_name, ret);
232 }
233
234 unlock_driver(rdev);
235
236 return ret;
237}
238
239/*
240 * Set regulator min voltage
241 *
242 * @rdev - pointer to rdev struct
243 * Return 0 if succeed, non 0 else.
244 */
245int regulator_set_min_voltage(struct rdev *rdev)
246{
247 return regulator_set_voltage(rdev, rdev->min_mv);
248}
249
250/*
251 * Get regulator voltage
252 *
253 * @rdev - pointer to rdev struct
254 * Return milli volts if succeed, <0 else.
255 */
256int regulator_get_voltage(const struct rdev *rdev)
257{
258 int ret;
259
260 assert(rdev != NULL);
261
262 VERBOSE("%s: get volt\n", rdev->desc->node_name);
263
264 if (rdev->desc->ops->get_voltage == NULL) {
265 return rdev->min_mv;
266 }
267
268 lock_driver(rdev);
269
270 ret = rdev->desc->ops->get_voltage(rdev->desc);
271 if (ret < 0) {
272 ERROR("regul %s get voltage failed: err:%d\n",
273 rdev->desc->node_name, ret);
274 }
275
276 unlock_driver(rdev);
277
278 return ret;
279}
280
281/*
282 * List regulator voltages
283 *
284 * @rdev - pointer to rdev struct
285 * @levels - out: array of supported millitvolt levels from min to max value
286 * @count - out: number of possible millivolt values
287 * Return 0 if succeed, non 0 else.
288 */
289int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count)
290{
291 int ret;
292 size_t n;
293
294 assert(rdev != NULL);
295 assert(levels != NULL);
296 assert(count != NULL);
297
298 VERBOSE("%s: list volt\n", rdev->desc->node_name);
299
300 if (rdev->desc->ops->list_voltages == NULL) {
301 return -ENODEV;
302 }
303
304 lock_driver(rdev);
305
306 ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count);
307
308 unlock_driver(rdev);
309
310 if (ret < 0) {
311 ERROR("regul %s list_voltages failed: err: %d\n",
312 rdev->desc->node_name, ret);
313 return ret;
314 }
315
316 /*
317 * Reduce the possible values depending on min and max from device-tree
318 */
319 n = *count;
320 while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) {
321 n--;
322 }
323
324 /* Verify that max val is a valid value */
325 if (rdev->max_mv != (*levels)[n - 1]) {
326 ERROR("regul %s: max value %u is invalid\n",
327 rdev->desc->node_name, rdev->max_mv);
328 return -EINVAL;
329 }
330
331 while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) {
332 (*levels)++;
333 n--;
334 }
335
336 /* Verify that min is not too high */
337 if (n == 0U) {
338 ERROR("regul %s set min voltage is too high\n",
339 rdev->desc->node_name);
340 return -EINVAL;
341 }
342
343 /* Verify that min val is a valid vlue */
344 if (rdev->min_mv != (*levels)[0U]) {
345 ERROR("regul %s: min value %u is invalid\n",
346 rdev->desc->node_name, rdev->min_mv);
347 return -EINVAL;
348 }
349
350 *count = n;
351
352 VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv);
353
354 return 0;
355}
356
357/*
358 * Get regulator voltages range
359 *
360 * @rdev - pointer to rdev struct
361 * @min_mv - out: min possible millivolt value
362 * @max_mv - out: max possible millivolt value
363 * Return 0 if succeed, non 0 else.
364 */
365void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv)
366{
367 assert(rdev != NULL);
368
369 if (min_mv != NULL) {
370 *min_mv = rdev->min_mv;
371 }
372 if (max_mv != NULL) {
373 *max_mv = rdev->max_mv;
374 }
375}
376
377/*
378 * Set regulator flag
379 *
380 * @rdev - pointer to rdev struct
381 * @flag - flag value to set (eg: REGUL_OCP)
382 * Return 0 if succeed, non 0 else.
383 */
384int regulator_set_flag(struct rdev *rdev, uint16_t flag)
385{
386 int ret;
387
388 /* check that only one bit is set on flag */
389 if (__builtin_popcount(flag) != 1) {
390 return -EINVAL;
391 }
392
393 /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */
394 if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) {
395 rdev->flags |= flag;
396 return 0;
397 }
398
399 if (rdev->desc->ops->set_flag == NULL) {
400 ERROR("%s can not set any flag\n", rdev->desc->node_name);
401 return -ENODEV;
402 }
403
404 lock_driver(rdev);
405
406 ret = rdev->desc->ops->set_flag(rdev->desc, flag);
407
408 unlock_driver(rdev);
409
410 if (ret != 0) {
411 ERROR("%s: could not set flag %d ret=%d\n",
412 rdev->desc->node_name, flag, ret);
413 return ret;
414 }
415
416 rdev->flags |= flag;
417
418 return 0;
419}
420
Pascal Pailletc30b6d02022-01-28 13:40:36 +0100421static int parse_properties(const void *fdt, struct rdev *rdev, int node)
422{
423 int ret;
424
425 if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) {
426 VERBOSE("%s: set regulator-always-on\n", rdev->desc->node_name);
427 ret = regulator_set_flag(rdev, REGUL_ALWAYS_ON);
428 if (ret != 0) {
429 return ret;
430 }
431 }
432
433 return 0;
434}
435
Pascal Paillet79503b82020-12-15 18:26:39 +0100436/*
437 * Parse the device-tree for a regulator
438 *
439 * Read min/max voltage from dt and check its validity
440 * Read the properties, and call the driver to set flags
441 * Read power supply phandle
442 * Read and store low power mode states
443 *
444 * @rdev - pointer to rdev struct
445 * @node - device-tree node offset of the regulator
446 * Return 0 if disabled, 1 if enabled, <0 else.
447 */
448static int parse_dt(struct rdev *rdev, int node)
449{
450 void *fdt;
451 const fdt32_t *cuint;
452 const uint16_t *levels;
453 size_t size;
454 int ret;
455
456 VERBOSE("%s: parse dt\n", rdev->desc->node_name);
457
458 if (fdt_get_address(&fdt) == 0) {
459 return -ENOENT;
460 }
461
462 rdev->phandle = fdt_get_phandle(fdt, node);
463
464 cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
465 if (cuint != NULL) {
466 uint16_t min_mv;
467
468 min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
469 VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv);
470 if (min_mv <= rdev->max_mv) {
471 rdev->min_mv = min_mv;
472 } else {
473 ERROR("%s: min_mv=%d is too high\n",
474 rdev->desc->node_name, (int)min_mv);
475 return -EINVAL;
476 }
477 }
478
479 cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
480 if (cuint != NULL) {
481 uint16_t max_mv;
482
483 max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
484 VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv);
485 if (max_mv >= rdev->min_mv) {
486 rdev->max_mv = max_mv;
487 } else {
488 ERROR("%s: max_mv=%d is too low\n",
489 rdev->desc->node_name, (int)max_mv);
490 return -EINVAL;
491 }
492 }
493
494 /* validate that min and max values can be used */
495 ret = regulator_list_voltages(rdev, &levels, &size);
496 if ((ret != 0) && (ret != -ENODEV)) {
497 return ret;
498 }
499
Pascal Pailletc30b6d02022-01-28 13:40:36 +0100500 ret = parse_properties(fdt, rdev, node);
501 if (ret != 0) {
502 return ret;
503 }
504
Pascal Paillet79503b82020-12-15 18:26:39 +0100505 return 0;
506}
507
508/*
509 * Register a regulator driver in regulator framework.
510 * Initialize voltage range from driver description
511 *
512 * @desc - pointer to the regulator description
513 * @node - device-tree node offset of the regulator
514 * Return 0 if succeed, non 0 else.
515 */
516int regulator_register(const struct regul_description *desc, int node)
517{
518 struct rdev *rdev;
519
520 assert(desc != NULL);
521
522 VERBOSE("register %s\n", desc->node_name);
523
524 for_each_rdev(rdev) {
525 if (rdev->desc == NULL) {
526 break;
527 }
528 }
529
Yann Gautier3086df82022-11-25 15:29:38 +0100530 if (rdev > &rdev_array[PLAT_NB_RDEVS - 1U]) {
Pascal Paillet79503b82020-12-15 18:26:39 +0100531 WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n");
532 return -ENOMEM;
533 }
534
535 rdev->desc = desc;
536 rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay;
537
538 if (rdev->desc->ops->list_voltages != NULL) {
539 int ret;
540 const uint16_t *levels;
541 size_t count;
542
543 lock_driver(rdev);
544
545 ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count);
546
547 unlock_driver(rdev);
548
549 if (ret < 0) {
550 ERROR("regul %s set state failed: err:%d\n",
551 rdev->desc->node_name, ret);
552 return ret;
553 }
554
555 rdev->min_mv = levels[0];
556 rdev->max_mv = levels[count - 1U];
557 } else {
558 rdev->max_mv = UINT16_MAX;
559 }
560
561 return parse_dt(rdev, node);
562}