aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/wm831x-dcdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/wm831x-dcdc.c')
-rw-r--r--drivers/regulator/wm831x-dcdc.c126
1 files changed, 65 insertions, 61 deletions
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index a0982e809851..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
@@ -456,27 +434,6 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
456 if (!pdata || !pdata->dvs_gpio) 434 if (!pdata || !pdata->dvs_gpio)
457 return; 435 return;
458 436
459 switch (pdata->dvs_control_src) {
460 case 1:
461 ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
462 break;
463 case 2:
464 ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
465 break;
466 default:
467 dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
468 pdata->dvs_control_src, dcdc->name);
469 return;
470 }
471
472 ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
473 WM831X_DC1_DVS_SRC_MASK, ctrl);
474 if (ret < 0) {
475 dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
476 dcdc->name, ret);
477 return;
478 }
479
480 ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); 437 ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
481 if (ret < 0) { 438 if (ret < 0) {
482 dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", 439 dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
@@ -498,17 +455,57 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
498 } 455 }
499 456
500 dcdc->dvs_gpio = pdata->dvs_gpio; 457 dcdc->dvs_gpio = pdata->dvs_gpio;
458
459 switch (pdata->dvs_control_src) {
460 case 1:
461 ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
462 break;
463 case 2:
464 ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
465 break;
466 default:
467 dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
468 pdata->dvs_control_src, dcdc->name);
469 return;
470 }
471
472 /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL
473 * to make bootstrapping a bit smoother.
474 */
475 if (!dcdc->dvs_vsel) {
476 ret = wm831x_set_bits(wm831x,
477 dcdc->base + WM831X_DCDC_DVS_CONTROL,
478 WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);
479 if (ret == 0)
480 dcdc->dvs_vsel = dcdc->on_vsel;
481 else
482 dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",
483 ret);
484 }
485
486 ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
487 WM831X_DC1_DVS_SRC_MASK, ctrl);
488 if (ret < 0) {
489 dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
490 dcdc->name, ret);
491 }
501} 492}
502 493
503static __devinit int wm831x_buckv_probe(struct platform_device *pdev) 494static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
504{ 495{
505 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 496 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
506 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 497 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
507 int id = pdev->id % ARRAY_SIZE(pdata->dcdc); 498 int id;
508 struct wm831x_dcdc *dcdc; 499 struct wm831x_dcdc *dcdc;
509 struct resource *res; 500 struct resource *res;
510 int ret, irq; 501 int ret, irq;
511 502
503 if (pdata && pdata->wm831x_num)
504 id = (pdata->wm831x_num * 10) + 1;
505 else
506 id = 0;
507 id = pdev->id - id;
508
512 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); 509 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
513 510
514 if (pdata == NULL || pdata->dcdc[id] == NULL) 511 if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -545,7 +542,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
545 } 542 }
546 dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK; 543 dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
547 544
548 ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); 545 ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);
549 if (ret < 0) { 546 if (ret < 0) {
550 dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret); 547 dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
551 goto err; 548 goto err;
@@ -709,11 +706,17 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
709{ 706{
710 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 707 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
711 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 708 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
712 int id = pdev->id % ARRAY_SIZE(pdata->dcdc); 709 int id;
713 struct wm831x_dcdc *dcdc; 710 struct wm831x_dcdc *dcdc;
714 struct resource *res; 711 struct resource *res;
715 int ret, irq; 712 int ret, irq;
716 713
714 if (pdata && pdata->wm831x_num)
715 id = (pdata->wm831x_num * 10) + 1;
716 else
717 id = 0;
718 id = pdev->id - id;
719
717 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); 720 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
718 721
719 if (pdata == NULL || pdata->dcdc[id] == NULL) 722 if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -1046,3 +1049,4 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
1046MODULE_LICENSE("GPL"); 1049MODULE_LICENSE("GPL");
1047MODULE_ALIAS("platform:wm831x-buckv"); 1050MODULE_ALIAS("platform:wm831x-buckv");
1048MODULE_ALIAS("platform:wm831x-buckp"); 1051MODULE_ALIAS("platform:wm831x-buckp");
1052MODULE_ALIAS("platform:wm831x-epe");