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