Skip to content

Commit

Permalink
regulator: Report actual configured voltage to set_voltage()
Browse files Browse the repository at this point in the history
Change the interface used by set_voltage() to report the selected value
to the regulator core in terms of a selector used by list_voltage().
This allows the regulator core to know the voltage that was chosen
without having to do an explict get_voltage(), which would be much more
expensive as it will generally access hardware.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
  • Loading branch information
broonie authored and Liam Girdwood committed Jan 12, 2011
1 parent 63cee94 commit 3a93f2a
Show file tree
Hide file tree
Showing 27 changed files with 202 additions and 79 deletions.
3 changes: 2 additions & 1 deletion drivers/regulator/88pm8607.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
}

static int pm8607_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV, unsigned *selector)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
uint8_t val, mask;
Expand All @@ -263,6 +263,7 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
ret = choose_voltage(rdev, min_uV, max_uV);
if (ret < 0)
return -EINVAL;
*selector = ret;
val = (uint8_t)(ret << info->vol_shift);
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

Expand Down
5 changes: 4 additions & 1 deletion drivers/regulator/ab3100.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ static int ab3100_get_best_voltage_index(struct regulator_dev *reg,
}

static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned *selector)
{
struct ab3100_regulator *abreg = reg->reg_data;
u8 regval;
Expand All @@ -373,6 +374,8 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
if (bestindex < 0)
return bestindex;

*selector = bestindex;

err = abx500_get_register_interruptible(abreg->dev, 0,
abreg->regreg, &regval);
if (err) {
Expand Down
5 changes: 4 additions & 1 deletion drivers/regulator/ab8500.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev,
}

static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned *selector)
{
int regulator_id, ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
Expand All @@ -232,6 +233,8 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
return ret;
}

*selector = ret;

/* set the registers for the request */
ret = abx500_mask_and_set_register_interruptible(info->dev,
info->voltage_bank, info->voltage_reg,
Expand Down
14 changes: 12 additions & 2 deletions drivers/regulator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,13 +723,16 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
struct regulator_ops *ops = rdev->desc->ops;
const char *name = rdev_get_name(rdev);
int ret;
unsigned selector;

/* do we need to apply the constraint voltage */
if (rdev->constraints->apply_uV &&
rdev->constraints->min_uV == rdev->constraints->max_uV &&
ops->set_voltage) {
ret = ops->set_voltage(rdev,
rdev->constraints->min_uV, rdev->constraints->max_uV);
rdev->constraints->min_uV,
rdev->constraints->max_uV,
&selector);
if (ret < 0) {
printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
__func__,
Expand Down Expand Up @@ -1625,6 +1628,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{
struct regulator_dev *rdev = regulator->rdev;
int ret;
unsigned selector;

mutex_lock(&rdev->mutex);

Expand All @@ -1640,7 +1644,13 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
goto out;
regulator->min_uV = min_uV;
regulator->max_uV = max_uV;
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV);

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, selector);
else
selector = -1;

out:
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
Expand Down
17 changes: 12 additions & 5 deletions drivers/regulator/da903x.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ static inline int check_range(struct da903x_regulator_info *info,

/* DA9030/DA9034 common operations */
static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV, unsigned *selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
Expand All @@ -119,6 +119,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
}

val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

Expand Down Expand Up @@ -187,7 +188,8 @@ static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector)

/* DA9030 specific operations */
static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned *selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da903x_dev = to_da903x_dev(rdev);
Expand All @@ -200,6 +202,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
}

val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
Expand All @@ -214,7 +217,8 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
}

static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned *selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da903x_dev = to_da903x_dev(rdev);
Expand All @@ -234,6 +238,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
val = (min_uV - thresh + info->step_uV - 1) / info->step_uV;
}

*selector = val;
val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

Expand Down Expand Up @@ -263,7 +268,7 @@ static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)

/* DA9034 specific operations */
static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV, unsigned *selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
Expand All @@ -276,6 +281,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
}

val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

Expand All @@ -289,7 +295,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
}

static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV, unsigned *selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
Expand All @@ -302,6 +308,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,

val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val);
*selector = val;
val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

Expand Down
6 changes: 5 additions & 1 deletion drivers/regulator/isl6271a-regulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ static int isl6271a_get_voltage(struct regulator_dev *dev)
return data;
}

static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV)
static int isl6271a_set_voltage(struct regulator_dev *dev,
int minuV, int maxuV,
unsigned *selector)
{
struct isl_pmic *pmic = rdev_get_drvdata(dev);
int vsel, err, data;
Expand All @@ -78,6 +80,8 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV)
/* Convert the microvolts to data for the chip */
data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP;

