summaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
authorAxel Lin2012-04-04 04:32:10 +0200
committerMark Brown2012-04-05 12:36:20 +0200
commiteba41a5e8c9473c24c333df288d4fd6a40e98464 (patch)
tree1c6478752c673622d6ad0e83852ec0cd2c4517bb /drivers/regulator/core.c
parentregulator: core: Pull non-DT supply mapping into regulator_dev_lookup() (diff)
downloadkernel-qcow2-linux-eba41a5e8c9473c24c333df288d4fd6a40e98464.tar.gz
kernel-qcow2-linux-eba41a5e8c9473c24c333df288d4fd6a40e98464.tar.xz
kernel-qcow2-linux-eba41a5e8c9473c24c333df288d4fd6a40e98464.zip
regulator: Support set_voltage_time_sel for drivers implement set_voltage
In currently implementation of _regulator_do_set_voltage, set_voltage_time_sel will only be called if set_voltage_sel is implemented. set_voltage_time_sel actually only needs get_voltage_sel to get old_selector. This patch makes regulator core support set_voltage_time_sel for drivers implement either set_voltage or set_voltage_sel. Signed-off-by: Axel Lin <axel.lin@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c59
1 files changed, 31 insertions, 28 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index f032823caa98..d4d34cbd34d9 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1856,23 +1856,35 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int ret;
int delay = 0;
unsigned int selector;
+ int old_selector = -1;
+ int best_val = INT_MAX;
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset;
max_uV += rdev->constraints->uV_offset;
+ /*
+ * If we can't obtain the old selector there is not enough
+ * info to call set_voltage_time_sel().
+ */
+ if (rdev->desc->ops->set_voltage_time_sel &&
+ rdev->desc->ops->get_voltage_sel) {
+ old_selector = rdev->desc->ops->get_voltage_sel(rdev);
+ if (old_selector < 0)
+ return old_selector;
+ }
+
if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);
if (rdev->desc->ops->list_voltage)
- selector = rdev->desc->ops->list_voltage(rdev,
+ best_val = rdev->desc->ops->list_voltage(rdev,
selector);
else
- selector = -1;
+ best_val = -1;
} else if (rdev->desc->ops->set_voltage_sel) {
- int best_val = INT_MAX;
int i;
selector = 0;
@@ -1891,36 +1903,27 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
}
- /*
- * If we can't obtain the old selector there is not enough
- * info to call set_voltage_time_sel().
- */
- if (rdev->desc->ops->set_voltage_time_sel &&
- rdev->desc->ops->get_voltage_sel) {
- unsigned int old_selector = 0;
-
- ret = rdev->desc->ops->get_voltage_sel(rdev);
- if (ret < 0)
- return ret;
- old_selector = ret;
- ret = rdev->desc->ops->set_voltage_time_sel(rdev,
- old_selector, selector);
- if (ret < 0)
- rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret);
- else
- delay = ret;
- }
-
- if (best_val != INT_MAX) {
+ if (best_val != INT_MAX)
ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
- selector = best_val;
- } else {
+ else
ret = -EINVAL;
- }
} else {
ret = -EINVAL;
}
+ /* Call set_voltage_time_sel if successfully obtained old_selector */
+ if (ret == 0 && old_selector >= 0 &&
+ rdev->desc->ops->set_voltage_time_sel) {
+
+ delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+ old_selector, selector);
+ if (delay < 0) {
+ rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
+ delay);
+ delay = 0;
+ }
+ }
+
/* Insert any necessary delays */
if (delay >= 1000) {
mdelay(delay / 1000);
@@ -1933,7 +1936,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
NULL);
- trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
+ trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
return ret;
}