diff options
Diffstat (limited to 'drivers/power/regulator/regulator-uclass.c')
-rw-r--r-- | drivers/power/regulator/regulator-uclass.c | 104 |
1 files changed, 68 insertions, 36 deletions
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c index 07ce2869e6..31ffd44454 100644 --- a/drivers/power/regulator/regulator-uclass.c +++ b/drivers/power/regulator/regulator-uclass.c @@ -108,16 +108,19 @@ int regulator_set_mode(struct udevice *dev, int mode) return ops->set_mode(dev, mode); } -int regulator_by_platname(const char *plat_name, struct udevice **devp) +int regulator_get_by_platname(const char *plat_name, struct udevice **devp) { struct dm_regulator_uclass_platdata *uc_pdata; struct udevice *dev; + int ret; *devp = NULL; - for (uclass_find_first_device(UCLASS_REGULATOR, &dev); - dev; - uclass_find_next_device(&dev)) { + for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; + ret = uclass_find_next_device(&dev)) { + if (ret) + continue; + uc_pdata = dev_get_uclass_platdata(dev); if (!uc_pdata || strcmp(plat_name, uc_pdata->name)) continue; @@ -130,12 +133,12 @@ int regulator_by_platname(const char *plat_name, struct udevice **devp) return -ENODEV; } -int regulator_by_devname(const char *devname, struct udevice **devp) +int regulator_get_by_devname(const char *devname, struct udevice **devp) { return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp); } -static int setting_failed(int ret, bool verbose, const char *fmt, ...) +static int failed(int ret, bool verbose, const char *fmt, ...) { va_list args; char buf[64]; @@ -157,19 +160,18 @@ static int setting_failed(int ret, bool verbose, const char *fmt, ...) return ret; } -int regulator_by_platname_autoset_and_enable(const char *platname, - struct udevice **devp, - bool verbose) +int regulator_autoset(const char *platname, + struct udevice **devp, + bool verbose) { struct dm_regulator_uclass_platdata *uc_pdata; struct udevice *dev; - bool v = verbose; int ret; if (devp) *devp = NULL; - ret = regulator_by_platname(platname, &dev); + ret = regulator_get_by_platname(platname, &dev); if (ret) { error("Can get the regulator: %s!", platname); return ret; @@ -181,7 +183,10 @@ int regulator_by_platname_autoset_and_enable(const char *platname, return -ENXIO; } - if (v) + 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) */ @@ -189,7 +194,7 @@ int regulator_by_platname_autoset_and_enable(const char *platname, (uc_pdata->max_uV != -ENODATA) && (uc_pdata->min_uV == uc_pdata->max_uV)) { ret = regulator_set_value(dev, uc_pdata->min_uV); - if (setting_failed(ret, v, "set %d uV", uc_pdata->min_uV)) + if (failed(ret, verbose, "set %d uV", uc_pdata->min_uV)) goto exit; } @@ -198,49 +203,69 @@ int regulator_by_platname_autoset_and_enable(const char *platname, (uc_pdata->max_uA != -ENODATA) && (uc_pdata->min_uA == uc_pdata->max_uA)) { ret = regulator_set_current(dev, uc_pdata->min_uA); - if (setting_failed(ret, v, "; set %d uA", uc_pdata->min_uA)) + if (failed(ret, verbose, "; set %d uA", uc_pdata->min_uA)) goto exit; } - if (!uc_pdata->always_on && !uc_pdata->boot_on) - goto retdev; - ret = regulator_set_enable(dev, true); - if (setting_failed(ret, v, "; enabling", uc_pdata->min_uA)) + if (failed(ret, verbose, "; enabling", uc_pdata->min_uA)) goto exit; retdev: if (devp) *devp = dev; exit: - if (v) + if (verbose) printf("\n"); + return ret; } -int regulator_by_platname_list_autoset_and_enable(const char *list_platname[], - int list_entries, - struct udevice *list_devp[], - bool verbose) +int regulator_list_autoset(const char *list_platname[], + struct udevice *list_devp[], + bool verbose) { struct udevice *dev; - int i, ret, success = 0; + int error = 0, i = 0, ret; - for (i = 0; i < list_entries; i++) { + while (list_platname[i]) { ret = regulator_autoset(list_platname[i], &dev, verbose); - if (!ret) - success++; + if (ret & !error) + error = ret; + + if (list_devp) + list_devp[i] = dev; + + i++; + } + + return error; +} + +static bool regulator_name_is_unique(struct udevice *check_dev, + const char *check_name) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct udevice *dev; + int check_len = strlen(check_name); + int ret; + int len; - if (!list_devp) + for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; + ret = uclass_find_next_device(&dev)) { + if (ret || dev == check_dev) continue; - if (ret) - list_devp[i] = NULL; - else - list_devp[i] = dev; + uc_pdata = dev_get_uclass_platdata(dev); + len = strlen(uc_pdata->name); + if (len != check_len) + continue; + + if (!strcmp(uc_pdata->name, check_name)) + return false; } - return (success != list_entries); + return true; } static int regulator_post_bind(struct udevice *dev) @@ -248,20 +273,27 @@ static int regulator_post_bind(struct udevice *dev) struct dm_regulator_uclass_platdata *uc_pdata; int offset = dev->of_offset; const void *blob = gd->fdt_blob; + const char *property = "regulator-name"; uc_pdata = dev_get_uclass_platdata(dev); if (!uc_pdata) return -ENXIO; /* Regulator's mandatory constraint */ - uc_pdata->name = fdt_getprop(blob, offset, "regulator-name", NULL); + uc_pdata->name = fdt_getprop(blob, offset, property, NULL); if (!uc_pdata->name) { debug("%s: dev: %s has no property 'regulator-name'\n", __func__, dev->name); - return -ENXIO; + return -EINVAL; } - return 0; + if (regulator_name_is_unique(dev, uc_pdata->name)) + return 0; + + error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"", + property, dev->name, uc_pdata->name); + + return -EINVAL; } static int regulator_pre_probe(struct udevice *dev) |