diff options
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r-- | drivers/regulator/core.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0c0cf462004..afe94470b67f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -381,12 +381,16 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, if (!regnode) { regnode = of_get_child_regulator(child, prop_name); if (regnode) - return regnode; + goto err_node_put; } else { - return regnode; + goto err_node_put; } } return NULL; + +err_node_put: + of_node_put(child); + return regnode; } /** @@ -564,13 +568,15 @@ static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - ssize_t ret; + int uV; regulator_lock(rdev); - ret = sprintf(buf, "%d\n", regulator_get_voltage_rdev(rdev)); + uV = regulator_get_voltage_rdev(rdev); regulator_unlock(rdev); - return ret; + if (uV < 0) + return uV; + return sprintf(buf, "%d\n", uV); } static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); @@ -5640,7 +5646,7 @@ static int __init regulator_init(void) /* init early to allow our consumers to complete system booting */ core_initcall(regulator_init); -static int __init regulator_late_cleanup(struct device *dev, void *data) +static int regulator_late_cleanup(struct device *dev, void *data) { struct regulator_dev *rdev = dev_to_rdev(dev); const struct regulator_ops *ops = rdev->desc->ops; @@ -5689,18 +5695,9 @@ unlock: return 0; } -static int __init regulator_init_complete(void) +static void regulator_init_complete_work_function(struct work_struct *work) { /* - * Since DT doesn't provide an idiomatic mechanism for - * enabling full constraints and since it's much more natural - * with DT to provide them just assume that a DT enabled - * system has full constraints. - */ - if (of_have_populated_dt()) - has_full_constraints = true; - - /* * Regulators may had failed to resolve their input supplies * when were registered, either because the input supply was * not registered yet or because its parent device was not @@ -5717,6 +5714,35 @@ static int __init regulator_init_complete(void) */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); +} + +static DECLARE_DELAYED_WORK(regulator_init_complete_work, + regulator_init_complete_work_function); + +static int __init regulator_init_complete(void) +{ + /* + * Since DT doesn't provide an idiomatic mechanism for + * enabling full constraints and since it's much more natural + * with DT to provide them just assume that a DT enabled + * system has full constraints. + */ + if (of_have_populated_dt()) + has_full_constraints = true; + + /* + * We punt completion for an arbitrary amount of time since + * systems like distros will load many drivers from userspace + * so consumers might not always be ready yet, this is + * particularly an issue with laptops where this might bounce + * the display off then on. Ideally we'd get a notification + * from userspace when this happens but we don't so just wait + * a bit and hope we waited long enough. It'd be better if + * we'd only do this on systems that need it, and a kernel + * command line option might be useful. + */ + schedule_delayed_work(®ulator_init_complete_work, + msecs_to_jiffies(30000)); return 0; } |