diff options
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r-- | drivers/regulator/core.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9a09f3cdbabb..4c1f999041dd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -844,13 +844,22 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, /* do we need to apply the constraint voltage */ if (rdev->constraints->apply_uV && rdev->constraints->min_uV == rdev->constraints->max_uV) { - ret = _regulator_do_set_voltage(rdev, - rdev->constraints->min_uV, - rdev->constraints->max_uV); - if (ret < 0) { - rdev_err(rdev, "failed to apply %duV constraint\n", - rdev->constraints->min_uV); - return ret; + int current_uV = _regulator_get_voltage(rdev); + if (current_uV < 0) { + rdev_err(rdev, "failed to get the current voltage\n"); + return current_uV; + } + if (current_uV < rdev->constraints->min_uV || + current_uV > rdev->constraints->max_uV) { + ret = _regulator_do_set_voltage( + rdev, rdev->constraints->min_uV, + rdev->constraints->max_uV); + if (ret < 0) { + rdev_err(rdev, + "failed to apply %duV constraint\n", + rdev->constraints->min_uV); + return ret; + } } } @@ -1430,9 +1439,9 @@ EXPORT_SYMBOL_GPL(regulator_get); * * Returns a struct regulator corresponding to the regulator producer, * or IS_ERR() condition containing errno. Other consumers will be - * unable to obtain this reference is held and the use count for the - * regulator will be initialised to reflect the current state of the - * regulator. + * unable to obtain this regulator while this reference is held and the + * use count for the regulator will be initialised to reflect the current + * state of the regulator. * * This is intended for use by consumers which cannot tolerate shared * use of the regulator such as those which need to force the @@ -1456,10 +1465,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); * @id: Supply name or regulator ID. * * Returns a struct regulator corresponding to the regulator producer, - * or IS_ERR() condition containing errno. Other consumers will be - * unable to obtain this reference is held and the use count for the - * regulator will be initialised to reflect the current state of the - * regulator. + * or IS_ERR() condition containing errno. * * This is intended for use by consumers for devices which can have * some supplies unconnected in normal use, such as some MMC devices. @@ -1597,9 +1603,10 @@ EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); * registered any aliases that were registered will be removed * before returning to the caller. */ -int regulator_bulk_register_supply_alias(struct device *dev, const char **id, +int regulator_bulk_register_supply_alias(struct device *dev, + const char *const *id, struct device *alias_dev, - const char **alias_id, + const char *const *alias_id, int num_id) { int i; @@ -1637,7 +1644,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); * aliases in one operation. */ void regulator_bulk_unregister_supply_alias(struct device *dev, - const char **id, + const char *const *id, int num_id) { int i; @@ -2321,6 +2328,10 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, regulator_list_voltage_linear) ret = regulator_map_voltage_linear(rdev, min_uV, max_uV); + else if (rdev->desc->ops->list_voltage == + regulator_list_voltage_linear_range) + ret = regulator_map_voltage_linear_range(rdev, + min_uV, max_uV); else ret = regulator_map_voltage_iterate(rdev, min_uV, max_uV); @@ -3447,7 +3458,7 @@ regulator_register(const struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; - rdev->dev.of_node = config->of_node; + rdev->dev.of_node = of_node_get(config->of_node); rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); @@ -3589,6 +3600,7 @@ void regulator_unregister(struct regulator_dev *rdev) list_del(&rdev->list); kfree(rdev->constraints); regulator_ena_gpio_free(rdev); + of_node_put(rdev->dev.of_node); device_unregister(&rdev->dev); mutex_unlock(®ulator_list_mutex); } @@ -3819,8 +3831,9 @@ static int __init regulator_init_complete(void) mutex_lock(®ulator_list_mutex); /* If we have a full configuration then disable any regulators - * which are not in use or always_on. This will become the - * default behaviour in the future. + * we have permission to change the status for and which are + * not in use or always_on. This is effectively the default + * for DT and ACPI as they have full constraints. */ list_for_each_entry(rdev, ®ulator_list, list) { ops = rdev->desc->ops; @@ -3829,6 +3842,9 @@ static int __init regulator_init_complete(void) if (c && c->always_on) continue; + if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) + continue; + mutex_lock(&rdev->mutex); if (rdev->use_count) @@ -3867,4 +3883,4 @@ unlock: return 0; } -late_initcall(regulator_init_complete); +late_initcall_sync(regulator_init_complete); |