xref: /rk3399_rockchip-uboot/drivers/power/regulator/regulator-uclass.c (revision 0e1b20c53db7fafc0915a97654ec0ee2071d849c)
1af41e8dbSPrzemyslaw Marczak /*
2af41e8dbSPrzemyslaw Marczak  * Copyright (C) 2014-2015 Samsung Electronics
3af41e8dbSPrzemyslaw Marczak  * Przemyslaw Marczak <p.marczak@samsung.com>
4af41e8dbSPrzemyslaw Marczak  *
5af41e8dbSPrzemyslaw Marczak  * SPDX-License-Identifier:	GPL-2.0+
6af41e8dbSPrzemyslaw Marczak  */
7f15cd4f1SSimon Glass 
8af41e8dbSPrzemyslaw Marczak #include <common.h>
9af41e8dbSPrzemyslaw Marczak #include <errno.h>
10af41e8dbSPrzemyslaw Marczak #include <dm.h>
11af41e8dbSPrzemyslaw Marczak #include <dm/uclass-internal.h>
12af41e8dbSPrzemyslaw Marczak #include <power/pmic.h>
13af41e8dbSPrzemyslaw Marczak #include <power/regulator.h>
14af41e8dbSPrzemyslaw Marczak 
15af41e8dbSPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR;
16af41e8dbSPrzemyslaw Marczak 
17af41e8dbSPrzemyslaw Marczak int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
18af41e8dbSPrzemyslaw Marczak {
19af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
20af41e8dbSPrzemyslaw Marczak 
21af41e8dbSPrzemyslaw Marczak 	*modep = NULL;
22af41e8dbSPrzemyslaw Marczak 
23af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
24af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
25af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
26af41e8dbSPrzemyslaw Marczak 
27af41e8dbSPrzemyslaw Marczak 	*modep = uc_pdata->mode;
28af41e8dbSPrzemyslaw Marczak 	return uc_pdata->mode_count;
29af41e8dbSPrzemyslaw Marczak }
30af41e8dbSPrzemyslaw Marczak 
31af41e8dbSPrzemyslaw Marczak int regulator_get_value(struct udevice *dev)
32af41e8dbSPrzemyslaw Marczak {
33af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
34af41e8dbSPrzemyslaw Marczak 
35af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_value)
36af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
37af41e8dbSPrzemyslaw Marczak 
38af41e8dbSPrzemyslaw Marczak 	return ops->get_value(dev);
39af41e8dbSPrzemyslaw Marczak }
40af41e8dbSPrzemyslaw Marczak 
41af41e8dbSPrzemyslaw Marczak int regulator_set_value(struct udevice *dev, int uV)
42af41e8dbSPrzemyslaw Marczak {
43af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
44eaadcf38SKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
45eaadcf38SKeerthy 
46eaadcf38SKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
47eaadcf38SKeerthy 	if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
48eaadcf38SKeerthy 		return -EINVAL;
49eaadcf38SKeerthy 	if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
50eaadcf38SKeerthy 		return -EINVAL;
51af41e8dbSPrzemyslaw Marczak 
52af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_value)
53af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
54af41e8dbSPrzemyslaw Marczak 
55af41e8dbSPrzemyslaw Marczak 	return ops->set_value(dev, uV);
56af41e8dbSPrzemyslaw Marczak }
57af41e8dbSPrzemyslaw Marczak 
58fbc6dab9SJoseph Chen int regulator_set_suspend_value(struct udevice *dev, int uV)
59fbc6dab9SJoseph Chen {
60fbc6dab9SJoseph Chen 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
61fbc6dab9SJoseph Chen 
62fbc6dab9SJoseph Chen 	if (!ops || !ops->set_suspend_value)
63fbc6dab9SJoseph Chen 		return -ENOSYS;
64fbc6dab9SJoseph Chen 
65fbc6dab9SJoseph Chen 	return ops->set_suspend_value(dev, uV);
66fbc6dab9SJoseph Chen }
67fbc6dab9SJoseph Chen 
682f5d532fSKeerthy /*
692f5d532fSKeerthy  * To be called with at most caution as there is no check
702f5d532fSKeerthy  * before setting the actual voltage value.
712f5d532fSKeerthy  */
722f5d532fSKeerthy int regulator_set_value_force(struct udevice *dev, int uV)
732f5d532fSKeerthy {
742f5d532fSKeerthy 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
752f5d532fSKeerthy 
762f5d532fSKeerthy 	if (!ops || !ops->set_value)
772f5d532fSKeerthy 		return -ENOSYS;
782f5d532fSKeerthy 
792f5d532fSKeerthy 	return ops->set_value(dev, uV);
802f5d532fSKeerthy }
812f5d532fSKeerthy 
82af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev)
83af41e8dbSPrzemyslaw Marczak {
84af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
85af41e8dbSPrzemyslaw Marczak 
86af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_current)
87af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
88af41e8dbSPrzemyslaw Marczak 
89af41e8dbSPrzemyslaw Marczak 	return ops->get_current(dev);
90af41e8dbSPrzemyslaw Marczak }
91af41e8dbSPrzemyslaw Marczak 
92af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA)
93af41e8dbSPrzemyslaw Marczak {
94af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
955483456eSKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
965483456eSKeerthy 
975483456eSKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
985483456eSKeerthy 	if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA)
995483456eSKeerthy 		return -EINVAL;
1005483456eSKeerthy 	if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA)
1015483456eSKeerthy 		return -EINVAL;
102af41e8dbSPrzemyslaw Marczak 
103af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_current)
104af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
105af41e8dbSPrzemyslaw Marczak 
106af41e8dbSPrzemyslaw Marczak 	return ops->set_current(dev, uA);
107af41e8dbSPrzemyslaw Marczak }
108af41e8dbSPrzemyslaw Marczak 
10906bdf600SKeerthy int regulator_get_enable(struct udevice *dev)
110af41e8dbSPrzemyslaw Marczak {
111af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
112af41e8dbSPrzemyslaw Marczak 
113af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_enable)
114af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
115af41e8dbSPrzemyslaw Marczak 
116af41e8dbSPrzemyslaw Marczak 	return ops->get_enable(dev);
117af41e8dbSPrzemyslaw Marczak }
118af41e8dbSPrzemyslaw Marczak 
119af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable)
120af41e8dbSPrzemyslaw Marczak {
121af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
122af41e8dbSPrzemyslaw Marczak 
123af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_enable)
124af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
125af41e8dbSPrzemyslaw Marczak 
126af41e8dbSPrzemyslaw Marczak 	return ops->set_enable(dev, enable);
127af41e8dbSPrzemyslaw Marczak }
128af41e8dbSPrzemyslaw Marczak 
129fbc6dab9SJoseph Chen int regulator_set_suspend_enable(struct udevice *dev, bool enable)
130fbc6dab9SJoseph Chen {
131fbc6dab9SJoseph Chen 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
132fbc6dab9SJoseph Chen 
133fbc6dab9SJoseph Chen 	if (!ops || !ops->set_suspend_enable)
134fbc6dab9SJoseph Chen 		return -ENOSYS;
135fbc6dab9SJoseph Chen 
136fbc6dab9SJoseph Chen 	return ops->set_suspend_enable(dev, enable);
137fbc6dab9SJoseph Chen }
138fbc6dab9SJoseph Chen 
139af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev)
140af41e8dbSPrzemyslaw Marczak {
141af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
142af41e8dbSPrzemyslaw Marczak 
143af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_mode)
144af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
145af41e8dbSPrzemyslaw Marczak 
146af41e8dbSPrzemyslaw Marczak 	return ops->get_mode(dev);
147af41e8dbSPrzemyslaw Marczak }
148af41e8dbSPrzemyslaw Marczak 
149af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode)
150af41e8dbSPrzemyslaw Marczak {
151af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
152af41e8dbSPrzemyslaw Marczak 
153af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_mode)
154af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
155af41e8dbSPrzemyslaw Marczak 
156af41e8dbSPrzemyslaw Marczak 	return ops->set_mode(dev, mode);
157af41e8dbSPrzemyslaw Marczak }
158af41e8dbSPrzemyslaw Marczak 
1593b880757SPrzemyslaw Marczak int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
160af41e8dbSPrzemyslaw Marczak {
161af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
162af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
1633b880757SPrzemyslaw Marczak 	int ret;
164af41e8dbSPrzemyslaw Marczak 
165af41e8dbSPrzemyslaw Marczak 	*devp = NULL;
166af41e8dbSPrzemyslaw Marczak 
1673b880757SPrzemyslaw Marczak 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
1683b880757SPrzemyslaw Marczak 	     ret = uclass_find_next_device(&dev)) {
169422f04b6SSimon Glass 		if (ret) {
170422f04b6SSimon Glass 			debug("regulator %s, ret=%d\n", dev->name, ret);
1713b880757SPrzemyslaw Marczak 			continue;
172422f04b6SSimon Glass 		}
1733b880757SPrzemyslaw Marczak 
174af41e8dbSPrzemyslaw Marczak 		uc_pdata = dev_get_uclass_platdata(dev);
175af41e8dbSPrzemyslaw Marczak 		if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
176af41e8dbSPrzemyslaw Marczak 			continue;
177af41e8dbSPrzemyslaw Marczak 
178af41e8dbSPrzemyslaw Marczak 		return uclass_get_device_tail(dev, 0, devp);
179af41e8dbSPrzemyslaw Marczak 	}
180af41e8dbSPrzemyslaw Marczak 
181422f04b6SSimon Glass 	debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret);
182af41e8dbSPrzemyslaw Marczak 
183af41e8dbSPrzemyslaw Marczak 	return -ENODEV;
184af41e8dbSPrzemyslaw Marczak }
185af41e8dbSPrzemyslaw Marczak 
1863b880757SPrzemyslaw Marczak int regulator_get_by_devname(const char *devname, struct udevice **devp)
187af41e8dbSPrzemyslaw Marczak {
188af41e8dbSPrzemyslaw Marczak 	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
189af41e8dbSPrzemyslaw Marczak }
190af41e8dbSPrzemyslaw Marczak 
1917c816e24SPrzemyslaw Marczak int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
1927c816e24SPrzemyslaw Marczak 				struct udevice **devp)
1937c816e24SPrzemyslaw Marczak {
1947c816e24SPrzemyslaw Marczak 	return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
1957c816e24SPrzemyslaw Marczak 					    supply_name, devp);
1967c816e24SPrzemyslaw Marczak }
1977c816e24SPrzemyslaw Marczak 
1983b55d30fSSimon Glass int regulator_autoset(struct udevice *dev)
199af41e8dbSPrzemyslaw Marczak {
2003b55d30fSSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
2013b55d30fSSimon Glass 	int ret = 0;
202af41e8dbSPrzemyslaw Marczak 
2033b55d30fSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
204fbc6dab9SJoseph Chen 
205fbc6dab9SJoseph Chen 	ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on);
206fbc6dab9SJoseph Chen 	if (!ret && uc_pdata->suspend_on)
207fbc6dab9SJoseph Chen 		ret = regulator_set_suspend_value(dev, uc_pdata->suspend_uV);
208fbc6dab9SJoseph Chen 
2093b55d30fSSimon Glass 	if (!uc_pdata->always_on && !uc_pdata->boot_on)
2103b55d30fSSimon Glass 		return -EMEDIUMTYPE;
211af41e8dbSPrzemyslaw Marczak 
2123b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
2133b55d30fSSimon Glass 		ret = regulator_set_value(dev, uc_pdata->min_uV);
214*0e1b20c5SJoseph Chen 	if (uc_pdata->init_uV > 0)
215*0e1b20c5SJoseph Chen 		ret = regulator_set_value(dev, uc_pdata->init_uV);
2163b55d30fSSimon Glass 	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
2173b55d30fSSimon Glass 		ret = regulator_set_current(dev, uc_pdata->min_uA);
218af41e8dbSPrzemyslaw Marczak 
219af41e8dbSPrzemyslaw Marczak 	if (!ret)
2203b55d30fSSimon Glass 		ret = regulator_set_enable(dev, true);
221af41e8dbSPrzemyslaw Marczak 
222af41e8dbSPrzemyslaw Marczak 	return ret;
223af41e8dbSPrzemyslaw Marczak }
224af41e8dbSPrzemyslaw Marczak 
2253b55d30fSSimon Glass static void regulator_show(struct udevice *dev, int ret)
226af41e8dbSPrzemyslaw Marczak {
227af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
2283b55d30fSSimon Glass 
2293b55d30fSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
2303b55d30fSSimon Glass 
2313b55d30fSSimon Glass 	printf("%s@%s: ", dev->name, uc_pdata->name);
2323b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
2333b55d30fSSimon Glass 		printf("set %d uV", uc_pdata->min_uV);
2343b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
2353b55d30fSSimon Glass 		printf("; set %d uA", uc_pdata->min_uA);
2363b55d30fSSimon Glass 	printf("; enabling");
2373b55d30fSSimon Glass 	if (ret)
2387d577999SSimon Glass 		printf(" (ret: %d)", ret);
2393b55d30fSSimon Glass 	printf("\n");
2403b55d30fSSimon Glass }
2413b55d30fSSimon Glass 
2423b55d30fSSimon Glass int regulator_autoset_by_name(const char *platname, struct udevice **devp)
2433b55d30fSSimon Glass {
244af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
245af41e8dbSPrzemyslaw Marczak 	int ret;
246af41e8dbSPrzemyslaw Marczak 
2473b880757SPrzemyslaw Marczak 	ret = regulator_get_by_platname(platname, &dev);
248af41e8dbSPrzemyslaw Marczak 	if (devp)
249af41e8dbSPrzemyslaw Marczak 		*devp = dev;
2503b55d30fSSimon Glass 	if (ret) {
251422f04b6SSimon Glass 		debug("Can get the regulator: %s (err=%d)\n", platname, ret);
252af41e8dbSPrzemyslaw Marczak 		return ret;
253af41e8dbSPrzemyslaw Marczak 	}
254af41e8dbSPrzemyslaw Marczak 
2553b55d30fSSimon Glass 	return regulator_autoset(dev);
2563b55d30fSSimon Glass }
2573b55d30fSSimon Glass 
2583b880757SPrzemyslaw Marczak int regulator_list_autoset(const char *list_platname[],
259af41e8dbSPrzemyslaw Marczak 			   struct udevice *list_devp[],
260af41e8dbSPrzemyslaw Marczak 			   bool verbose)
261af41e8dbSPrzemyslaw Marczak {
262af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
2633b880757SPrzemyslaw Marczak 	int error = 0, i = 0, ret;
264af41e8dbSPrzemyslaw Marczak 
2653b880757SPrzemyslaw Marczak 	while (list_platname[i]) {
2663b55d30fSSimon Glass 		ret = regulator_autoset_by_name(list_platname[i], &dev);
2673b55d30fSSimon Glass 		if (ret != -EMEDIUMTYPE && verbose)
2683b55d30fSSimon Glass 			regulator_show(dev, ret);
2693b880757SPrzemyslaw Marczak 		if (ret & !error)
2703b880757SPrzemyslaw Marczak 			error = ret;
271af41e8dbSPrzemyslaw Marczak 
2723b880757SPrzemyslaw Marczak 		if (list_devp)
273af41e8dbSPrzemyslaw Marczak 			list_devp[i] = dev;
2743b880757SPrzemyslaw Marczak 
2753b880757SPrzemyslaw Marczak 		i++;
276af41e8dbSPrzemyslaw Marczak 	}
277af41e8dbSPrzemyslaw Marczak 
2783b880757SPrzemyslaw Marczak 	return error;
2793b880757SPrzemyslaw Marczak }
2803b880757SPrzemyslaw Marczak 
2813b880757SPrzemyslaw Marczak static bool regulator_name_is_unique(struct udevice *check_dev,
2823b880757SPrzemyslaw Marczak 				     const char *check_name)
2833b880757SPrzemyslaw Marczak {
2843b880757SPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
2853b880757SPrzemyslaw Marczak 	struct udevice *dev;
2863b880757SPrzemyslaw Marczak 	int check_len = strlen(check_name);
2873b880757SPrzemyslaw Marczak 	int ret;
2883b880757SPrzemyslaw Marczak 	int len;
2893b880757SPrzemyslaw Marczak 
2903b880757SPrzemyslaw Marczak 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
2913b880757SPrzemyslaw Marczak 	     ret = uclass_find_next_device(&dev)) {
2923b880757SPrzemyslaw Marczak 		if (ret || dev == check_dev)
2933b880757SPrzemyslaw Marczak 			continue;
2943b880757SPrzemyslaw Marczak 
2953b880757SPrzemyslaw Marczak 		uc_pdata = dev_get_uclass_platdata(dev);
2963b880757SPrzemyslaw Marczak 		len = strlen(uc_pdata->name);
2973b880757SPrzemyslaw Marczak 		if (len != check_len)
2983b880757SPrzemyslaw Marczak 			continue;
2993b880757SPrzemyslaw Marczak 
3003b880757SPrzemyslaw Marczak 		if (!strcmp(uc_pdata->name, check_name))
3013b880757SPrzemyslaw Marczak 			return false;
3023b880757SPrzemyslaw Marczak 	}
3033b880757SPrzemyslaw Marczak 
3043b880757SPrzemyslaw Marczak 	return true;
305af41e8dbSPrzemyslaw Marczak }
306af41e8dbSPrzemyslaw Marczak 
307af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev)
308af41e8dbSPrzemyslaw Marczak {
309af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
3103b880757SPrzemyslaw Marczak 	const char *property = "regulator-name";
311af41e8dbSPrzemyslaw Marczak 
312af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
313af41e8dbSPrzemyslaw Marczak 
314af41e8dbSPrzemyslaw Marczak 	/* Regulator's mandatory constraint */
315f15cd4f1SSimon Glass 	uc_pdata->name = dev_read_string(dev, property);
316af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata->name) {
317f15cd4f1SSimon Glass 		debug("%s: dev '%s' has no property '%s'\n",
318f15cd4f1SSimon Glass 		      __func__, dev->name, property);
319f15cd4f1SSimon Glass 		uc_pdata->name = dev_read_name(dev);
320cf260011SPeng Fan 		if (!uc_pdata->name)
3213b880757SPrzemyslaw Marczak 			return -EINVAL;
322af41e8dbSPrzemyslaw Marczak 	}
323af41e8dbSPrzemyslaw Marczak 
3243b880757SPrzemyslaw Marczak 	if (regulator_name_is_unique(dev, uc_pdata->name))
325af41e8dbSPrzemyslaw Marczak 		return 0;
3263b880757SPrzemyslaw Marczak 
327f15cd4f1SSimon Glass 	debug("'%s' of dev: '%s', has nonunique value: '%s\n",
3283b880757SPrzemyslaw Marczak 	      property, dev->name, uc_pdata->name);
3293b880757SPrzemyslaw Marczak 
3303b880757SPrzemyslaw Marczak 	return -EINVAL;
331af41e8dbSPrzemyslaw Marczak }
332af41e8dbSPrzemyslaw Marczak 
333af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev)
334af41e8dbSPrzemyslaw Marczak {
335af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
336fbc6dab9SJoseph Chen 	ofnode node;
337af41e8dbSPrzemyslaw Marczak 
338af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
339af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
340af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
341af41e8dbSPrzemyslaw Marczak 
342af41e8dbSPrzemyslaw Marczak 	/* Regulator's optional constraints */
343f15cd4f1SSimon Glass 	uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
344f15cd4f1SSimon Glass 						-ENODATA);
345f15cd4f1SSimon Glass 	uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
346f15cd4f1SSimon Glass 						-ENODATA);
347*0e1b20c5SJoseph Chen 	uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt",
348*0e1b20c5SJoseph Chen 						-ENODATA);
349f15cd4f1SSimon Glass 	uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
350f15cd4f1SSimon Glass 						-ENODATA);
351f15cd4f1SSimon Glass 	uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
352f15cd4f1SSimon Glass 						-ENODATA);
353f15cd4f1SSimon Glass 	uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
354f15cd4f1SSimon Glass 	uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
355af41e8dbSPrzemyslaw Marczak 
356fbc6dab9SJoseph Chen 	node = dev_read_subnode(dev, "regulator-state-mem");
357fbc6dab9SJoseph Chen 	if (ofnode_valid(node)) {
358fbc6dab9SJoseph Chen 		uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend");
359fbc6dab9SJoseph Chen 		if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
360fbc6dab9SJoseph Chen 			uc_pdata->suspend_uV = uc_pdata->max_uA;
361fbc6dab9SJoseph Chen 	} else {
362fbc6dab9SJoseph Chen 		uc_pdata->suspend_on = true;
363fbc6dab9SJoseph Chen 		uc_pdata->suspend_uV = uc_pdata->max_uA;
364fbc6dab9SJoseph Chen 	}
365fbc6dab9SJoseph Chen 
3667837ceabSSimon Glass 	/* Those values are optional (-ENODATA if unset) */
3677837ceabSSimon Glass 	if ((uc_pdata->min_uV != -ENODATA) &&
3687837ceabSSimon Glass 	    (uc_pdata->max_uV != -ENODATA) &&
3697837ceabSSimon Glass 	    (uc_pdata->min_uV == uc_pdata->max_uV))
3707837ceabSSimon Glass 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
3717837ceabSSimon Glass 
3727837ceabSSimon Glass 	/* Those values are optional (-ENODATA if unset) */
3737837ceabSSimon Glass 	if ((uc_pdata->min_uA != -ENODATA) &&
3747837ceabSSimon Glass 	    (uc_pdata->max_uA != -ENODATA) &&
3757837ceabSSimon Glass 	    (uc_pdata->min_uA == uc_pdata->max_uA))
3767837ceabSSimon Glass 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
3777837ceabSSimon Glass 
3782f22a22fSJoseph Chen 	debug("dev.name=%s: min_uV=%d, max_uV=%d, boot-on=%d, always-on=%d, "
3792f22a22fSJoseph Chen 	      "off-in-suspend=%d, suspend_volt=%d\n",
3802f22a22fSJoseph Chen 	      dev->name, uc_pdata->min_uV, uc_pdata->max_uV, uc_pdata->boot_on,
3812f22a22fSJoseph Chen 	      uc_pdata->always_on, !uc_pdata->suspend_on, uc_pdata->suspend_uV);
3822f22a22fSJoseph Chen 
383af41e8dbSPrzemyslaw Marczak 	return 0;
384af41e8dbSPrzemyslaw Marczak }
385af41e8dbSPrzemyslaw Marczak 
386083fc83aSSimon Glass int regulators_enable_boot_on(bool verbose)
387083fc83aSSimon Glass {
388083fc83aSSimon Glass 	struct udevice *dev;
389083fc83aSSimon Glass 	struct uclass *uc;
390083fc83aSSimon Glass 	int ret;
391083fc83aSSimon Glass 
392083fc83aSSimon Glass 	ret = uclass_get(UCLASS_REGULATOR, &uc);
393083fc83aSSimon Glass 	if (ret)
394083fc83aSSimon Glass 		return ret;
395083fc83aSSimon Glass 	for (uclass_first_device(UCLASS_REGULATOR, &dev);
3963f603cbbSSimon Glass 	     dev;
397083fc83aSSimon Glass 	     uclass_next_device(&dev)) {
398083fc83aSSimon Glass 		ret = regulator_autoset(dev);
399d08504d1SSimon Glass 		if (ret == -EMEDIUMTYPE) {
400d08504d1SSimon Glass 			ret = 0;
401083fc83aSSimon Glass 			continue;
402d08504d1SSimon Glass 		}
403083fc83aSSimon Glass 		if (verbose)
404083fc83aSSimon Glass 			regulator_show(dev, ret);
405364809deSSimon Glass 		if (ret == -ENOSYS)
406364809deSSimon Glass 			ret = 0;
407083fc83aSSimon Glass 	}
408083fc83aSSimon Glass 
409083fc83aSSimon Glass 	return ret;
410083fc83aSSimon Glass }
411083fc83aSSimon Glass 
412af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = {
413af41e8dbSPrzemyslaw Marczak 	.id		= UCLASS_REGULATOR,
414af41e8dbSPrzemyslaw Marczak 	.name		= "regulator",
415af41e8dbSPrzemyslaw Marczak 	.post_bind	= regulator_post_bind,
416af41e8dbSPrzemyslaw Marczak 	.pre_probe	= regulator_pre_probe,
417af41e8dbSPrzemyslaw Marczak 	.per_device_platdata_auto_alloc_size =
418af41e8dbSPrzemyslaw Marczak 				sizeof(struct dm_regulator_uclass_platdata),
419af41e8dbSPrzemyslaw Marczak };
420