diff options
author | Axel Lin <axel.lin@gmail.com> | 2012-04-04 10:32:10 +0800 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-05 11:36:20 +0100 |
commit | eba41a5e8c9473c24c333df288d4fd6a40e98464 (patch) | |
tree | 1c6478752c673622d6ad0e83852ec0cd2c4517bb /drivers/regulator/core.c | |
parent | 576ca4367f291a9b240d027670fa2e344edf8c8a (diff) |
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.c | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f032823caa9..d4d34cbd34d 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; } |