aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/s5m8767.c
diff options
context:
space:
mode:
authorSangbeom Kim <sbkim73@samsung.com>2012-06-17 20:49:20 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-06-19 07:06:32 -0400
commitc848bc8538cd29e92223d5e72e8fb60e6f2e176e (patch)
treea7a40e51dc2efafc2a25959cb05f7bf9cf71732e /drivers/regulator/s5m8767.c
parent852abad238da723efac29f3e78dd768c18d6a062 (diff)
regulator: s5m8767a: Support AP watchdog reset operation
The S5M8767A can't know status of ap reset. So, After AP watchdog reset, AP can't boot normally. Problem can be happened like below condition. - AP Bootable lowest voltage(vdd_arm): 0.9v - AP DVFS voltage table: 0.8v, 0.9v, 1.0v - During AP works on lowest voltage(0.8V), watchdog reset is asserted - AP can't boot, because vdd arm is still 0.8v Solution - Basic concept: After ap watchdog reset, GPIO configuration is changed by default value - S5M8767A has function of voltage control with gpio (8 levels with 3 gpios) - Set bootable voltage on level 0 -> can work with default gpio configuration - In the probing, Change voltage control level from level 0 to level 1 - Execute normal dvfs operation on level 1 - After watchdog reset, ap gpio is set by default value - PMIC operation mode is changed by ap reset (level1 -> level0) - Regardless of previous vdd_arm voltage, AP always can be booted. Signed-off-by: Sangbeom Kim <sbkim73@samsung.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/s5m8767.c')
-rw-r--r--drivers/regulator/s5m8767.c137
1 files changed, 93 insertions, 44 deletions
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index a4a3c7eefd1f..fd89574c405c 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -41,6 +41,7 @@ struct s5m8767_info {
41 u8 buck3_vol[8]; 41 u8 buck3_vol[8];
42 u8 buck4_vol[8]; 42 u8 buck4_vol[8];
43 int buck_gpios[3]; 43 int buck_gpios[3];
44 int buck_ds[3];
44 int buck_gpioindex; 45 int buck_gpioindex;
45}; 46};
46 47
@@ -283,17 +284,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
283 reg = S5M8767_REG_BUCK1CTRL2; 284 reg = S5M8767_REG_BUCK1CTRL2;
284 break; 285 break;
285 case S5M8767_BUCK2: 286 case S5M8767_BUCK2:
286 reg = S5M8767_REG_BUCK2DVS1; 287 reg = S5M8767_REG_BUCK2DVS2;
287 if (s5m8767->buck2_gpiodvs) 288 if (s5m8767->buck2_gpiodvs)
288 reg += s5m8767->buck_gpioindex; 289 reg += s5m8767->buck_gpioindex;
289 break; 290 break;
290 case S5M8767_BUCK3: 291 case S5M8767_BUCK3:
291 reg = S5M8767_REG_BUCK3DVS1; 292 reg = S5M8767_REG_BUCK3DVS2;
292 if (s5m8767->buck3_gpiodvs) 293 if (s5m8767->buck3_gpiodvs)
293 reg += s5m8767->buck_gpioindex; 294 reg += s5m8767->buck_gpioindex;
294 break; 295 break;
295 case S5M8767_BUCK4: 296 case S5M8767_BUCK4:
296 reg = S5M8767_REG_BUCK4DVS1; 297 reg = S5M8767_REG_BUCK4DVS2;
297 if (s5m8767->buck4_gpiodvs) 298 if (s5m8767->buck4_gpiodvs)
298 reg += s5m8767->buck_gpioindex; 299 reg += s5m8767->buck_gpioindex;
299 break; 300 break;
@@ -512,7 +513,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
512 struct regulator_config config = { }; 513 struct regulator_config config = { };
513 struct regulator_dev **rdev; 514 struct regulator_dev **rdev;
514 struct s5m8767_info *s5m8767; 515 struct s5m8767_info *s5m8767;
515 int i, ret, size; 516 int i, ret, size, buck_init;
516 517
517 if (!pdata) { 518 if (!pdata) {
518 dev_err(pdev->dev.parent, "Platform data not supplied\n"); 519 dev_err(pdev->dev.parent, "Platform data not supplied\n");
@@ -563,12 +564,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
563 s5m8767->buck_gpios[0] = pdata->buck_gpios[0]; 564 s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
564 s5m8767->buck_gpios[1] = pdata->buck_gpios[1]; 565 s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
565 s5m8767->buck_gpios[2] = pdata->buck_gpios[2]; 566 s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
567 s5m8767->buck_ds[0] = pdata->buck_ds[0];
568 s5m8767->buck_ds[1] = pdata->buck_ds[1];
569 s5m8767->buck_ds[2] = pdata->buck_ds[2];
570
566 s5m8767->ramp_delay = pdata->buck_ramp_delay; 571 s5m8767->ramp_delay = pdata->buck_ramp_delay;
567 s5m8767->buck2_ramp = pdata->buck2_ramp_enable; 572 s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
568 s5m8767->buck3_ramp = pdata->buck3_ramp_enable; 573 s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
569 s5m8767->buck4_ramp = pdata->buck4_ramp_enable; 574 s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
570 s5m8767->opmode = pdata->opmode; 575 s5m8767->opmode = pdata->opmode;
571 576
577 buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
578 pdata->buck2_init,
579 pdata->buck2_init +
580 buck_voltage_val2.step);
581
582 s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init);
583
584 buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
585 pdata->buck3_init,
586 pdata->buck3_init +
587 buck_voltage_val2.step);
588
589 s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init);
590
591 buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
592 pdata->buck4_init,
593 pdata->buck4_init +
594 buck_voltage_val2.step);
595
596 s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init);
597
572 for (i = 0; i < 8; i++) { 598 for (i = 0; i < 8; i++) {
573 if (s5m8767->buck2_gpiodvs) { 599 if (s5m8767->buck2_gpiodvs) {
574 s5m8767->buck2_vol[i] = 600 s5m8767->buck2_vol[i] =
@@ -598,48 +624,71 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
598 } 624 }
599 } 625 }
600 626
601 if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || 627 if (gpio_is_valid(pdata->buck_gpios[0]) &&
602 pdata->buck4_gpiodvs) { 628 gpio_is_valid(pdata->buck_gpios[1]) &&
603 if (gpio_is_valid(pdata->buck_gpios[0]) && 629 gpio_is_valid(pdata->buck_gpios[2])) {
604 gpio_is_valid(pdata->buck_gpios[1]) && 630 ret = gpio_request(pdata->buck_gpios[0], "S5M8767 SET1");
605 gpio_is_valid(pdata->buck_gpios[2])) { 631 if (ret == -EBUSY)
606 ret = gpio_request(pdata->buck_gpios[0], 632 dev_warn(&pdev->dev, "Duplicated gpio request"
607 "S5M8767 SET1"); 633 " for SET1\n");
608 if (ret == -EBUSY) 634
609 dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n"); 635 ret = gpio_request(pdata->buck_gpios[1], "S5M8767 SET2");
610 636 if (ret == -EBUSY)
611 ret = gpio_request(pdata->buck_gpios[1], 637 dev_warn(&pdev->dev, "Duplicated gpio request"
612 "S5M8767 SET2"); 638 " for SET2\n");
613 if (ret == -EBUSY) 639
614 dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n"); 640 ret = gpio_request(pdata->buck_gpios[2], "S5M8767 SET3");
615 641 if (ret == -EBUSY)
616 ret = gpio_request(pdata->buck_gpios[2], 642 dev_warn(&pdev->dev, "Duplicated gpio request"
617 "S5M8767 SET3"); 643 " for SET3\n");
618 if (ret == -EBUSY) 644 /* SET1 GPIO */
619 dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n"); 645 gpio_direction_output(pdata->buck_gpios[0],
620 /* SET1 GPIO */ 646 (s5m8767->buck_gpioindex >> 2) & 0x1);
621 gpio_direction_output(pdata->buck_gpios[0], 647 /* SET2 GPIO */
622 (s5m8767->buck_gpioindex >> 2) & 0x1); 648 gpio_direction_output(pdata->buck_gpios[1],
623 /* SET2 GPIO */ 649 (s5m8767->buck_gpioindex >> 1) & 0x1);
624 gpio_direction_output(pdata->buck_gpios[1], 650 /* SET3 GPIO */
625 (s5m8767->buck_gpioindex >> 1) & 0x1); 651 gpio_direction_output(pdata->buck_gpios[2],
626 /* SET3 GPIO */ 652 (s5m8767->buck_gpioindex >> 0) & 0x1);
627 gpio_direction_output(pdata->buck_gpios[2], 653 ret = 0;
628 (s5m8767->buck_gpioindex >> 0) & 0x1); 654
629 ret = 0; 655 } else {
630 } else { 656 dev_err(&pdev->dev, "GPIO NOT VALID\n");
631 dev_err(&pdev->dev, "GPIO NOT VALID\n"); 657 ret = -EINVAL;
632 ret = -EINVAL; 658 return ret;
633 return ret;
634 }
635 } 659 }
636 660
637 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 661 ret = gpio_request(pdata->buck_ds[0], "S5M8767 DS2");
638 (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); 662 if (ret == -EBUSY)
639 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 663 dev_warn(&pdev->dev, "Duplicated gpio request for DS2\n");
640 (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); 664
641 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 665 ret = gpio_request(pdata->buck_ds[1], "S5M8767 DS3");
642 (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); 666 if (ret == -EBUSY)
667 dev_warn(&pdev->dev, "Duplicated gpio request for DS3\n");
668
669 ret = gpio_request(pdata->buck_ds[2], "S5M8767 DS4");
670 if (ret == -EBUSY)
671 dev_warn(&pdev->dev, "Duplicated gpio request for DS4\n");
672
673 /* DS2 GPIO */
674 gpio_direction_output(pdata->buck_ds[0], 0x0);
675 /* DS3 GPIO */
676 gpio_direction_output(pdata->buck_ds[1], 0x0);
677 /* DS4 GPIO */
678 gpio_direction_output(pdata->buck_ds[2], 0x0);
679
680 if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
681 pdata->buck4_gpiodvs) {
682 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
683 (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1),
684 1 << 1);
685 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
686 (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1),
687 1 << 1);
688 s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
689 (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1),
690 1 << 1);
691 }
643 692
644 /* Initialize GPIO DVS registers */ 693 /* Initialize GPIO DVS registers */
645 for (i = 0; i < 8; i++) { 694 for (i = 0; i < 8; i++) {