*selector = data;

mutex_lock(&pmic->mtx);

err = i2c_smbus_write_byte(pmic->client, data);
Expand Down
10 changes: 8 additions & 2 deletions drivers/regulator/lp3971.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
}

static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned int *selector)
{
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3971_LDO1;
Expand All @@ -187,6 +188,8 @@ static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
return -EINVAL;

*selector = val;

return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
val << LDO_VOL_CONTR_SHIFT(ldo));
Expand Down Expand Up @@ -256,7 +259,8 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
}

static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned int *selector)
{
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3971_DCDC1;
Expand All @@ -277,6 +281,8 @@ static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
return -EINVAL;

*selector = val;

ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
BUCK_TARGET_VOL_MASK, val);
if (ret)
Expand Down
10 changes: 8 additions & 2 deletions drivers/regulator/lp3972.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
}

static int lp3972_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned int *selector)
{
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3972_LDO1;
Expand All @@ -313,6 +314,8 @@ static int lp3972_ldo_set_voltage(struct regulator_dev *dev,
if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol)
return -EINVAL;

*selector = val;

shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo);
ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo),
LP3972_LDO_VOL_MASK(ldo) << shift, val << shift);
Expand Down Expand Up @@ -416,7 +419,8 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
}

static int lp3972_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
int min_uV, int max_uV,
unsigned int *selector)
{
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3972_DCDC1;
Expand All @@ -438,6 +442,8 @@ static int lp3972_dcdc_set_voltage(struct regulator_dev *dev,
vol_map[val] > max_vol)
return -EINVAL;

*selector = val;

ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck),
LP3972_BUCK_VOL_MASK, val);
if (ret)
Expand Down
30 changes: 15 additions & 15 deletions drivers/regulator/max1586.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,28 @@ static int max1586_v3_calc_voltage(struct max1586_data *max1586,
return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL);
}

static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV)
static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
struct i2c_client *client = max1586->client;
unsigned range_uV = max1586->max_uV - max1586->min_uV;
unsigned selector;
u8 v3_prog;

if (min_uV > max1586->max_uV || max_uV < max1586->min_uV)
return -EINVAL;
if (min_uV < max1586->min_uV)
min_uV = max1586->min_uV;

selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL +
*selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL +
range_uV - 1) / range_uV;
if (max1586_v3_calc_voltage(max1586, selector) > max_uV)
if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
return -EINVAL;

dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
max1586_v3_calc_voltage(max1586, selector) / 1000);
max1586_v3_calc_voltage(max1586, *selector) / 1000);

v3_prog = I2C_V3_SELECT | (u8) selector;
v3_prog = I2C_V3_SELECT | (u8) *selector;
return i2c_smbus_write_byte(client, v3_prog);
}

Expand All @@ -110,10 +110,10 @@ static int max1586_v6_calc_voltage(unsigned selector)
return voltages_uv[selector];
}

static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV)
static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *selector)
{
struct i2c_client *client = rdev_get_drvdata(rdev);
unsigned selector;
u8 v6_prog;

if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
Expand All @@ -122,21 +122,21 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV)
return -EINVAL;

if (min_uV < 1800000)
selector = 0;
*selector = 0;
else if (min_uV < 2500000)
selector = 1;
*selector = 1;
else if (min_uV < 3000000)
selector = 2;
*selector = 2;
else if (min_uV >= 3000000)
selector = 3;
*selector = 3;

if (max1586_v6_calc_voltage(selector) > max_uV)
if (max1586_v6_calc_voltage(*selector) > max_uV)
return -EINVAL;

dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
max1586_v6_calc_voltage(selector) / 1000);
max1586_v6_calc_voltage(*selector) / 1000);

v6_prog = I2C_V6_SELECT | (u8) selector;
v6_prog = I2C_V6_SELECT | (u8) *selector;
return i2c_smbus_write_byte(client, v6_prog);
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/regulator/max8649.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ static int max8649_get_voltage(struct regulator_dev *rdev)
}

static int max8649_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
int min_uV, int max_uV, unsigned *selector)
{
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
unsigned char data, mask;
Expand All @@ -168,6 +168,7 @@ static int max8649_set_voltage(struct regulator_dev *rdev,
data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1)
/ MAX8649_DCDC_STEP;
mask = MAX8649_VOL_MASK;
*selector = data & mask;

return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
}
Expand Down
Loading

0 comments on commit 3a93f2a

Please sign in to comment.