regulator: Add set_voltage_time op
PATCH v4 1/4 regulator: Add set_voltage_time op
The new op is analogous to set_voltage_time_sel. It can be used by regulators that don't have a table of discrete voltages. The function returns the time for the regulator voltage output voltage to stabilize after being set to a new value, in microseconds. The actual calculation of the stabilization time is done in the same place for both types of regulators.
---
Changes in v4:
- This patch is new for v4.
drivers/regulator/core.c | 140 +++++++++++++++++++++++++-------------- include/linux/regulator/driver.h | 8 +++ 2 files changed, 97 insertions(+), 51 deletions(-)
drivers/regulator/core.c +89 -51
@@ -2751,6 +2751,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,int best_val =0 ;unsigned int selector;int old_selector =-1 ; +int old_uV =_regulator_get_voltage (rdev);trace_regulator_set_voltage (rdev_get_name (rdev), min_uV, max_uV);
@@ -2800,27 +2801,38 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, ret = -EINVAL ; } -/* Call set_voltage_time_sel if successfully obtained old_selector */ -if (ret ==0 && !rdev->constraints->ramp_disable && old_selector >=0 - && old_selector != selector) { +if (ret !=0 || rdev->constraints->ramp_disable) + goto no_delay; - 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 ; - } +if (rdev->desc->ops->set_voltage_time) { +int new_uV =_regulator_get_voltage (rdev); -/* Insert any necessary delays */ -if (delay >=1000 ) { -mdelay (delay /1000 ); -udelay (delay %1000 ); - }else if (delay) { -udelay (delay); - } +if (old_uV == new_uV) + goto no_delay; + + delay = rdev->desc->ops->set_voltage_time (rdev, old_uV, new_uV); + }else if (rdev->desc->ops->set_voltage_time_sel) { +if (old_selector <0 || old_selector == selector) + goto no_delay; + + delay = rdev->desc->ops->set_voltage_time_sel ( + rdev, old_selector, selector); + } + +if (delay <0 ) { +rdev_warn (rdev,"failed to get delay: %d\n" , delay); + delay =0 ; } +/* Insert any necessary delays */ +if (delay >=1000 ) { +mdelay (delay /1000 ); +udelay (delay %1000 ); + }else if (delay) { +udelay (delay); + } + +no_delay:if (ret ==0 && best_val >=0 ) {unsigned long data = best_val;
@@ -2993,54 +3005,58 @@ int regulator_set_voltage_time(struct regulator *regulator, {struct regulator_dev *rdev = regulator->rdev;const struct regulator_ops *ops = rdev->desc->ops; -int old_sel =-1 ; -int new_sel =-1 ; -int voltage; -int i; -/* Currently requires operations to do this */ -if (!ops->list_voltage || !ops->set_voltage_time_sel - || !rdev->desc->n_voltages) -return -EINVAL ; +if (ops->set_voltage_time) { +return ops->set_voltage_time (rdev, old_uV, new_uV); + }else if (ops->set_voltage_time_sel) { +int old_sel =-1 ; +int new_sel =-1 ; +int voltage; +int i; -for (i =0 ; i < rdev->desc->n_voltages; i++) { -/* We only look for exact voltage matches here */ - voltage =regulator_list_voltage (regulator, i); -if (voltage <0 ) +/* Currently requires operations to do this */ +if (!ops->list_voltage || !rdev->desc->n_voltages)return -EINVAL ; -if (voltage ==0 ) -continue ; -if (voltage == old_uV) - old_sel = i; -if (voltage == new_uV) - new_sel = i; - } -if (old_sel <0 || new_sel <0 ) -return -EINVAL ; +for (i =0 ; i < rdev->desc->n_voltages; i++) { +/* We only look for exact voltage matches here */ + voltage =regulator_list_voltage (regulator, i); +if (voltage <0 ) +return -EINVAL ; +if (voltage ==0 ) +continue ; +if (voltage == old_uV) + old_sel = i; +if (voltage == new_uV) + new_sel = i; + } + +if (old_sel <0 || new_sel <0 ) +return -EINVAL ; + +return ops->set_voltage_time_sel (rdev, old_sel, new_sel); + } -return ops->set_voltage_time_sel (rdev, old_sel, new_sel); +return -EINVAL ; }EXPORT_SYMBOL_GPL (regulator_set_voltage_time);/** -* regulator_set_voltage_time_sel - get raise/fall time -* @rdev: regulator source device -* @old_selector: selector for starting voltage -* @new_selector: selector for target voltage +* regulator_set_voltage_time_op - get raise/fall time +* @regulator: regulator source +* @old_uV: starting voltage in microvolts +* @new_uV: target voltage in microvolts * -* Provided with the starting and target voltage selectors, this function -* returns time in microseconds required to rise or fall to this new voltage +* Provided with the starting and ending voltage, this function calculates +* the time in microseconds required to rise or fall to this new voltage. * * Drivers providing ramp_delay in regulation_constraints can use this as their -* set_voltage_time_sel() operation. +* set_voltage_time() operation. */ -int regulator_set_voltage_time_sel (struct regulator_dev *rdev, -unsigned int old_selector, -unsigned int new_selector) +int regulator_set_voltage_time_op (struct regulator_dev *rdev, +int old_uV,int new_uV) {unsigned int ramp_delay =0 ; -int old_volt, new_volt;if (rdev->constraints->ramp_delay) ramp_delay = rdev->constraints->ramp_delay;
@@ -3052,6 +3068,28 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,return 0 ; } +return DIV_ROUND_UP (abs (new_uV - old_uV), ramp_delay); +} +EXPORT_SYMBOL_GPL (regulator_set_voltage_time_op); + +/** +* regulator_set_voltage_time_sel - get raise/fall time +* @rdev: regulator source device +* @old_selector: selector for starting voltage +* @new_selector: selector for target voltage +* +* Provided with the starting and target voltage selectors, this function +* returns time in microseconds required to rise or fall to this new voltage +* +* Drivers providing ramp_delay in regulation_constraints can use this as their +* set_voltage_time_sel() operation. +*/ +int regulator_set_voltage_time_sel (struct regulator_dev *rdev, +unsigned int old_selector, +unsigned int new_selector) +{ +int old_volt, new_volt; +/* sanity check */ if (!rdev->desc->ops->list_voltage)return -EINVAL ;
@@ -3059,7 +3097,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, old_volt = rdev->desc->ops->list_voltage (rdev, old_selector); new_volt = rdev->desc->ops->list_voltage (rdev, new_selector); -return DIV_ROUND_UP (abs (new_volt - old_volt), ramp_delay); +return regulator_set_voltage_time_op (rdev, old_volt, new_volt); }EXPORT_SYMBOL_GPL (regulator_set_voltage_time_sel);
include/linux/regulator/driver.h +8 -0
@@ -113,6 +113,10 @@ struct regulator_linear_range {* stabilise after being enabled, in microseconds. * @set_ramp_delay: Set the ramp delay for the regulator. The driver should * select ramp delay equal to or less than(closest) ramp_delay. +* @set_voltage_time: Time taken for the regulator voltage output voltage +* to stabilise after being set to a new value, in microseconds. +* The function provides the from and to voltage, the function +* should return the worst case. * @set_voltage_time_sel: Time taken for the regulator voltage output voltage * to stabilise after being set to a new value, in microseconds. * The function provides the from and to voltage selector, the
@@ -168,6 +172,8 @@ struct regulator_ops {/* Time taken to enable or set voltage on the regulator */ int (*enable_time) (struct regulator_dev *);int (*set_ramp_delay) (struct regulator_dev *,int ramp_delay); +int (*set_voltage_time) (struct regulator_dev *, +int old_uV,int new_uV);int (*set_voltage_time_sel) (struct regulator_dev *,unsigned int old_selector,unsigned int new_selector);
@@ -461,6 +467,8 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);int regulator_is_enabled_regmap (struct regulator_dev *rdev);int regulator_enable_regmap (struct regulator_dev *rdev);int regulator_disable_regmap (struct regulator_dev *rdev); +int regulator_set_voltage_time_op (struct regulator_dev *rdev, +int old_uV,int new_uV);int regulator_set_voltage_time_sel (struct regulator_dev *rdev,unsigned int old_selector,unsigned int new_selector);
Signature · 1 line
2.8.0.rc3.226.g39d4020
Mark Brown
maintainerQuoted 2 lines · Matthias Kaehlcke
The new op is analogous to
set_voltage_time_sel. It can be used by regulators that don't have a table of discrete voltages. The function
I've only got patch 1 in this series, what's going on here?
Mark Brown
maintainerQuoted 5 lines · Mark Brown
Quoted 2 lines · Matthias Kaehlcke
The new op is analogous to
set_voltage_time_sel. It can be used by regulators that don't have a table of discrete voltages. The functionI've only got patch 1 in this series, what's going on here?
Actually it turns out I have at least three copies of this, one copy of what's hopefully the reset of the series and none of them are threaded together :( You probably want to take a look at your patch sending setup...
Quoted 5 lines · Mark Brown
Quoted 3 lines · Mark Brown
Quoted 2 lines · Matthias Kaehlcke
The new op is analogous to
set_voltage_time_sel. It can be used by regulators that don't have a table of discrete voltages. The function
Quoted 7 lines
Quoted 1 line
I've only got patch 1 in this series, what's going on here?
Actually it turns out I have at least three copies of this, one copy of what's hopefully the reset of the series and none of them are threaded together :( You probably want to take a look at your patch sending setup...
On my side it looked as if the first time the patch wasn't sent at all and apparently the second one contained an unintended attachment.
Sorry for the spam :(