Skip to content

Commit

Permalink
regulator: twl: Fix checking voltage range in twl6030smps_set_voltage()
Browse files Browse the repository at this point in the history
The voltage selection logic is supposed to find the samllest voltage falls
within specified range. When using equation to calculate vsel, we need to
ensure the requested min_uV meet the range of using the equation.
Otherwise we may select a voltage that is out of specified range.

For example, in the case vsel = 62 means select voltage of 2100000uV.
What we want is to ensure the requested min_uV <= 2100000 rather than checking
max_uV >= 2100000. And this also means in the case min_uV > 2100000, vsel = 62
does not meet the request.

Also calling twl6030smps_list_voltage() for all cases to ensure the selected
voltage still in bounds.

Signed-off-by: Axel Lin <axel.lin@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Axel Lin authored and Mark Brown committed Aug 28, 2012
1 parent 13407ea commit 78292f4
Showing 1 changed file with 16 additions and 20 deletions.
36 changes: 16 additions & 20 deletions drivers/regulator/twl-regulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,32 +762,28 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = 0;
int vsel = 0, calc_uV;

switch (info->flags) {
case 0:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
int calc_uV;
vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
else if ((min_uV > 1900000) && (min_uV <= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
else if ((min_uV > 1800000) && (min_uV <= 1900000))
vsel = 61;
else if ((min_uV > 1500000) && (max_uV >= 1800000))
else if ((min_uV > 1500000) && (min_uV <= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
else if ((min_uV > 1350000) && (min_uV <= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
else if ((min_uV > 1300000) && (min_uV <= 1350000))
vsel = 58;
else
return -EINVAL;
Expand All @@ -796,25 +792,21 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
int calc_uV;
vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
else if ((min_uV > 1900000) && (min_uV <= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
else if ((min_uV > 1800000) && (min_uV <= 1900000))
vsel = 61;
else if ((min_uV > 1350000) && (max_uV >= 1800000))
else if ((min_uV > 1350000) && (min_uV <= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
else if ((min_uV > 1350000) && (min_uV <= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
else if ((min_uV > 1300000) && (min_uV <= 1350000))
vsel = 58;
else
return -EINVAL;
Expand All @@ -830,13 +822,17 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
if (min_uV == 0) {
vsel = 0;
} else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
} else if ((min_uV >= 2161000) && (min_uV <= 4321000)) {
vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
vsel++;
}
break;
}

calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;

*selector = vsel;

return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
Expand Down

0 comments on commit 78292f4

Please sign in to comment.