summaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 11:31:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 11:31:16 -0700
commit3f17ea6dea8ba5668873afa54628a91aaa3fb1c0 (patch)
treeafbeb2accd4c2199ddd705ae943995b143a0af02 /drivers/regulator/core.c
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
parent1a5700bc2d10cd379a795fd2bb377a190af5acd4 (diff)
Merge branch 'next' (accumulated 3.16 merge window patches) into master
Now that 3.15 is released, this merges the 'next' branch into 'master', bringing us to the normal situation where my 'master' branch is the merge window. * accumulated work in next: (6809 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9a09f3cdbab..4c1f999041d 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 = &regulator_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(&regulator_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(&regulator_list_mutex);
}
@@ -3819,8 +3831,9 @@ static int __init regulator_init_complete(void)
mutex_lock(&regulator_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, &regulator_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);