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