blob: 94b3ceff7443d5a47c5b92262481cae8be44e47c [file] [log] [blame]
Pascal Paillet79503b82020-12-15 18:26:39 +01001/*
2 * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
3 *
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
159 ret = __regulator_set_state(rdev, STATE_DISABLE);
160
161 udelay(rdev->enable_ramp_delay);
162
163 return ret;
164}
165
166/*
167 * Regulator enabled query
168 *
169 * @rdev - pointer to rdev struct
170 * Return 0 if disabled, 1 if enabled, <0 else.
171 */
172int regulator_is_enabled(const struct rdev *rdev)
173{
174 int ret;
175
176 assert(rdev != NULL);
177
178 VERBOSE("%s: is en\n", rdev->desc->node_name);
179
180 if (rdev->desc->ops->get_state == NULL) {
181 return -ENODEV;
182 }
183
184 lock_driver(rdev);
185
186 ret = rdev->desc->ops->get_state(rdev->desc);
187 if (ret < 0) {
188 ERROR("regul %s get state failed: err:%d\n",
189 rdev->desc->node_name, ret);
190 }
191
192 unlock_driver(rdev);
193
194 return ret;
195}
196
197/*
198 * Set regulator voltage
199 *
200 * @rdev - pointer to rdev struct
201 * @mvolt - Target voltage level in millivolt
202 * Return 0 if succeed, non 0 else.
203 */
204int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt)
205{
206 int ret;
207
208 assert(rdev != NULL);
209
210 VERBOSE("%s: set mvolt\n", rdev->desc->node_name);
211
212 if (rdev->desc->ops->set_voltage == NULL) {
213 return -ENODEV;
214 }
215
216 if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) {
217 return -EPERM;
218 }
219
220 lock_driver(rdev);
221
222 ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt);
223 if (ret < 0) {
224 ERROR("regul %s set volt failed: err:%d\n",
225 rdev->desc->node_name, ret);
226 }
227
228 unlock_driver(rdev);
229
230 return ret;
231}
232
233/*
234 * Set regulator min voltage
235 *
236 * @rdev - pointer to rdev struct
237 * Return 0 if succeed, non 0 else.
238 */
239int regulator_set_min_voltage(struct rdev *rdev)
240{
241 return regulator_set_voltage(rdev, rdev->min_mv);
242}
243
244/*
245 * Get regulator voltage
246 *
247 * @rdev - pointer to rdev struct
248 * Return milli volts if succeed, <0 else.
249 */
250int regulator_get_voltage(const struct rdev *rdev)
251{
252 int ret;
253
254 assert(rdev != NULL);
255
256 VERBOSE("%s: get volt\n", rdev->desc->node_name);
257
258 if (rdev->desc->ops->get_voltage == NULL) {
259 return rdev->min_mv;
260 }
261
262 lock_driver(rdev);
263
264 ret = rdev->desc->ops->get_voltage(rdev->desc);
265 if (ret < 0) {
266 ERROR("regul %s get voltage failed: err:%d\n",
267 rdev->desc->node_name, ret);
268 }
269
270 unlock_driver(rdev);
271
272 return ret;
273}
274
275/*
276 * List regulator voltages
277 *
278 * @rdev - pointer to rdev struct
279 * @levels - out: array of supported millitvolt levels from min to max value
280 * @count - out: number of possible millivolt values
281 * Return 0 if succeed, non 0 else.
282 */
283int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count)
284{
285 int ret;
286 size_t n;
287
288 assert(rdev != NULL);
289 assert(levels != NULL);
290 assert(count != NULL);
291
292 VERBOSE("%s: list volt\n", rdev->desc->node_name);
293
294 if (rdev->desc->ops->list_voltages == NULL) {
295 return -ENODEV;
296 }
297
298 lock_driver(rdev);
299
300 ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count);
301
302 unlock_driver(rdev);
303
304 if (ret < 0) {
305 ERROR("regul %s list_voltages failed: err: %d\n",
306 rdev->desc->node_name, ret);
307 return ret;
308 }
309
310 /*
311 * Reduce the possible values depending on min and max from device-tree
312 */
313 n = *count;
314 while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) {
315 n--;
316 }
317
318 /* Verify that max val is a valid value */
319 if (rdev->max_mv != (*levels)[n - 1]) {
320 ERROR("regul %s: max value %u is invalid\n",
321 rdev->desc->node_name, rdev->max_mv);
322 return -EINVAL;
323 }
324
325 while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) {
326 (*levels)++;
327 n--;
328 }
329
330 /* Verify that min is not too high */
331 if (n == 0U) {
332 ERROR("regul %s set min voltage is too high\n",
333 rdev->desc->node_name);
334 return -EINVAL;
335 }
336
337 /* Verify that min val is a valid vlue */
338 if (rdev->min_mv != (*levels)[0U]) {
339 ERROR("regul %s: min value %u is invalid\n",
340 rdev->desc->node_name, rdev->min_mv);
341 return -EINVAL;
342 }
343
344 *count = n;
345
346 VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv);
347
348 return 0;
349}
350
351/*
352 * Get regulator voltages range
353 *
354 * @rdev - pointer to rdev struct
355 * @min_mv - out: min possible millivolt value
356 * @max_mv - out: max possible millivolt value
357 * Return 0 if succeed, non 0 else.
358 */
359void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv)
360{
361 assert(rdev != NULL);
362
363 if (min_mv != NULL) {
364 *min_mv = rdev->min_mv;
365 }
366 if (max_mv != NULL) {
367 *max_mv = rdev->max_mv;
368 }
369}
370
371/*
372 * Set regulator flag
373 *
374 * @rdev - pointer to rdev struct
375 * @flag - flag value to set (eg: REGUL_OCP)
376 * Return 0 if succeed, non 0 else.
377 */
378int regulator_set_flag(struct rdev *rdev, uint16_t flag)
379{
380 int ret;
381
382 /* check that only one bit is set on flag */
383 if (__builtin_popcount(flag) != 1) {
384 return -EINVAL;
385 }
386
387 /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */
388 if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) {
389 rdev->flags |= flag;
390 return 0;
391 }
392
393 if (rdev->desc->ops->set_flag == NULL) {
394 ERROR("%s can not set any flag\n", rdev->desc->node_name);
395 return -ENODEV;
396 }
397
398 lock_driver(rdev);
399
400 ret = rdev->desc->ops->set_flag(rdev->desc, flag);
401
402 unlock_driver(rdev);
403
404 if (ret != 0) {
405 ERROR("%s: could not set flag %d ret=%d\n",
406 rdev->desc->node_name, flag, ret);
407 return ret;
408 }
409
410 rdev->flags |= flag;
411
412 return 0;
413}
414
415/*
416 * Parse the device-tree for a regulator
417 *
418 * Read min/max voltage from dt and check its validity
419 * Read the properties, and call the driver to set flags
420 * Read power supply phandle
421 * Read and store low power mode states
422 *
423 * @rdev - pointer to rdev struct
424 * @node - device-tree node offset of the regulator
425 * Return 0 if disabled, 1 if enabled, <0 else.
426 */
427static int parse_dt(struct rdev *rdev, int node)
428{
429 void *fdt;
430 const fdt32_t *cuint;
431 const uint16_t *levels;
432 size_t size;
433 int ret;
434
435 VERBOSE("%s: parse dt\n", rdev->desc->node_name);
436
437 if (fdt_get_address(&fdt) == 0) {
438 return -ENOENT;
439 }
440
441 rdev->phandle = fdt_get_phandle(fdt, node);
442
443 cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
444 if (cuint != NULL) {
445 uint16_t min_mv;
446
447 min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
448 VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv);
449 if (min_mv <= rdev->max_mv) {
450 rdev->min_mv = min_mv;
451 } else {
452 ERROR("%s: min_mv=%d is too high\n",
453 rdev->desc->node_name, (int)min_mv);
454 return -EINVAL;
455 }
456 }
457
458 cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
459 if (cuint != NULL) {
460 uint16_t max_mv;
461
462 max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
463 VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv);
464 if (max_mv >= rdev->min_mv) {
465 rdev->max_mv = max_mv;
466 } else {
467 ERROR("%s: max_mv=%d is too low\n",
468 rdev->desc->node_name, (int)max_mv);
469 return -EINVAL;
470 }
471 }
472
473 /* validate that min and max values can be used */
474 ret = regulator_list_voltages(rdev, &levels, &size);
475 if ((ret != 0) && (ret != -ENODEV)) {
476 return ret;
477 }
478
479 return 0;
480}
481
482/*
483 * Register a regulator driver in regulator framework.
484 * Initialize voltage range from driver description
485 *
486 * @desc - pointer to the regulator description
487 * @node - device-tree node offset of the regulator
488 * Return 0 if succeed, non 0 else.
489 */
490int regulator_register(const struct regul_description *desc, int node)
491{
492 struct rdev *rdev;
493
494 assert(desc != NULL);
495
496 VERBOSE("register %s\n", desc->node_name);
497
498 for_each_rdev(rdev) {
499 if (rdev->desc == NULL) {
500 break;
501 }
502 }
503
504 if (rdev == rdev_array + PLAT_NB_RDEVS) {
505 WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n");
506 return -ENOMEM;
507 }
508
509 rdev->desc = desc;
510 rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay;
511
512 if (rdev->desc->ops->list_voltages != NULL) {
513 int ret;
514 const uint16_t *levels;
515 size_t count;
516
517 lock_driver(rdev);
518
519 ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count);
520
521 unlock_driver(rdev);
522
523 if (ret < 0) {
524 ERROR("regul %s set state failed: err:%d\n",
525 rdev->desc->node_name, ret);
526 return ret;
527 }
528
529 rdev->min_mv = levels[0];
530 rdev->max_mv = levels[count - 1U];
531 } else {
532 rdev->max_mv = UINT16_MAX;
533 }
534
535 return parse_dt(rdev, node);
536}