2 * Copyright (C) 2014-2015 Samsung Electronics
3 * Przemyslaw Marczak <p.marczak@samsung.com>
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <dm/uclass-internal.h>
12 #include <power/pmic.h>
13 #include <power/regulator.h>
15 DECLARE_GLOBAL_DATA_PTR
;
17 int regulator_mode(struct udevice
*dev
, struct dm_regulator_mode
**modep
)
19 struct dm_regulator_uclass_platdata
*uc_pdata
;
23 uc_pdata
= dev_get_uclass_platdata(dev
);
27 *modep
= uc_pdata
->mode
;
28 return uc_pdata
->mode_count
;
31 int regulator_get_value(struct udevice
*dev
)
33 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
35 if (!ops
|| !ops
->get_value
)
38 return ops
->get_value(dev
);
41 int regulator_set_value(struct udevice
*dev
, int uV
)
43 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
45 if (!ops
|| !ops
->set_value
)
48 return ops
->set_value(dev
, uV
);
51 int regulator_get_current(struct udevice
*dev
)
53 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
55 if (!ops
|| !ops
->get_current
)
58 return ops
->get_current(dev
);
61 int regulator_set_current(struct udevice
*dev
, int uA
)
63 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
65 if (!ops
|| !ops
->set_current
)
68 return ops
->set_current(dev
, uA
);
71 bool regulator_get_enable(struct udevice
*dev
)
73 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
75 if (!ops
|| !ops
->get_enable
)
78 return ops
->get_enable(dev
);
81 int regulator_set_enable(struct udevice
*dev
, bool enable
)
83 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
85 if (!ops
|| !ops
->set_enable
)
88 return ops
->set_enable(dev
, enable
);
91 int regulator_get_mode(struct udevice
*dev
)
93 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
95 if (!ops
|| !ops
->get_mode
)
98 return ops
->get_mode(dev
);
101 int regulator_set_mode(struct udevice
*dev
, int mode
)
103 const struct dm_regulator_ops
*ops
= dev_get_driver_ops(dev
);
105 if (!ops
|| !ops
->set_mode
)
108 return ops
->set_mode(dev
, mode
);
111 int regulator_get_by_platname(const char *plat_name
, struct udevice
**devp
)
113 struct dm_regulator_uclass_platdata
*uc_pdata
;
119 for (ret
= uclass_find_first_device(UCLASS_REGULATOR
, &dev
); dev
;
120 ret
= uclass_find_next_device(&dev
)) {
124 uc_pdata
= dev_get_uclass_platdata(dev
);
125 if (!uc_pdata
|| strcmp(plat_name
, uc_pdata
->name
))
128 return uclass_get_device_tail(dev
, 0, devp
);
131 debug("%s: can't find: %s\n", __func__
, plat_name
);
136 int regulator_get_by_devname(const char *devname
, struct udevice
**devp
)
138 return uclass_get_device_by_name(UCLASS_REGULATOR
, devname
, devp
);
141 static int failed(int ret
, bool verbose
, const char *fmt
, ...)
146 if (verbose
== false)
150 vscnprintf(buf
, sizeof(buf
), fmt
, args
);
158 printf(" (ret: %d)", ret
);
163 int regulator_autoset(const char *platname
,
164 struct udevice
**devp
,
167 struct dm_regulator_uclass_platdata
*uc_pdata
;
174 ret
= regulator_get_by_platname(platname
, &dev
);
176 error("Can get the regulator: %s!", platname
);
180 uc_pdata
= dev_get_uclass_platdata(dev
);
182 error("Can get the regulator %s uclass platdata!", platname
);
186 if (!uc_pdata
->always_on
&& !uc_pdata
->boot_on
)
190 printf("%s@%s: ", dev
->name
, uc_pdata
->name
);
192 /* Those values are optional (-ENODATA if unset) */
193 if ((uc_pdata
->min_uV
!= -ENODATA
) &&
194 (uc_pdata
->max_uV
!= -ENODATA
) &&
195 (uc_pdata
->min_uV
== uc_pdata
->max_uV
)) {
196 ret
= regulator_set_value(dev
, uc_pdata
->min_uV
);
197 if (failed(ret
, verbose
, "set %d uV", uc_pdata
->min_uV
))
201 /* Those values are optional (-ENODATA if unset) */
202 if ((uc_pdata
->min_uA
!= -ENODATA
) &&
203 (uc_pdata
->max_uA
!= -ENODATA
) &&
204 (uc_pdata
->min_uA
== uc_pdata
->max_uA
)) {
205 ret
= regulator_set_current(dev
, uc_pdata
->min_uA
);
206 if (failed(ret
, verbose
, "; set %d uA", uc_pdata
->min_uA
))
210 ret
= regulator_set_enable(dev
, true);
211 if (failed(ret
, verbose
, "; enabling", uc_pdata
->min_uA
))
224 int regulator_list_autoset(const char *list_platname
[],
225 struct udevice
*list_devp
[],
229 int error
= 0, i
= 0, ret
;
231 while (list_platname
[i
]) {
232 ret
= regulator_autoset(list_platname
[i
], &dev
, verbose
);
245 static bool regulator_name_is_unique(struct udevice
*check_dev
,
246 const char *check_name
)
248 struct dm_regulator_uclass_platdata
*uc_pdata
;
250 int check_len
= strlen(check_name
);
254 for (ret
= uclass_find_first_device(UCLASS_REGULATOR
, &dev
); dev
;
255 ret
= uclass_find_next_device(&dev
)) {
256 if (ret
|| dev
== check_dev
)
259 uc_pdata
= dev_get_uclass_platdata(dev
);
260 len
= strlen(uc_pdata
->name
);
261 if (len
!= check_len
)
264 if (!strcmp(uc_pdata
->name
, check_name
))
271 static int regulator_post_bind(struct udevice
*dev
)
273 struct dm_regulator_uclass_platdata
*uc_pdata
;
274 int offset
= dev
->of_offset
;
275 const void *blob
= gd
->fdt_blob
;
276 const char *property
= "regulator-name";
278 uc_pdata
= dev_get_uclass_platdata(dev
);
282 /* Regulator's mandatory constraint */
283 uc_pdata
->name
= fdt_getprop(blob
, offset
, property
, NULL
);
284 if (!uc_pdata
->name
) {
285 debug("%s: dev: %s has no property 'regulator-name'\n",
286 __func__
, dev
->name
);
290 if (regulator_name_is_unique(dev
, uc_pdata
->name
))
293 error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
294 property
, dev
->name
, uc_pdata
->name
);
299 static int regulator_pre_probe(struct udevice
*dev
)
301 struct dm_regulator_uclass_platdata
*uc_pdata
;
302 int offset
= dev
->of_offset
;
304 uc_pdata
= dev_get_uclass_platdata(dev
);
308 /* Regulator's optional constraints */
309 uc_pdata
->min_uV
= fdtdec_get_int(gd
->fdt_blob
, offset
,
310 "regulator-min-microvolt", -ENODATA
);
311 uc_pdata
->max_uV
= fdtdec_get_int(gd
->fdt_blob
, offset
,
312 "regulator-max-microvolt", -ENODATA
);
313 uc_pdata
->min_uA
= fdtdec_get_int(gd
->fdt_blob
, offset
,
314 "regulator-min-microamp", -ENODATA
);
315 uc_pdata
->max_uA
= fdtdec_get_int(gd
->fdt_blob
, offset
,
316 "regulator-max-microamp", -ENODATA
);
317 uc_pdata
->always_on
= fdtdec_get_bool(gd
->fdt_blob
, offset
,
318 "regulator-always-on");
319 uc_pdata
->boot_on
= fdtdec_get_bool(gd
->fdt_blob
, offset
,
320 "regulator-boot-on");
325 UCLASS_DRIVER(regulator
) = {
326 .id
= UCLASS_REGULATOR
,
328 .post_bind
= regulator_post_bind
,
329 .pre_probe
= regulator_pre_probe
,
330 .per_device_platdata_auto_alloc_size
=
331 sizeof(struct dm_regulator_uclass_platdata
),