xref: /rk3399_rockchip-uboot/drivers/power/regulator/regulator-uclass.c (revision 34483cf7020bb195dfb6d239f73edde86fcd812e)
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;
45b29e2b63SJoseph Chen 	u32 old_uV = -ENODATA, us;
46b29e2b63SJoseph Chen 	int ret;
47eaadcf38SKeerthy 
48eaadcf38SKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
49eaadcf38SKeerthy 	if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
50eaadcf38SKeerthy 		return -EINVAL;
51eaadcf38SKeerthy 	if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
52eaadcf38SKeerthy 		return -EINVAL;
53af41e8dbSPrzemyslaw Marczak 
54af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_value)
55af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
56af41e8dbSPrzemyslaw Marczak 
57b29e2b63SJoseph Chen 	if (uc_pdata->ramp_delay != -ENODATA) {
58b29e2b63SJoseph Chen 		if (!ops->get_value)
59b29e2b63SJoseph Chen 			return -ENOSYS;
60b29e2b63SJoseph Chen 		old_uV = ops->get_value(dev);
61b29e2b63SJoseph Chen 		if (old_uV < 0)
62b29e2b63SJoseph Chen 			return -EINVAL;
63b29e2b63SJoseph Chen 	}
64b29e2b63SJoseph Chen 
65b29e2b63SJoseph Chen 	ret = ops->set_value(dev, uV);
66b29e2b63SJoseph Chen 
67b29e2b63SJoseph Chen 	if (!ret && (old_uV != -ENODATA) && (old_uV != uV)) {
68b29e2b63SJoseph Chen 		us = DIV_ROUND_UP(abs(uV - old_uV), uc_pdata->ramp_delay);
69b29e2b63SJoseph Chen 		udelay(us);
70b29e2b63SJoseph Chen 		debug("%s: ramp=%d, old_uV=%d, uV=%d, us=%d\n",
71b29e2b63SJoseph Chen 		      uc_pdata->name, uc_pdata->ramp_delay, old_uV, uV, us);
72b29e2b63SJoseph Chen 	}
73b29e2b63SJoseph Chen 
74b29e2b63SJoseph Chen 	return ret;
75af41e8dbSPrzemyslaw Marczak }
76af41e8dbSPrzemyslaw Marczak 
77fbc6dab9SJoseph Chen int regulator_set_suspend_value(struct udevice *dev, int uV)
78fbc6dab9SJoseph Chen {
79fbc6dab9SJoseph Chen 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
80fbc6dab9SJoseph Chen 
81fbc6dab9SJoseph Chen 	if (!ops || !ops->set_suspend_value)
82fbc6dab9SJoseph Chen 		return -ENOSYS;
83fbc6dab9SJoseph Chen 
84fbc6dab9SJoseph Chen 	return ops->set_suspend_value(dev, uV);
85fbc6dab9SJoseph Chen }
86fbc6dab9SJoseph Chen 
872f5d532fSKeerthy /*
882f5d532fSKeerthy  * To be called with at most caution as there is no check
892f5d532fSKeerthy  * before setting the actual voltage value.
902f5d532fSKeerthy  */
912f5d532fSKeerthy int regulator_set_value_force(struct udevice *dev, int uV)
922f5d532fSKeerthy {
932f5d532fSKeerthy 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
942f5d532fSKeerthy 
952f5d532fSKeerthy 	if (!ops || !ops->set_value)
962f5d532fSKeerthy 		return -ENOSYS;
972f5d532fSKeerthy 
982f5d532fSKeerthy 	return ops->set_value(dev, uV);
992f5d532fSKeerthy }
1002f5d532fSKeerthy 
101af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev)
102af41e8dbSPrzemyslaw Marczak {
103af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
104af41e8dbSPrzemyslaw Marczak 
105af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_current)
106af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
107af41e8dbSPrzemyslaw Marczak 
108af41e8dbSPrzemyslaw Marczak 	return ops->get_current(dev);
109af41e8dbSPrzemyslaw Marczak }
110af41e8dbSPrzemyslaw Marczak 
111af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA)
112af41e8dbSPrzemyslaw Marczak {
113af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
1145483456eSKeerthy 	struct dm_regulator_uclass_platdata *uc_pdata;
1155483456eSKeerthy 
1165483456eSKeerthy 	uc_pdata = dev_get_uclass_platdata(dev);
1175483456eSKeerthy 	if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA)
1185483456eSKeerthy 		return -EINVAL;
1195483456eSKeerthy 	if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA)
1205483456eSKeerthy 		return -EINVAL;
121af41e8dbSPrzemyslaw Marczak 
122af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_current)
123af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
124af41e8dbSPrzemyslaw Marczak 
125af41e8dbSPrzemyslaw Marczak 	return ops->set_current(dev, uA);
126af41e8dbSPrzemyslaw Marczak }
127af41e8dbSPrzemyslaw Marczak 
12806bdf600SKeerthy int regulator_get_enable(struct udevice *dev)
129af41e8dbSPrzemyslaw Marczak {
130af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
131af41e8dbSPrzemyslaw Marczak 
132af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_enable)
133af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
134af41e8dbSPrzemyslaw Marczak 
135af41e8dbSPrzemyslaw Marczak 	return ops->get_enable(dev);
136af41e8dbSPrzemyslaw Marczak }
137af41e8dbSPrzemyslaw Marczak 
138af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable)
139af41e8dbSPrzemyslaw Marczak {
140af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
141af41e8dbSPrzemyslaw Marczak 
142af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_enable)
143af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
144af41e8dbSPrzemyslaw Marczak 
145af41e8dbSPrzemyslaw Marczak 	return ops->set_enable(dev, enable);
146af41e8dbSPrzemyslaw Marczak }
147af41e8dbSPrzemyslaw Marczak 
148fbc6dab9SJoseph Chen int regulator_set_suspend_enable(struct udevice *dev, bool enable)
149fbc6dab9SJoseph Chen {
150fbc6dab9SJoseph Chen 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
151fbc6dab9SJoseph Chen 
152fbc6dab9SJoseph Chen 	if (!ops || !ops->set_suspend_enable)
153fbc6dab9SJoseph Chen 		return -ENOSYS;
154fbc6dab9SJoseph Chen 
155fbc6dab9SJoseph Chen 	return ops->set_suspend_enable(dev, enable);
156fbc6dab9SJoseph Chen }
157fbc6dab9SJoseph Chen 
158b29e2b63SJoseph Chen int regulator_set_ramp_delay(struct udevice *dev, u32 ramp_delay)
159b29e2b63SJoseph Chen {
160b29e2b63SJoseph Chen 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
161b29e2b63SJoseph Chen 
162b29e2b63SJoseph Chen 	if (!ops || !ops->set_ramp_delay)
163b29e2b63SJoseph Chen 		return -ENOSYS;
164b29e2b63SJoseph Chen 
165b29e2b63SJoseph Chen 	return ops->set_ramp_delay(dev, ramp_delay);
166b29e2b63SJoseph Chen }
167b29e2b63SJoseph Chen 
168af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev)
169af41e8dbSPrzemyslaw Marczak {
170af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
171af41e8dbSPrzemyslaw Marczak 
172af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->get_mode)
173af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
174af41e8dbSPrzemyslaw Marczak 
175af41e8dbSPrzemyslaw Marczak 	return ops->get_mode(dev);
176af41e8dbSPrzemyslaw Marczak }
177af41e8dbSPrzemyslaw Marczak 
178af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode)
179af41e8dbSPrzemyslaw Marczak {
180af41e8dbSPrzemyslaw Marczak 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
181af41e8dbSPrzemyslaw Marczak 
182af41e8dbSPrzemyslaw Marczak 	if (!ops || !ops->set_mode)
183af41e8dbSPrzemyslaw Marczak 		return -ENOSYS;
184af41e8dbSPrzemyslaw Marczak 
185af41e8dbSPrzemyslaw Marczak 	return ops->set_mode(dev, mode);
186af41e8dbSPrzemyslaw Marczak }
187af41e8dbSPrzemyslaw Marczak 
1883b880757SPrzemyslaw Marczak int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
189af41e8dbSPrzemyslaw Marczak {
190af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
191af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
1923b880757SPrzemyslaw Marczak 	int ret;
193af41e8dbSPrzemyslaw Marczak 
194af41e8dbSPrzemyslaw Marczak 	*devp = NULL;
195af41e8dbSPrzemyslaw Marczak 
1963b880757SPrzemyslaw Marczak 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
1973b880757SPrzemyslaw Marczak 	     ret = uclass_find_next_device(&dev)) {
198422f04b6SSimon Glass 		if (ret) {
199422f04b6SSimon Glass 			debug("regulator %s, ret=%d\n", dev->name, ret);
2003b880757SPrzemyslaw Marczak 			continue;
201422f04b6SSimon Glass 		}
2023b880757SPrzemyslaw Marczak 
203af41e8dbSPrzemyslaw Marczak 		uc_pdata = dev_get_uclass_platdata(dev);
204af41e8dbSPrzemyslaw Marczak 		if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
205af41e8dbSPrzemyslaw Marczak 			continue;
206af41e8dbSPrzemyslaw Marczak 
207af41e8dbSPrzemyslaw Marczak 		return uclass_get_device_tail(dev, 0, devp);
208af41e8dbSPrzemyslaw Marczak 	}
209af41e8dbSPrzemyslaw Marczak 
210422f04b6SSimon Glass 	debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret);
211af41e8dbSPrzemyslaw Marczak 
212af41e8dbSPrzemyslaw Marczak 	return -ENODEV;
213af41e8dbSPrzemyslaw Marczak }
214af41e8dbSPrzemyslaw Marczak 
2153b880757SPrzemyslaw Marczak int regulator_get_by_devname(const char *devname, struct udevice **devp)
216af41e8dbSPrzemyslaw Marczak {
217af41e8dbSPrzemyslaw Marczak 	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
218af41e8dbSPrzemyslaw Marczak }
219af41e8dbSPrzemyslaw Marczak 
2207c816e24SPrzemyslaw Marczak int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
2217c816e24SPrzemyslaw Marczak 				struct udevice **devp)
2227c816e24SPrzemyslaw Marczak {
2237c816e24SPrzemyslaw Marczak 	return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
2247c816e24SPrzemyslaw Marczak 					    supply_name, devp);
2257c816e24SPrzemyslaw Marczak }
2267c816e24SPrzemyslaw Marczak 
2273b55d30fSSimon Glass int regulator_autoset(struct udevice *dev)
228af41e8dbSPrzemyslaw Marczak {
2293b55d30fSSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
2303b55d30fSSimon Glass 	int ret = 0;
231af41e8dbSPrzemyslaw Marczak 
2323b55d30fSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
233fbc6dab9SJoseph Chen 
234b29e2b63SJoseph Chen 	if (uc_pdata->ramp_delay != -ENODATA)
235b29e2b63SJoseph Chen 		regulator_set_ramp_delay(dev, uc_pdata->ramp_delay);
236b29e2b63SJoseph Chen 
237*34483cf7SJoseph Chen 	/*
238*34483cf7SJoseph Chen 	 * Suspend configure is not necessary and should not influence normal
239*34483cf7SJoseph Chen 	 * configure, so that we set "ret=0" even failed here.
240*34483cf7SJoseph Chen 	 */
241fbc6dab9SJoseph Chen 	ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on);
242fbc6dab9SJoseph Chen 	if (!ret && uc_pdata->suspend_on)
243*34483cf7SJoseph Chen 		regulator_set_suspend_value(dev, uc_pdata->suspend_uV);
244*34483cf7SJoseph Chen 	else
245*34483cf7SJoseph Chen 		ret = 0;
246fbc6dab9SJoseph Chen 
2473b55d30fSSimon Glass 	if (!uc_pdata->always_on && !uc_pdata->boot_on)
2483b55d30fSSimon Glass 		return -EMEDIUMTYPE;
249af41e8dbSPrzemyslaw Marczak 
2503b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
2513b55d30fSSimon Glass 		ret = regulator_set_value(dev, uc_pdata->min_uV);
2520e1b20c5SJoseph Chen 	if (uc_pdata->init_uV > 0)
2530e1b20c5SJoseph Chen 		ret = regulator_set_value(dev, uc_pdata->init_uV);
2543b55d30fSSimon Glass 	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
2553b55d30fSSimon Glass 		ret = regulator_set_current(dev, uc_pdata->min_uA);
256af41e8dbSPrzemyslaw Marczak 
257af41e8dbSPrzemyslaw Marczak 	if (!ret)
2583b55d30fSSimon Glass 		ret = regulator_set_enable(dev, true);
259af41e8dbSPrzemyslaw Marczak 
260af41e8dbSPrzemyslaw Marczak 	return ret;
261af41e8dbSPrzemyslaw Marczak }
262af41e8dbSPrzemyslaw Marczak 
2633b55d30fSSimon Glass static void regulator_show(struct udevice *dev, int ret)
264af41e8dbSPrzemyslaw Marczak {
265af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
2663b55d30fSSimon Glass 
2673b55d30fSSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
2683b55d30fSSimon Glass 
2693b55d30fSSimon Glass 	printf("%s@%s: ", dev->name, uc_pdata->name);
2703b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
2713b55d30fSSimon Glass 		printf("set %d uV", uc_pdata->min_uV);
2723b55d30fSSimon Glass 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
2733b55d30fSSimon Glass 		printf("; set %d uA", uc_pdata->min_uA);
2743b55d30fSSimon Glass 	printf("; enabling");
2753b55d30fSSimon Glass 	if (ret)
2767d577999SSimon Glass 		printf(" (ret: %d)", ret);
2773b55d30fSSimon Glass 	printf("\n");
2783b55d30fSSimon Glass }
2793b55d30fSSimon Glass 
2803b55d30fSSimon Glass int regulator_autoset_by_name(const char *platname, struct udevice **devp)
2813b55d30fSSimon Glass {
282af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
283af41e8dbSPrzemyslaw Marczak 	int ret;
284af41e8dbSPrzemyslaw Marczak 
2853b880757SPrzemyslaw Marczak 	ret = regulator_get_by_platname(platname, &dev);
286af41e8dbSPrzemyslaw Marczak 	if (devp)
287af41e8dbSPrzemyslaw Marczak 		*devp = dev;
2883b55d30fSSimon Glass 	if (ret) {
289422f04b6SSimon Glass 		debug("Can get the regulator: %s (err=%d)\n", platname, ret);
290af41e8dbSPrzemyslaw Marczak 		return ret;
291af41e8dbSPrzemyslaw Marczak 	}
292af41e8dbSPrzemyslaw Marczak 
2933b55d30fSSimon Glass 	return regulator_autoset(dev);
2943b55d30fSSimon Glass }
2953b55d30fSSimon Glass 
2963b880757SPrzemyslaw Marczak int regulator_list_autoset(const char *list_platname[],
297af41e8dbSPrzemyslaw Marczak 			   struct udevice *list_devp[],
298af41e8dbSPrzemyslaw Marczak 			   bool verbose)
299af41e8dbSPrzemyslaw Marczak {
300af41e8dbSPrzemyslaw Marczak 	struct udevice *dev;
3013b880757SPrzemyslaw Marczak 	int error = 0, i = 0, ret;
302af41e8dbSPrzemyslaw Marczak 
3033b880757SPrzemyslaw Marczak 	while (list_platname[i]) {
3043b55d30fSSimon Glass 		ret = regulator_autoset_by_name(list_platname[i], &dev);
3053b55d30fSSimon Glass 		if (ret != -EMEDIUMTYPE && verbose)
3063b55d30fSSimon Glass 			regulator_show(dev, ret);
3073b880757SPrzemyslaw Marczak 		if (ret & !error)
3083b880757SPrzemyslaw Marczak 			error = ret;
309af41e8dbSPrzemyslaw Marczak 
3103b880757SPrzemyslaw Marczak 		if (list_devp)
311af41e8dbSPrzemyslaw Marczak 			list_devp[i] = dev;
3123b880757SPrzemyslaw Marczak 
3133b880757SPrzemyslaw Marczak 		i++;
314af41e8dbSPrzemyslaw Marczak 	}
315af41e8dbSPrzemyslaw Marczak 
3163b880757SPrzemyslaw Marczak 	return error;
3173b880757SPrzemyslaw Marczak }
3183b880757SPrzemyslaw Marczak 
3193b880757SPrzemyslaw Marczak static bool regulator_name_is_unique(struct udevice *check_dev,
3203b880757SPrzemyslaw Marczak 				     const char *check_name)
3213b880757SPrzemyslaw Marczak {
3223b880757SPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
3233b880757SPrzemyslaw Marczak 	struct udevice *dev;
3243b880757SPrzemyslaw Marczak 	int check_len = strlen(check_name);
3253b880757SPrzemyslaw Marczak 	int ret;
3263b880757SPrzemyslaw Marczak 	int len;
3273b880757SPrzemyslaw Marczak 
3283b880757SPrzemyslaw Marczak 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
3293b880757SPrzemyslaw Marczak 	     ret = uclass_find_next_device(&dev)) {
3303b880757SPrzemyslaw Marczak 		if (ret || dev == check_dev)
3313b880757SPrzemyslaw Marczak 			continue;
3323b880757SPrzemyslaw Marczak 
3333b880757SPrzemyslaw Marczak 		uc_pdata = dev_get_uclass_platdata(dev);
3343b880757SPrzemyslaw Marczak 		len = strlen(uc_pdata->name);
3353b880757SPrzemyslaw Marczak 		if (len != check_len)
3363b880757SPrzemyslaw Marczak 			continue;
3373b880757SPrzemyslaw Marczak 
3383b880757SPrzemyslaw Marczak 		if (!strcmp(uc_pdata->name, check_name))
3393b880757SPrzemyslaw Marczak 			return false;
3403b880757SPrzemyslaw Marczak 	}
3413b880757SPrzemyslaw Marczak 
3423b880757SPrzemyslaw Marczak 	return true;
343af41e8dbSPrzemyslaw Marczak }
344af41e8dbSPrzemyslaw Marczak 
345af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev)
346af41e8dbSPrzemyslaw Marczak {
347af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
3483b880757SPrzemyslaw Marczak 	const char *property = "regulator-name";
349af41e8dbSPrzemyslaw Marczak 
350af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
351af41e8dbSPrzemyslaw Marczak 
352af41e8dbSPrzemyslaw Marczak 	/* Regulator's mandatory constraint */
353f15cd4f1SSimon Glass 	uc_pdata->name = dev_read_string(dev, property);
354af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata->name) {
355f15cd4f1SSimon Glass 		debug("%s: dev '%s' has no property '%s'\n",
356f15cd4f1SSimon Glass 		      __func__, dev->name, property);
357f15cd4f1SSimon Glass 		uc_pdata->name = dev_read_name(dev);
358cf260011SPeng Fan 		if (!uc_pdata->name)
3593b880757SPrzemyslaw Marczak 			return -EINVAL;
360af41e8dbSPrzemyslaw Marczak 	}
361af41e8dbSPrzemyslaw Marczak 
3623b880757SPrzemyslaw Marczak 	if (regulator_name_is_unique(dev, uc_pdata->name))
363af41e8dbSPrzemyslaw Marczak 		return 0;
3643b880757SPrzemyslaw Marczak 
365f15cd4f1SSimon Glass 	debug("'%s' of dev: '%s', has nonunique value: '%s\n",
3663b880757SPrzemyslaw Marczak 	      property, dev->name, uc_pdata->name);
3673b880757SPrzemyslaw Marczak 
3683b880757SPrzemyslaw Marczak 	return -EINVAL;
369af41e8dbSPrzemyslaw Marczak }
370af41e8dbSPrzemyslaw Marczak 
371af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev)
372af41e8dbSPrzemyslaw Marczak {
373af41e8dbSPrzemyslaw Marczak 	struct dm_regulator_uclass_platdata *uc_pdata;
374fbc6dab9SJoseph Chen 	ofnode node;
375af41e8dbSPrzemyslaw Marczak 
376af41e8dbSPrzemyslaw Marczak 	uc_pdata = dev_get_uclass_platdata(dev);
377af41e8dbSPrzemyslaw Marczak 	if (!uc_pdata)
378af41e8dbSPrzemyslaw Marczak 		return -ENXIO;
379af41e8dbSPrzemyslaw Marczak 
380af41e8dbSPrzemyslaw Marczak 	/* Regulator's optional constraints */
381f15cd4f1SSimon Glass 	uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
382f15cd4f1SSimon Glass 						-ENODATA);
383f15cd4f1SSimon Glass 	uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
384f15cd4f1SSimon Glass 						-ENODATA);
3850e1b20c5SJoseph Chen 	uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt",
3860e1b20c5SJoseph Chen 						-ENODATA);
387f15cd4f1SSimon Glass 	uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
388f15cd4f1SSimon Glass 						-ENODATA);
389f15cd4f1SSimon Glass 	uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
390f15cd4f1SSimon Glass 						-ENODATA);
391f15cd4f1SSimon Glass 	uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
392f15cd4f1SSimon Glass 	uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
393b29e2b63SJoseph Chen 	uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
394b29e2b63SJoseph Chen 						    -ENODATA);
395fbc6dab9SJoseph Chen 	node = dev_read_subnode(dev, "regulator-state-mem");
396fbc6dab9SJoseph Chen 	if (ofnode_valid(node)) {
397fbc6dab9SJoseph Chen 		uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend");
398fbc6dab9SJoseph Chen 		if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
399fbc6dab9SJoseph Chen 			uc_pdata->suspend_uV = uc_pdata->max_uA;
400fbc6dab9SJoseph Chen 	} else {
401fbc6dab9SJoseph Chen 		uc_pdata->suspend_on = true;
402fbc6dab9SJoseph Chen 		uc_pdata->suspend_uV = uc_pdata->max_uA;
403fbc6dab9SJoseph Chen 	}
404fbc6dab9SJoseph Chen 
4057837ceabSSimon Glass 	/* Those values are optional (-ENODATA if unset) */
4067837ceabSSimon Glass 	if ((uc_pdata->min_uV != -ENODATA) &&
4077837ceabSSimon Glass 	    (uc_pdata->max_uV != -ENODATA) &&
4087837ceabSSimon Glass 	    (uc_pdata->min_uV == uc_pdata->max_uV))
4097837ceabSSimon Glass 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
4107837ceabSSimon Glass 
4117837ceabSSimon Glass 	/* Those values are optional (-ENODATA if unset) */
4127837ceabSSimon Glass 	if ((uc_pdata->min_uA != -ENODATA) &&
4137837ceabSSimon Glass 	    (uc_pdata->max_uA != -ENODATA) &&
4147837ceabSSimon Glass 	    (uc_pdata->min_uA == uc_pdata->max_uA))
4157837ceabSSimon Glass 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
4167837ceabSSimon Glass 
4172f22a22fSJoseph Chen 	debug("dev.name=%s: min_uV=%d, max_uV=%d, boot-on=%d, always-on=%d, "
4182f22a22fSJoseph Chen 	      "off-in-suspend=%d, suspend_volt=%d\n",
4192f22a22fSJoseph Chen 	      dev->name, uc_pdata->min_uV, uc_pdata->max_uV, uc_pdata->boot_on,
4202f22a22fSJoseph Chen 	      uc_pdata->always_on, !uc_pdata->suspend_on, uc_pdata->suspend_uV);
4212f22a22fSJoseph Chen 
422af41e8dbSPrzemyslaw Marczak 	return 0;
423af41e8dbSPrzemyslaw Marczak }
424af41e8dbSPrzemyslaw Marczak 
425083fc83aSSimon Glass int regulators_enable_boot_on(bool verbose)
426083fc83aSSimon Glass {
427083fc83aSSimon Glass 	struct udevice *dev;
428083fc83aSSimon Glass 	struct uclass *uc;
429083fc83aSSimon Glass 	int ret;
430083fc83aSSimon Glass 
431083fc83aSSimon Glass 	ret = uclass_get(UCLASS_REGULATOR, &uc);
432083fc83aSSimon Glass 	if (ret)
433083fc83aSSimon Glass 		return ret;
434083fc83aSSimon Glass 	for (uclass_first_device(UCLASS_REGULATOR, &dev);
4353f603cbbSSimon Glass 	     dev;
436083fc83aSSimon Glass 	     uclass_next_device(&dev)) {
437083fc83aSSimon Glass 		ret = regulator_autoset(dev);
438d08504d1SSimon Glass 		if (ret == -EMEDIUMTYPE) {
439d08504d1SSimon Glass 			ret = 0;
440083fc83aSSimon Glass 			continue;
441d08504d1SSimon Glass 		}
442083fc83aSSimon Glass 		if (verbose)
443083fc83aSSimon Glass 			regulator_show(dev, ret);
444364809deSSimon Glass 		if (ret == -ENOSYS)
445364809deSSimon Glass 			ret = 0;
446083fc83aSSimon Glass 	}
447083fc83aSSimon Glass 
448083fc83aSSimon Glass 	return ret;
449083fc83aSSimon Glass }
450083fc83aSSimon Glass 
451af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = {
452af41e8dbSPrzemyslaw Marczak 	.id		= UCLASS_REGULATOR,
453af41e8dbSPrzemyslaw Marczak 	.name		= "regulator",
454af41e8dbSPrzemyslaw Marczak 	.post_bind	= regulator_post_bind,
455af41e8dbSPrzemyslaw Marczak 	.pre_probe	= regulator_pre_probe,
456af41e8dbSPrzemyslaw Marczak 	.per_device_platdata_auto_alloc_size =
457af41e8dbSPrzemyslaw Marczak 				sizeof(struct dm_regulator_uclass_platdata),
458af41e8dbSPrzemyslaw Marczak };
459