regulator: core: Allow specific minimal selector for starting linear mapping
PATCH 1/4 regulator: core: Allow specific minimal selector for starting linear mapping
Some drivers (at least 3 drivers) have such variant of linear mapping that the first few selectors are invalid and the reset are linear mapping. Let's support this case in core.
This patch adds linear_min_sel in struct regulator_desc,
so we can allow specific minimal selector for starting linear mapping. Then extends regulator_[map|list]_voltage_linear() to support this feature.
Note that for selectors less than min_linear_index, we need count them to n_voltages so regulator_list_voltage() won't fail while checking the boundary for selector before calling list_voltage callback.
--- drivers/regulator/core.c | 6 ++++++ include/linux/regulator/driver.h | 2 ++ 2 files changed, 8 insertions(+)
drivers/regulator/core.c +6 -0
@@ -1897,6 +1897,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, {if (selector >= rdev->desc->n_voltages)return -EINVAL ; +if (selector < rdev->desc->linear_min_sel) +return 0 ; + + selector -= rdev->desc->linear_min_sel;return rdev->desc->min_uV + (rdev->desc->uV_step * selector); }
@@ -2125,6 +2129,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,if (ret <0 )return ret; + ret += rdev->desc->linear_min_sel; +/* Map back into a voltage to verify we're still in bounds */ voltage = rdev->desc->ops->list_voltage (rdev, ret);if (voltage < min_uV || voltage > max_uV)
include/linux/regulator/driver.h +2 -0
@@ -187,6 +187,7 @@ enum regulator_type {* * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) +* @linear_min_sel: Minimal selector for starting linear mapping * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @volt_table: Voltage mapping table (if table based mapping) *
@@ -210,6 +211,7 @@ struct regulator_desc {unsigned int min_uV;unsigned int uV_step; +unsigned int linear_min_sel;unsigned int ramp_delay;const unsigned int *volt_table;
Signature · 1 line
1.7.9.5
PATCH 2/4 regulator: da9055: Use linear_min_sel and regulator_[map|list]_voltage_linear
--- drivers/regulator/da9055-regulator.c | 55 +++++----------------------------- 1 file changed, 8 insertions(+), 47 deletions(-)
drivers/regulator/da9055-regulator.c +8 -47
@@ -57,7 +57,6 @@ struct da9055_volt_reg {int reg_a;int reg_b;int sl_shift; -int v_offset;int v_mask;int v_shift; };
@@ -201,41 +200,6 @@ static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,return -EINVAL ; } -static int da9055_list_voltage (struct regulator_dev *rdev,unsigned selector) -{ -struct da9055_regulator *regulator =rdev_get_drvdata (rdev); -struct da9055_regulator_info *info = regulator->info; - -if (selector >= rdev->desc->n_voltages) -return -EINVAL ; - -if (selector < info->volt.v_offset) -return 0 ; - - selector -= info->volt.v_offset; -return rdev->desc->min_uV + (rdev->desc->uV_step * selector); -} - -static int da9055_map_voltage (struct regulator_dev *rdev,int min_uV, -int max_uV) -{ -struct da9055_regulator *regulator =rdev_get_drvdata (rdev); -struct da9055_regulator_info *info = regulator->info; -int sel, voltage; - -if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - - sel =DIV_ROUND_UP (min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - sel += info->volt.v_offset; - - voltage =da9055_list_voltage (rdev, sel); -if (voltage < min_uV || voltage > max_uV) -return -EINVAL ; - -return sel; -} -static int da9055_regulator_get_voltage_sel (struct regulator_dev *rdev) {struct da9055_regulator *regulator =rdev_get_drvdata (rdev);
@@ -264,10 +228,7 @@ static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)return ret; sel = (ret & volt.v_mask); -if (sel <= volt.v_offset) -return 0 ; -else -return sel; +return sel; } static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
@@ -328,7 +289,7 @@ static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,return ret; } - ret =da9055_map_voltage (rdev, uV, uV); + ret =regulator_map_voltage_linear (rdev, uV, uV);if (ret <0 )return ret;
@@ -371,8 +332,8 @@ static struct regulator_ops da9055_buck_ops = { .get_voltage_sel = da9055_regulator_get_voltage_sel, .set_voltage_sel = da9055_regulator_set_voltage_sel, - .list_voltage = da9055_list_voltage, - .map_voltage = da9055_map_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap,
@@ -389,8 +350,8 @@ static struct regulator_ops da9055_ldo_ops = { .get_voltage_sel = da9055_regulator_get_voltage_sel, .set_voltage_sel = da9055_regulator_set_voltage_sel, - .list_voltage = da9055_list_voltage, - .map_voltage = da9055_map_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap,
@@ -414,6 +375,7 @@ static struct regulator_ops da9055_ldo_ops = { .enable_mask = 1, \ .min_uV = (min) * 1000,\ .uV_step = (step) * 1000,\ + .linear_min_sel = (voffset),\ .owner = THIS_MODULE,\ },\ .conf = {\
@@ -425,7 +387,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ - .v_offset = (voffset),\ .v_mask = (1 << (vbits)) - 1,\ .v_shift = (vbits),\ },\
@@ -443,6 +404,7 @@ static struct regulator_ops da9055_ldo_ops = { .enable_mask = 1,\ .min_uV = (min) * 1000,\ .uV_step = (step) * 1000,\ + .linear_min_sel = (voffset),\ .owner = THIS_MODULE,\ },\ .conf = {\
@@ -454,7 +416,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ - .v_offset = (voffset),\ .v_mask = (1 << (vbits)) - 1,\ .v_shift = (vbits),\ },\
Signature · 1 line
1.7.9.5
PATCH 3/4 regulator: palmas: Use linear_min_sel and regulator_[map|list]_voltage_linear
In reply to Axel Lin--- drivers/regulator/palmas-regulator.c | 37 +++++----------------------------- 1 file changed, 5 insertions(+), 32 deletions(-)
drivers/regulator/palmas-regulator.c +5 -32
@@ -436,44 +436,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)return !!(reg); } -static int palmas_list_voltage_ldo (struct regulator_dev *dev, -unsigned selector) -{ -if (!selector) -return 0 ; - -/* voltage is 0.85V + (selector * 0.05v) */ -return 850000 + (selector *50000 ); -} - -static int palmas_map_voltage_ldo (struct regulator_dev *rdev, -int min_uV,int max_uV) -{ -int ret, voltage; - -if (min_uV ==0 ) -return 0 ; - -if (min_uV <900000 ) - min_uV =900000 ; - ret =DIV_ROUND_UP (min_uV -900000 ,50000 ) +1 ; - -/* Map back into a voltage to verify we're still in bounds */ - voltage =palmas_list_voltage_ldo (rdev, ret); -if (voltage < min_uV || voltage > max_uV) -return -EINVAL ; - -return ret; -} -static struct regulator_ops palmas_ops_ldo = { .is_enabled = palmas_is_enabled_ldo, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = palmas_list_voltage_ldo, - .map_voltage = palmas_map_voltage_ldo, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, };/*
@@ -821,6 +791,9 @@ static int palmas_probe(struct platform_device *pdev) pmic->desc[id].type =REGULATOR_VOLTAGE ; pmic->desc[id].owner =THIS_MODULE ; + pmic->desc[id].min_uV =900000 ; + pmic->desc[id].uV_step =50000 ; + pmic->desc[id].linear_min_sel =1 ; pmic->desc[id].vsel_reg =PALMAS_BASE_TO_REG (PALMAS_LDO_BASE , palmas_regs_info[id].vsel_addr); pmic->desc[id].vsel_mask =PALMAS_LDO1_VOLTAGE_VSEL_MASK ;
Signature · 1 line
1.7.9.5
PATCH 4/4 regulator: tps51632: Use linear_min_sel and regulator_[map|list]_voltage_linear
In reply to Axel Lin--- drivers/regulator/tps51632-regulator.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
drivers/regulator/tps51632-regulator.c +5 -10
@@ -106,29 +106,23 @@ static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev) } vsel = data &TPS51632_VOUT_MASK ; - -if (vsel <TPS51632_MIN_VSEL ) -return 0 ; -else -return vsel -TPS51632_MIN_VSEL ; +return vsel; }static int tps51632_dcdc_set_voltage_sel (struct regulator_dev *rdev,unsigned selector) {struct tps51632_chip *tps =rdev_get_drvdata (rdev); -int vsel;int ret;unsigned int reg =TPS51632_VOLTAGE_SELECT_REG ;if (tps->enable_pwm_dvfs) reg =TPS51632_VOLTAGE_BASE_REG ; - vsel = selector +TPS51632_MIN_VSEL ; -if (vsel >TPS51632_MAX_VSEL ) +if (selector >TPS51632_MAX_VSEL )return -EINVAL ; - ret =regmap_write (tps->regmap, reg, vsel); + ret =regmap_write (tps->regmap, reg, selector);if (ret <0 )dev_err (tps->dev,"reg write failed, err %d\n" , ret);return ret;
@@ -254,7 +248,8 @@ static int tps51632_probe(struct i2c_client *client, tps->desc.ramp_delay =TPS51632_DEFAULT_RAMP_DELAY ; tps->desc.min_uV =TPS51632_MIN_VOLATGE ; tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV; - tps->desc.n_voltages = (TPS51632_MAX_VSEL -TPS51632_MIN_VSEL ) +1 ; + tps->desc.linear_min_sel =TPS51632_MIN_VSEL ; + tps->desc.n_voltages =TPS51632_MAX_VSEL +1 ; tps->desc.ops = &tps51632_dcdc_ops; tps->desc.type =REGULATOR_VOLTAGE ; tps->desc.owner =THIS_MODULE ;
Signature · 1 line
1.7.9.5
Re: [RFC/RFT][PATCH 4/4] regulator: tps51632: Use linear_min_sel and regulator_[map|list]_voltage_linear
Quoted 1 line · Axel Lin
Signed-off-by Axel Lin <[email protected]
I got some conflicts applying this one, can you check my topic/min branch please? The conflicts looked pretty trivial but too easy for me to fat finger doing them by hand.
Quoted 3 lines · Axel Lin
Some drivers (at least 3 drivers) have such variant of linear mapping that the first few selectors are invalid and the reset are linear mapping. Let's support this case in core.
Cool! Applied all except patch 4, thanks.