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.
Signed-off-by Matthias Kaehlcke <[email protected]>
---
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