xref: /rk3399_rockchip-uboot/drivers/power/regulator/regulator-uclass.c (revision 2f5d532f3b8a7697dc1b5700000b1e350323d50c)
1 /*
2  * Copyright (C) 2014-2015 Samsung Electronics
3  * Przemyslaw Marczak <p.marczak@samsung.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 #include <common.h>
8 #include <fdtdec.h>
9 #include <errno.h>
10 #include <dm.h>
11 #include <dm/uclass-internal.h>
12 #include <power/pmic.h>
13 #include <power/regulator.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
17 int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
18 {
19 	struct dm_regulator_uclass_platdata *uc_pdata;
20 
21 	*modep = NULL;
22 
23 	uc_pdata = dev_get_uclass_platdata(dev);
24 	if (!uc_pdata)
25 		return -ENXIO;
26 
27 	*modep = uc_pdata->mode;
28 	return uc_pdata->mode_count;
29 }
30 
31 int regulator_get_value(struct udevice *dev)
32 {
33 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
34 
35 	if (!ops || !ops->get_value)
36 		return -ENOSYS;
37 
38 	return ops->get_value(dev);
39 }
40 
41 int regulator_set_value(struct udevice *dev, int uV)
42 {
43 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
44 
45 	if (!ops || !ops->set_value)
46 		return -ENOSYS;
47 
48 	return ops->set_value(dev, uV);
49 }
50 
51 /*
52  * To be called with at most caution as there is no check
53  * before setting the actual voltage value.
54  */
55 int regulator_set_value_force(struct udevice *dev, int uV)
56 {
57 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
58 
59 	if (!ops || !ops->set_value)
60 		return -ENOSYS;
61 
62 	return ops->set_value(dev, uV);
63 }
64 
65 int regulator_get_current(struct udevice *dev)
66 {
67 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
68 
69 	if (!ops || !ops->get_current)
70 		return -ENOSYS;
71 
72 	return ops->get_current(dev);
73 }
74 
75 int regulator_set_current(struct udevice *dev, int uA)
76 {
77 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
78 
79 	if (!ops || !ops->set_current)
80 		return -ENOSYS;
81 
82 	return ops->set_current(dev, uA);
83 }
84 
85 bool regulator_get_enable(struct udevice *dev)
86 {
87 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
88 
89 	if (!ops || !ops->get_enable)
90 		return -ENOSYS;
91 
92 	return ops->get_enable(dev);
93 }
94 
95 int regulator_set_enable(struct udevice *dev, bool enable)
96 {
97 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
98 
99 	if (!ops || !ops->set_enable)
100 		return -ENOSYS;
101 
102 	return ops->set_enable(dev, enable);
103 }
104 
105 int regulator_get_mode(struct udevice *dev)
106 {
107 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
108 
109 	if (!ops || !ops->get_mode)
110 		return -ENOSYS;
111 
112 	return ops->get_mode(dev);
113 }
114 
115 int regulator_set_mode(struct udevice *dev, int mode)
116 {
117 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
118 
119 	if (!ops || !ops->set_mode)
120 		return -ENOSYS;
121 
122 	return ops->set_mode(dev, mode);
123 }
124 
125 int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
126 {
127 	struct dm_regulator_uclass_platdata *uc_pdata;
128 	struct udevice *dev;
129 	int ret;
130 
131 	*devp = NULL;
132 
133 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
134 	     ret = uclass_find_next_device(&dev)) {
135 		if (ret)
136 			continue;
137 
138 		uc_pdata = dev_get_uclass_platdata(dev);
139 		if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
140 			continue;
141 
142 		return uclass_get_device_tail(dev, 0, devp);
143 	}
144 
145 	debug("%s: can't find: %s\n", __func__, plat_name);
146 
147 	return -ENODEV;
148 }
149 
150 int regulator_get_by_devname(const char *devname, struct udevice **devp)
151 {
152 	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
153 }
154 
155 int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
156 				struct udevice **devp)
157 {
158 	return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
159 					    supply_name, devp);
160 }
161 
162 int regulator_autoset(struct udevice *dev)
163 {
164 	struct dm_regulator_uclass_platdata *uc_pdata;
165 	int ret = 0;
166 
167 	uc_pdata = dev_get_uclass_platdata(dev);
168 	if (!uc_pdata->always_on && !uc_pdata->boot_on)
169 		return -EMEDIUMTYPE;
170 
171 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
172 		ret = regulator_set_value(dev, uc_pdata->min_uV);
173 	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
174 		ret = regulator_set_current(dev, uc_pdata->min_uA);
175 
176 	if (!ret)
177 		ret = regulator_set_enable(dev, true);
178 
179 	return ret;
180 }
181 
182 static void regulator_show(struct udevice *dev, int ret)
183 {
184 	struct dm_regulator_uclass_platdata *uc_pdata;
185 
186 	uc_pdata = dev_get_uclass_platdata(dev);
187 
188 	printf("%s@%s: ", dev->name, uc_pdata->name);
189 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
190 		printf("set %d uV", uc_pdata->min_uV);
191 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
192 		printf("; set %d uA", uc_pdata->min_uA);
193 	printf("; enabling");
194 	if (ret)
195 		printf(" (ret: %d)", ret);
196 	printf("\n");
197 }
198 
199 int regulator_autoset_by_name(const char *platname, struct udevice **devp)
200 {
201 	struct udevice *dev;
202 	int ret;
203 
204 	ret = regulator_get_by_platname(platname, &dev);
205 	if (devp)
206 		*devp = dev;
207 	if (ret) {
208 		debug("Can get the regulator: %s!", platname);
209 		return ret;
210 	}
211 
212 	return regulator_autoset(dev);
213 }
214 
215 int regulator_list_autoset(const char *list_platname[],
216 			   struct udevice *list_devp[],
217 			   bool verbose)
218 {
219 	struct udevice *dev;
220 	int error = 0, i = 0, ret;
221 
222 	while (list_platname[i]) {
223 		ret = regulator_autoset_by_name(list_platname[i], &dev);
224 		if (ret != -EMEDIUMTYPE && verbose)
225 			regulator_show(dev, ret);
226 		if (ret & !error)
227 			error = ret;
228 
229 		if (list_devp)
230 			list_devp[i] = dev;
231 
232 		i++;
233 	}
234 
235 	return error;
236 }
237 
238 static bool regulator_name_is_unique(struct udevice *check_dev,
239 				     const char *check_name)
240 {
241 	struct dm_regulator_uclass_platdata *uc_pdata;
242 	struct udevice *dev;
243 	int check_len = strlen(check_name);
244 	int ret;
245 	int len;
246 
247 	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
248 	     ret = uclass_find_next_device(&dev)) {
249 		if (ret || dev == check_dev)
250 			continue;
251 
252 		uc_pdata = dev_get_uclass_platdata(dev);
253 		len = strlen(uc_pdata->name);
254 		if (len != check_len)
255 			continue;
256 
257 		if (!strcmp(uc_pdata->name, check_name))
258 			return false;
259 	}
260 
261 	return true;
262 }
263 
264 static int regulator_post_bind(struct udevice *dev)
265 {
266 	struct dm_regulator_uclass_platdata *uc_pdata;
267 	int offset = dev->of_offset;
268 	const void *blob = gd->fdt_blob;
269 	const char *property = "regulator-name";
270 
271 	uc_pdata = dev_get_uclass_platdata(dev);
272 	if (!uc_pdata)
273 		return -ENXIO;
274 
275 	/* Regulator's mandatory constraint */
276 	uc_pdata->name = fdt_getprop(blob, offset, property, NULL);
277 	if (!uc_pdata->name) {
278 		debug("%s: dev: %s has no property 'regulator-name'\n",
279 		      __func__, dev->name);
280 		uc_pdata->name = fdt_get_name(blob, offset, NULL);
281 		if (!uc_pdata->name)
282 			return -EINVAL;
283 	}
284 
285 	if (regulator_name_is_unique(dev, uc_pdata->name))
286 		return 0;
287 
288 	debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
289 	      property, dev->name, uc_pdata->name);
290 
291 	return -EINVAL;
292 }
293 
294 static int regulator_pre_probe(struct udevice *dev)
295 {
296 	struct dm_regulator_uclass_platdata *uc_pdata;
297 	int offset = dev->of_offset;
298 
299 	uc_pdata = dev_get_uclass_platdata(dev);
300 	if (!uc_pdata)
301 		return -ENXIO;
302 
303 	/* Regulator's optional constraints */
304 	uc_pdata->min_uV = fdtdec_get_int(gd->fdt_blob, offset,
305 					  "regulator-min-microvolt", -ENODATA);
306 	uc_pdata->max_uV = fdtdec_get_int(gd->fdt_blob, offset,
307 					  "regulator-max-microvolt", -ENODATA);
308 	uc_pdata->min_uA = fdtdec_get_int(gd->fdt_blob, offset,
309 					  "regulator-min-microamp", -ENODATA);
310 	uc_pdata->max_uA = fdtdec_get_int(gd->fdt_blob, offset,
311 					  "regulator-max-microamp", -ENODATA);
312 	uc_pdata->always_on = fdtdec_get_bool(gd->fdt_blob, offset,
313 					      "regulator-always-on");
314 	uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
315 					    "regulator-boot-on");
316 
317 	/* Those values are optional (-ENODATA if unset) */
318 	if ((uc_pdata->min_uV != -ENODATA) &&
319 	    (uc_pdata->max_uV != -ENODATA) &&
320 	    (uc_pdata->min_uV == uc_pdata->max_uV))
321 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
322 
323 	/* Those values are optional (-ENODATA if unset) */
324 	if ((uc_pdata->min_uA != -ENODATA) &&
325 	    (uc_pdata->max_uA != -ENODATA) &&
326 	    (uc_pdata->min_uA == uc_pdata->max_uA))
327 		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
328 
329 	return 0;
330 }
331 
332 int regulators_enable_boot_on(bool verbose)
333 {
334 	struct udevice *dev;
335 	struct uclass *uc;
336 	int ret;
337 
338 	ret = uclass_get(UCLASS_REGULATOR, &uc);
339 	if (ret)
340 		return ret;
341 	for (uclass_first_device(UCLASS_REGULATOR, &dev);
342 	     dev;
343 	     uclass_next_device(&dev)) {
344 		ret = regulator_autoset(dev);
345 		if (ret == -EMEDIUMTYPE) {
346 			ret = 0;
347 			continue;
348 		}
349 		if (verbose)
350 			regulator_show(dev, ret);
351 		if (ret == -ENOSYS)
352 			ret = 0;
353 	}
354 
355 	return ret;
356 }
357 
358 UCLASS_DRIVER(regulator) = {
359 	.id		= UCLASS_REGULATOR,
360 	.name		= "regulator",
361 	.post_bind	= regulator_post_bind,
362 	.pre_probe	= regulator_pre_probe,
363 	.per_device_platdata_auto_alloc_size =
364 				sizeof(struct dm_regulator_uclass_platdata),
365 };
366