aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/wm831x-dcdc.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-25 17:20:34 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2011-07-28 05:20:49 -0400
commit88cda60e512373ca18a663ee66dc2550800223eb (patch)
treee825ff9214a04d60611e5aad36b421f70b2aa2c0 /drivers/regulator/wm831x-dcdc.c
parentc439b8f46ee79147139e124621dbc9e1e7804655 (diff)
regulator: Improve WM831x DVS VSEL selection algorithm
Rather than using the maximum voltage we get passed to select the DVS voltage to use remember the highest voltage we've ever seen. This improves how the driver works when the consumer permits higher voltages than it will ever selects in order to support the widest possible voltage range. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers/regulator/wm831x-dcdc.c')
-rw-r--r--drivers/regulator/wm831x-dcdc.c52
1 files changed, 15 insertions, 37 deletions
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 2c5d54b026c9..bd3531d8b2ac 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -267,23 +267,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
267 return vsel; 267 return vsel;
268} 268}
269 269
270static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev,
271 int min_uV, int max_uV)
272{
273 u16 vsel;
274
275 if (max_uV < 600000 || max_uV > 1800000)
276 return -EINVAL;
277
278 vsel = ((max_uV - 600000) / 12500) + 8;
279
280 if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV ||
281 wm831x_buckv_list_voltage(rdev, vsel) < max_uV)
282 return -EINVAL;
283
284 return vsel;
285}
286
287static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) 270static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
288{ 271{
289 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); 272 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
@@ -338,28 +321,23 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
338 if (ret < 0) 321 if (ret < 0)
339 return ret; 322 return ret;
340 323
341 /* Set the high voltage as the DVS voltage. This is optimised 324 /*
342 * for CPUfreq usage, most processors will keep the maximum 325 * If this VSEL is higher than the last one we've seen then
343 * voltage constant and lower the minimum with the frequency. */ 326 * remember it as the DVS VSEL. This is optimised for CPUfreq
344 vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV); 327 * usage where we want to get to the highest voltage very
345 if (vsel < 0) { 328 * quickly.
346 /* This should never happen - at worst the same vsel 329 */
347 * should be chosen */ 330 if (vsel > dcdc->dvs_vsel) {
348 WARN_ON(vsel < 0); 331 ret = wm831x_set_bits(wm831x, dvs_reg,
349 return 0; 332 WM831X_DC1_DVS_VSEL_MASK,
333 dcdc->dvs_vsel);
334 if (ret == 0)
335 dcdc->dvs_vsel = vsel;
336 else
337 dev_warn(wm831x->dev,
338 "Failed to set DCDC DVS VSEL: %d\n", ret);
350 } 339 }
351 340
352 /* Don't bother if it's the same VSEL we're already using */
353 if (vsel == dcdc->on_vsel)
354 return 0;
355
356 ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel);
357 if (ret == 0)
358 dcdc->dvs_vsel = vsel;
359 else
360 dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n",
361 ret);
362
363 return 0; 341 return 0;
364} 342}
365 343