summaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/pmic/pmic-uclass.c57
-rw-r--r--drivers/power/regulator/regulator-uclass.c134
2 files changed, 108 insertions, 83 deletions
diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c
index 812ac13baa..d99cb9aada 100644
--- a/drivers/power/pmic/pmic-uclass.c
+++ b/drivers/power/pmic/pmic-uclass.c
@@ -9,6 +9,7 @@
#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
+#include <vsprintf.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
@@ -17,16 +18,6 @@
DECLARE_GLOBAL_DATA_PTR;
-static ulong str_get_num(const char *ptr, const char *maxptr)
-{
- if (!ptr || !maxptr)
- return 0;
-
- while (!isdigit(*ptr) && ptr++ < maxptr);
-
- return simple_strtoul(ptr, NULL, 0);
-}
-
int pmic_bind_children(struct udevice *pmic, int offset,
const struct pmic_child_info *child_info)
{
@@ -35,7 +26,6 @@ int pmic_bind_children(struct udevice *pmic, int offset,
struct driver *drv;
struct udevice *child;
const char *node_name;
- int node_name_len;
int bind_count = 0;
int node;
int prefix_len;
@@ -47,19 +37,19 @@ int pmic_bind_children(struct udevice *pmic, int offset,
for (node = fdt_first_subnode(blob, offset);
node > 0;
node = fdt_next_subnode(blob, node)) {
- node_name = fdt_get_name(blob, node, &node_name_len);
+ node_name = fdt_get_name(blob, node, NULL);
debug("* Found child node: '%s' at offset:%d\n", node_name,
node);
child = NULL;
for (info = child_info; info->prefix && info->driver; info++) {
+ debug(" - compatible prefix: '%s'\n", info->prefix);
+
prefix_len = strlen(info->prefix);
- if (strncasecmp(info->prefix, node_name, prefix_len))
+ if (strncmp(info->prefix, node_name, prefix_len))
continue;
- debug(" - compatible prefix: '%s'\n", info->prefix);
-
drv = lists_driver_lookup_name(info->driver);
if (!drv) {
debug(" - driver: '%s' not found!\n",
@@ -78,10 +68,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
debug(" - bound child device: '%s'\n", child->name);
- child->driver_data = str_get_num(node_name +
- prefix_len,
- node_name +
- node_name_len);
+ child->driver_data = trailing_strtol(node_name);
debug(" - set 'child->driver_data': %lu\n",
child->driver_data);
@@ -139,6 +126,38 @@ int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
return ops->write(dev, reg, buffer, len);
}
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+ u8 byte;
+ int ret;
+
+ ret = pmic_read(dev, reg, &byte, 1);
+ debug("%s: reg=%x, value=%x\n", __func__, reg, byte);
+
+ return ret ? ret : byte;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+ u8 byte = value;
+
+ debug("%s: reg=%x, value=%x\n", __func__, reg, value);
+ return pmic_read(dev, reg, &byte, 1);
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+ u8 byte;
+ int ret;
+
+ ret = pmic_reg_read(dev, reg);
+ if (ret < 0)
+ return ret;
+ byte = (ret & ~clr) | set;
+
+ return pmic_reg_write(dev, reg, byte);
+}
+
UCLASS_DRIVER(pmic) = {
.id = UCLASS_PMIC,
.name = "pmic",
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 31ffd44454..12e141b4ad 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -138,87 +138,57 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp)
return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
}
-static int failed(int ret, bool verbose, const char *fmt, ...)
+int regulator_autoset(struct udevice *dev)
{
- va_list args;
- char buf[64];
-
- if (verbose == false)
- return ret;
+ struct dm_regulator_uclass_platdata *uc_pdata;
+ int ret = 0;
- va_start(args, fmt);
- vscnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
+ uc_pdata = dev_get_uclass_platdata(dev);
+ if (!uc_pdata->always_on && !uc_pdata->boot_on)
+ return -EMEDIUMTYPE;
- printf(buf);
+ if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+ ret = regulator_set_value(dev, uc_pdata->min_uV);
+ if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
+ ret = regulator_set_current(dev, uc_pdata->min_uA);
if (!ret)
- return 0;
-
- printf(" (ret: %d)", ret);
+ ret = regulator_set_enable(dev, true);
return ret;
}
-int regulator_autoset(const char *platname,
- struct udevice **devp,
- bool verbose)
+static void regulator_show(struct udevice *dev, int ret)
{
struct dm_regulator_uclass_platdata *uc_pdata;
- struct udevice *dev;
- int ret;
-
- if (devp)
- *devp = NULL;
-
- ret = regulator_get_by_platname(platname, &dev);
- if (ret) {
- error("Can get the regulator: %s!", platname);
- return ret;
- }
uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata) {
- error("Can get the regulator %s uclass platdata!", platname);
- return -ENXIO;
- }
- if (!uc_pdata->always_on && !uc_pdata->boot_on)
- goto retdev;
-
- if (verbose)
- printf("%s@%s: ", dev->name, uc_pdata->name);
-
- /* Those values are optional (-ENODATA if unset) */
- if ((uc_pdata->min_uV != -ENODATA) &&
- (uc_pdata->max_uV != -ENODATA) &&
- (uc_pdata->min_uV == uc_pdata->max_uV)) {
- ret = regulator_set_value(dev, uc_pdata->min_uV);
- if (failed(ret, verbose, "set %d uV", uc_pdata->min_uV))
- goto exit;
- }
-
- /* Those values are optional (-ENODATA if unset) */
- if ((uc_pdata->min_uA != -ENODATA) &&
- (uc_pdata->max_uA != -ENODATA) &&
- (uc_pdata->min_uA == uc_pdata->max_uA)) {
- ret = regulator_set_current(dev, uc_pdata->min_uA);
- if (failed(ret, verbose, "; set %d uA", uc_pdata->min_uA))
- goto exit;
- }
+ printf("%s@%s: ", dev->name, uc_pdata->name);
+ if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+ printf("set %d uV", uc_pdata->min_uV);
+ if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
+ printf("; set %d uA", uc_pdata->min_uA);
+ printf("; enabling");
+ if (ret)
+ printf(" (ret: %d)\n", ret);
+ printf("\n");
+}
- ret = regulator_set_enable(dev, true);
- if (failed(ret, verbose, "; enabling", uc_pdata->min_uA))
- goto exit;
+int regulator_autoset_by_name(const char *platname, struct udevice **devp)
+{
+ struct udevice *dev;
+ int ret;
-retdev:
+ ret = regulator_get_by_platname(platname, &dev);
if (devp)
*devp = dev;
-exit:
- if (verbose)
- printf("\n");
+ if (ret) {
+ debug("Can get the regulator: %s!", platname);
+ return ret;
+ }
- return ret;
+ return regulator_autoset(dev);
}
int regulator_list_autoset(const char *list_platname[],
@@ -229,7 +199,9 @@ int regulator_list_autoset(const char *list_platname[],
int error = 0, i = 0, ret;
while (list_platname[i]) {
- ret = regulator_autoset(list_platname[i], &dev, verbose);
+ ret = regulator_autoset_by_name(list_platname[i], &dev);
+ if (ret != -EMEDIUMTYPE && verbose)
+ regulator_show(dev, ret);
if (ret & !error)
error = ret;
@@ -290,7 +262,7 @@ static int regulator_post_bind(struct udevice *dev)
if (regulator_name_is_unique(dev, uc_pdata->name))
return 0;
- error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+ debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
property, dev->name, uc_pdata->name);
return -EINVAL;
@@ -319,9 +291,43 @@ static int regulator_pre_probe(struct udevice *dev)
uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
"regulator-boot-on");
+ /* Those values are optional (-ENODATA if unset) */
+ if ((uc_pdata->min_uV != -ENODATA) &&
+ (uc_pdata->max_uV != -ENODATA) &&
+ (uc_pdata->min_uV == uc_pdata->max_uV))
+ uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
+
+ /* Those values are optional (-ENODATA if unset) */
+ if ((uc_pdata->min_uA != -ENODATA) &&
+ (uc_pdata->max_uA != -ENODATA) &&
+ (uc_pdata->min_uA == uc_pdata->max_uA))
+ uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
+
return 0;
}
+int regulators_enable_boot_on(bool verbose)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_REGULATOR, &uc);
+ if (ret)
+ return ret;
+ for (uclass_first_device(UCLASS_REGULATOR, &dev);
+ dev && !ret;
+ uclass_next_device(&dev)) {
+ ret = regulator_autoset(dev);
+ if (ret == -EMEDIUMTYPE)
+ continue;
+ if (verbose)
+ regulator_show(dev, ret);
+ }
+
+ return ret;
+}
+
UCLASS_DRIVER(regulator) = {
.id = UCLASS_REGULATOR,
.name = "regulator",
OpenPOWER on IntegriCloud