xref: /rk3399_rockchip-uboot/drivers/power/regulator/regulator-uclass.c (revision af41e8db26821ae65fa10c8c4689ccb39043878f)
1*af41e8dbSPrzemyslaw Marczak /*
2*af41e8dbSPrzemyslaw Marczak  * Copyright (C) 2014-2015 Samsung Electronics
3*af41e8dbSPrzemyslaw Marczak  * Przemyslaw Marczak <p.marczak@samsung.com>
4*af41e8dbSPrzemyslaw Marczak  *
5*af41e8dbSPrzemyslaw Marczak  * SPDX-License-Identifier:	GPL-2.0+
6*af41e8dbSPrzemyslaw Marczak  */
7*af41e8dbSPrzemyslaw Marczak #include <common.h>
8*af41e8dbSPrzemyslaw Marczak #include <fdtdec.h>
9*af41e8dbSPrzemyslaw Marczak #include <errno.h>
10*af41e8dbSPrzemyslaw Marczak #include <dm.h>
11*af41e8dbSPrzemyslaw Marczak #include <dm/uclass-internal.h>
12*af41e8dbSPrzemyslaw Marczak #include <power/pmic.h>
13*af41e8dbSPrzemyslaw Marczak #include <power/regulator.h>
14*af41e8dbSPrzemyslaw Marczak 
15*af41e8dbSPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR;
16*af41e8dbSPrzemyslaw Marczak 
17*af41e8dbSPrzemyslaw Marczak int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
18*af41e8dbSPrzemyslaw Marczak {
19*af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
20*af41e8dbSPrzemyslaw Marczak 
21*af41e8dbSPrzemyslaw Marczak 	*modep = NULL;
22*af41e8dbSPrzemyslaw Marczak 
23*af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
24*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
25*af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
26*af41e8dbSPrzemyslaw Marczak 
27*af41e8dbSPrzemyslaw Marczak 	*modep = uc_pdata->mode;
28*af41e8dbSPrzemyslaw Marczak 	return uc_pdata->mode_count;
29*af41e8dbSPrzemyslaw Marczak }
30*af41e8dbSPrzemyslaw Marczak 
31*af41e8dbSPrzemyslaw Marczak int regulator_get_value(struct udevice *dev)
32*af41e8dbSPrzemyslaw Marczak {
33*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
34*af41e8dbSPrzemyslaw Marczak 
35*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_value)
36*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
37*af41e8dbSPrzemyslaw Marczak 
38*af41e8dbSPrzemyslaw Marczak 	return ops->get_value(dev);
39*af41e8dbSPrzemyslaw Marczak }
40*af41e8dbSPrzemyslaw Marczak 
41*af41e8dbSPrzemyslaw Marczak int regulator_set_value(struct udevice *dev, int uV)
42*af41e8dbSPrzemyslaw Marczak {
43*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
44*af41e8dbSPrzemyslaw Marczak 
45*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_value)
46*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
47*af41e8dbSPrzemyslaw Marczak 
48*af41e8dbSPrzemyslaw Marczak 	return ops->set_value(dev, uV);
49*af41e8dbSPrzemyslaw Marczak }
50*af41e8dbSPrzemyslaw Marczak 
51*af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev)
52*af41e8dbSPrzemyslaw Marczak {
53*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
54*af41e8dbSPrzemyslaw Marczak 
55*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_current)
56*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
57*af41e8dbSPrzemyslaw Marczak 
58*af41e8dbSPrzemyslaw Marczak 	return ops->get_current(dev);
59*af41e8dbSPrzemyslaw Marczak }
60*af41e8dbSPrzemyslaw Marczak 
61*af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA)
62*af41e8dbSPrzemyslaw Marczak {
63*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
64*af41e8dbSPrzemyslaw Marczak 
65*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_current)
66*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
67*af41e8dbSPrzemyslaw Marczak 
68*af41e8dbSPrzemyslaw Marczak 	return ops->set_current(dev, uA);
69*af41e8dbSPrzemyslaw Marczak }
70*af41e8dbSPrzemyslaw Marczak 
71*af41e8dbSPrzemyslaw Marczak bool regulator_get_enable(struct udevice *dev)
72*af41e8dbSPrzemyslaw Marczak {
73*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
74*af41e8dbSPrzemyslaw Marczak 
75*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_enable)
76*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
77*af41e8dbSPrzemyslaw Marczak 
78*af41e8dbSPrzemyslaw Marczak 	return ops->get_enable(dev);
79*af41e8dbSPrzemyslaw Marczak }
80*af41e8dbSPrzemyslaw Marczak 
81*af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable)
82*af41e8dbSPrzemyslaw Marczak {
83*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
84*af41e8dbSPrzemyslaw Marczak 
85*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_enable)
86*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
87*af41e8dbSPrzemyslaw Marczak 
88*af41e8dbSPrzemyslaw Marczak 	return ops->set_enable(dev, enable);
89*af41e8dbSPrzemyslaw Marczak }
90*af41e8dbSPrzemyslaw Marczak 
91*af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev)
92*af41e8dbSPrzemyslaw Marczak {
93*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
94*af41e8dbSPrzemyslaw Marczak 
95*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_mode)
96*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
97*af41e8dbSPrzemyslaw Marczak 
98*af41e8dbSPrzemyslaw Marczak 	return ops->get_mode(dev);
99*af41e8dbSPrzemyslaw Marczak }
100*af41e8dbSPrzemyslaw Marczak 
101*af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode)
102*af41e8dbSPrzemyslaw Marczak {
103*af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
104*af41e8dbSPrzemyslaw Marczak 
105*af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_mode)
106*af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
107*af41e8dbSPrzemyslaw Marczak 
108*af41e8dbSPrzemyslaw Marczak 	return ops->set_mode(dev, mode);
109*af41e8dbSPrzemyslaw Marczak }
110*af41e8dbSPrzemyslaw Marczak 
111*af41e8dbSPrzemyslaw Marczak int regulator_by_platname(const char *plat_name, struct udevice **devp)
112*af41e8dbSPrzemyslaw Marczak {
113*af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
114*af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
115*af41e8dbSPrzemyslaw Marczak 
116*af41e8dbSPrzemyslaw Marczak 	*devp = NULL;
117*af41e8dbSPrzemyslaw Marczak 
118*af41e8dbSPrzemyslaw Marczak 	for (uclass_find_first_device(UCLASS_REGULATOR, &dev);
119*af41e8dbSPrzemyslaw Marczak 	     dev;
120*af41e8dbSPrzemyslaw Marczak 	     uclass_find_next_device(&dev)) {
121*af41e8dbSPrzemyslaw Marczak 		uc_pdata = dev_get_uclass_platdata(dev);
122*af41e8dbSPrzemyslaw Marczak 		if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
123*af41e8dbSPrzemyslaw Marczak 			continue;
124*af41e8dbSPrzemyslaw Marczak 
125*af41e8dbSPrzemyslaw Marczak 		return uclass_get_device_tail(dev, 0, devp);
126*af41e8dbSPrzemyslaw Marczak 	}
127*af41e8dbSPrzemyslaw Marczak 
128*af41e8dbSPrzemyslaw Marczak 	debug("%s: can't find: %s\n", __func__, plat_name);
129*af41e8dbSPrzemyslaw Marczak 
130*af41e8dbSPrzemyslaw Marczak 	return -ENODEV;
131*af41e8dbSPrzemyslaw Marczak }
132*af41e8dbSPrzemyslaw Marczak 
133*af41e8dbSPrzemyslaw Marczak int regulator_by_devname(const char *devname, struct udevice **devp)
134*af41e8dbSPrzemyslaw Marczak {
135*af41e8dbSPrzemyslaw Marczak 	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
136*af41e8dbSPrzemyslaw Marczak }
137*af41e8dbSPrzemyslaw Marczak 
138*af41e8dbSPrzemyslaw Marczak static int setting_failed(int ret, bool verbose, const char *fmt, ...)
139*af41e8dbSPrzemyslaw Marczak {
140*af41e8dbSPrzemyslaw Marczak 	va_list args;
141*af41e8dbSPrzemyslaw Marczak 	char buf[64];
142*af41e8dbSPrzemyslaw Marczak 
143*af41e8dbSPrzemyslaw Marczak 	if (verbose == false)
144*af41e8dbSPrzemyslaw Marczak 		return ret;
145*af41e8dbSPrzemyslaw Marczak 
146*af41e8dbSPrzemyslaw Marczak 	va_start(args, fmt);
147*af41e8dbSPrzemyslaw Marczak 	vscnprintf(buf, sizeof(buf), fmt, args);
148*af41e8dbSPrzemyslaw Marczak 	va_end(args);
149*af41e8dbSPrzemyslaw Marczak 
150*af41e8dbSPrzemyslaw Marczak 	printf(buf);
151*af41e8dbSPrzemyslaw Marczak 
152*af41e8dbSPrzemyslaw Marczak 	if (!ret)
153*af41e8dbSPrzemyslaw Marczak 		return 0;
154*af41e8dbSPrzemyslaw Marczak 
155*af41e8dbSPrzemyslaw Marczak 	printf(" (ret: %d)", ret);
156*af41e8dbSPrzemyslaw Marczak 
157*af41e8dbSPrzemyslaw Marczak 	return ret;
158*af41e8dbSPrzemyslaw Marczak }
159*af41e8dbSPrzemyslaw Marczak 
160*af41e8dbSPrzemyslaw Marczak int regulator_by_platname_autoset_and_enable(const char *platname,
161*af41e8dbSPrzemyslaw Marczak 					     struct udevice **devp,
162*af41e8dbSPrzemyslaw Marczak 					     bool verbose)
163*af41e8dbSPrzemyslaw Marczak {
164*af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
165*af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
166*af41e8dbSPrzemyslaw Marczak 	bool v = verbose;
167*af41e8dbSPrzemyslaw Marczak 	int ret;
168*af41e8dbSPrzemyslaw Marczak 
169*af41e8dbSPrzemyslaw Marczak 	if (devp)
170*af41e8dbSPrzemyslaw Marczak 		*devp = NULL;
171*af41e8dbSPrzemyslaw Marczak 
172*af41e8dbSPrzemyslaw Marczak 	ret = regulator_by_platname(platname, &dev);
173*af41e8dbSPrzemyslaw Marczak 	if (ret) {
174*af41e8dbSPrzemyslaw Marczak 		error("Can get the regulator: %s!", platname);
175*af41e8dbSPrzemyslaw Marczak 		return ret;
176*af41e8dbSPrzemyslaw Marczak 	}
177*af41e8dbSPrzemyslaw Marczak 
178*af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
179*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata) {
180*af41e8dbSPrzemyslaw Marczak 		error("Can get the regulator %s uclass platdata!", platname);
181*af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
182*af41e8dbSPrzemyslaw Marczak 	}
183*af41e8dbSPrzemyslaw Marczak 
184*af41e8dbSPrzemyslaw Marczak 	if (v)
185*af41e8dbSPrzemyslaw Marczak 		printf("%s@%s: ", dev->name, uc_pdata->name);
186*af41e8dbSPrzemyslaw Marczak 
187*af41e8dbSPrzemyslaw Marczak 	/* Those values are optional (-ENODATA if unset) */
188*af41e8dbSPrzemyslaw Marczak 	if ((uc_pdata->min_uV != -ENODATA) &&
189*af41e8dbSPrzemyslaw Marczak 	    (uc_pdata->max_uV != -ENODATA) &&
190*af41e8dbSPrzemyslaw Marczak 	    (uc_pdata->min_uV == uc_pdata->max_uV)) {
191*af41e8dbSPrzemyslaw Marczak 		ret = regulator_set_value(dev, uc_pdata->min_uV);
192*af41e8dbSPrzemyslaw Marczak 		if (setting_failed(ret, v, "set %d uV", uc_pdata->min_uV))
193*af41e8dbSPrzemyslaw Marczak 			goto exit;
194*af41e8dbSPrzemyslaw Marczak 	}
195*af41e8dbSPrzemyslaw Marczak 
196*af41e8dbSPrzemyslaw Marczak 	/* Those values are optional (-ENODATA if unset) */
197*af41e8dbSPrzemyslaw Marczak 	if ((uc_pdata->min_uA != -ENODATA) &&
198*af41e8dbSPrzemyslaw Marczak 	    (uc_pdata->max_uA != -ENODATA) &&
199*af41e8dbSPrzemyslaw Marczak 	    (uc_pdata->min_uA == uc_pdata->max_uA)) {
200*af41e8dbSPrzemyslaw Marczak 		ret = regulator_set_current(dev, uc_pdata->min_uA);
201*af41e8dbSPrzemyslaw Marczak 		if (setting_failed(ret, v, "; set %d uA", uc_pdata->min_uA))
202*af41e8dbSPrzemyslaw Marczak 			goto exit;
203*af41e8dbSPrzemyslaw Marczak 	}
204*af41e8dbSPrzemyslaw Marczak 
205*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata->always_on && !uc_pdata->boot_on)
206*af41e8dbSPrzemyslaw Marczak 		goto retdev;
207*af41e8dbSPrzemyslaw Marczak 
208*af41e8dbSPrzemyslaw Marczak 	ret = regulator_set_enable(dev, true);
209*af41e8dbSPrzemyslaw Marczak 	if (setting_failed(ret, v, "; enabling", uc_pdata->min_uA))
210*af41e8dbSPrzemyslaw Marczak 		goto exit;
211*af41e8dbSPrzemyslaw Marczak 
212*af41e8dbSPrzemyslaw Marczak retdev:
213*af41e8dbSPrzemyslaw Marczak 	if (devp)
214*af41e8dbSPrzemyslaw Marczak 		*devp = dev;
215*af41e8dbSPrzemyslaw Marczak exit:
216*af41e8dbSPrzemyslaw Marczak 	if (v)
217*af41e8dbSPrzemyslaw Marczak 		printf("\n");
218*af41e8dbSPrzemyslaw Marczak 	return ret;
219*af41e8dbSPrzemyslaw Marczak }
220*af41e8dbSPrzemyslaw Marczak 
221*af41e8dbSPrzemyslaw Marczak int regulator_by_platname_list_autoset_and_enable(const char *list_platname[],
222*af41e8dbSPrzemyslaw Marczak 						  int list_entries,
223*af41e8dbSPrzemyslaw Marczak 						  struct udevice *list_devp[],
224*af41e8dbSPrzemyslaw Marczak 						  bool verbose)
225*af41e8dbSPrzemyslaw Marczak {
226*af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
227*af41e8dbSPrzemyslaw Marczak 	int i, ret, success = 0;
228*af41e8dbSPrzemyslaw Marczak 
229*af41e8dbSPrzemyslaw Marczak 	for (i = 0; i < list_entries; i++) {
230*af41e8dbSPrzemyslaw Marczak 		ret = regulator_autoset(list_platname[i], &dev, verbose);
231*af41e8dbSPrzemyslaw Marczak 		if (!ret)
232*af41e8dbSPrzemyslaw Marczak 			success++;
233*af41e8dbSPrzemyslaw Marczak 
234*af41e8dbSPrzemyslaw Marczak 		if (!list_devp)
235*af41e8dbSPrzemyslaw Marczak 			continue;
236*af41e8dbSPrzemyslaw Marczak 
237*af41e8dbSPrzemyslaw Marczak 		if (ret)
238*af41e8dbSPrzemyslaw Marczak 			list_devp[i] = NULL;
239*af41e8dbSPrzemyslaw Marczak 		else
240*af41e8dbSPrzemyslaw Marczak 			list_devp[i] = dev;
241*af41e8dbSPrzemyslaw Marczak 	}
242*af41e8dbSPrzemyslaw Marczak 
243*af41e8dbSPrzemyslaw Marczak 	return (success != list_entries);
244*af41e8dbSPrzemyslaw Marczak }
245*af41e8dbSPrzemyslaw Marczak 
246*af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev)
247*af41e8dbSPrzemyslaw Marczak {
248*af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
249*af41e8dbSPrzemyslaw Marczak 	int offset = dev->of_offset;
250*af41e8dbSPrzemyslaw Marczak 	const void *blob = gd->fdt_blob;
251*af41e8dbSPrzemyslaw Marczak 
252*af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
253*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
254*af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
255*af41e8dbSPrzemyslaw Marczak 
256*af41e8dbSPrzemyslaw Marczak 	/* Regulator's mandatory constraint */
257*af41e8dbSPrzemyslaw Marczak 	uc_pdata->name = fdt_getprop(blob, offset, "regulator-name", NULL);
258*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata->name) {
259*af41e8dbSPrzemyslaw Marczak 		debug("%s: dev: %s has no property 'regulator-name'\n",
260*af41e8dbSPrzemyslaw Marczak 		      __func__, dev->name);
261*af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
262*af41e8dbSPrzemyslaw Marczak 	}
263*af41e8dbSPrzemyslaw Marczak 
264*af41e8dbSPrzemyslaw Marczak 	return 0;
265*af41e8dbSPrzemyslaw Marczak }
266*af41e8dbSPrzemyslaw Marczak 
267*af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev)
268*af41e8dbSPrzemyslaw Marczak {
269*af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
270*af41e8dbSPrzemyslaw Marczak 	int offset = dev->of_offset;
271*af41e8dbSPrzemyslaw Marczak 
272*af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
273*af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
274*af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
275*af41e8dbSPrzemyslaw Marczak 
276*af41e8dbSPrzemyslaw Marczak 	/* Regulator's optional constraints */
277*af41e8dbSPrzemyslaw Marczak 	uc_pdata->min_uV = fdtdec_get_int(gd->fdt_blob, offset,
278*af41e8dbSPrzemyslaw Marczak 					  "regulator-min-microvolt", -ENODATA);
279*af41e8dbSPrzemyslaw Marczak 	uc_pdata->max_uV = fdtdec_get_int(gd->fdt_blob, offset,
280*af41e8dbSPrzemyslaw Marczak 					  "regulator-max-microvolt", -ENODATA);
281*af41e8dbSPrzemyslaw Marczak 	uc_pdata->min_uA = fdtdec_get_int(gd->fdt_blob, offset,
282*af41e8dbSPrzemyslaw Marczak 					  "regulator-min-microamp", -ENODATA);
283*af41e8dbSPrzemyslaw Marczak 	uc_pdata->max_uA = fdtdec_get_int(gd->fdt_blob, offset,
284*af41e8dbSPrzemyslaw Marczak 					  "regulator-max-microamp", -ENODATA);
285*af41e8dbSPrzemyslaw Marczak 	uc_pdata->always_on = fdtdec_get_bool(gd->fdt_blob, offset,
286*af41e8dbSPrzemyslaw Marczak 					      "regulator-always-on");
287*af41e8dbSPrzemyslaw Marczak 	uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
288*af41e8dbSPrzemyslaw Marczak 					    "regulator-boot-on");
289*af41e8dbSPrzemyslaw Marczak 
290*af41e8dbSPrzemyslaw Marczak 	return 0;
291*af41e8dbSPrzemyslaw Marczak }
292*af41e8dbSPrzemyslaw Marczak 
293*af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = {
294*af41e8dbSPrzemyslaw Marczak 	.id		= UCLASS_REGULATOR,
295*af41e8dbSPrzemyslaw Marczak 	.name		= "regulator",
296*af41e8dbSPrzemyslaw Marczak 	.post_bind	= regulator_post_bind,
297*af41e8dbSPrzemyslaw Marczak 	.pre_probe	= regulator_pre_probe,
298*af41e8dbSPrzemyslaw Marczak 	.per_device_platdata_auto_alloc_size =
299*af41e8dbSPrzemyslaw Marczak 				sizeof(struct dm_regulator_uclass_platdata),
300*af41e8dbSPrzemyslaw Marczak };
301