aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/twl4030-power.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2014-11-02 13:07:56 -0500
committerLee Jones <lee.jones@linaro.org>2014-11-10 10:22:04 -0500
commit481c7f868c6d855f31a29c69b445ac4aee9625a6 (patch)
treefec379479db753f58dacf53a59f29ec355e8a292 /drivers/mfd/twl4030-power.c
parentc0acb8144bd6d8d88aee1dab33364b7353e9a903 (diff)
mfd: twl4030-power: Fix poweroff with PM configuration enabled
Commit e7cd1d1eb16f ("mfd: twl4030-power: Add generic reset configuration") enabled configuring the PM features for twl4030. This caused poweroff command to fail on devices that have the BCI charger on twl4030 wired, or have power wired for VBUS. Instead of powering off, the device reboots. This is because voltage is detected on charger or VBUS with the default bits enabled for the power transition registers. To fix the issue, let's just clear VBUS and CHG bits as we want poweroff command to keep the system powered off. Fixes: e7cd1d1eb16f ("mfd: twl4030-power: Add generic reset configuration") Cc: stable@vger.kernel.org # v3.16+ Reported-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/twl4030-power.c')
-rw-r--r--drivers/mfd/twl4030-power.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index cf92a6d1c532..50f9091bcd38 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -44,6 +44,15 @@ static u8 twl4030_start_script_address = 0x2b;
44#define PWR_DEVSLP BIT(1) 44#define PWR_DEVSLP BIT(1)
45#define PWR_DEVOFF BIT(0) 45#define PWR_DEVOFF BIT(0)
46 46
47/* Register bits for CFG_P1_TRANSITION (also for P2 and P3) */
48#define STARTON_SWBUG BIT(7) /* Start on watchdog */
49#define STARTON_VBUS BIT(5) /* Start on VBUS */
50#define STARTON_VBAT BIT(4) /* Start on battery insert */
51#define STARTON_RTC BIT(3) /* Start on RTC */
52#define STARTON_USB BIT(2) /* Start on USB host */
53#define STARTON_CHG BIT(1) /* Start on charger */
54#define STARTON_PWON BIT(0) /* Start on PWRON button */
55
47#define SEQ_OFFSYNC (1 << 0) 56#define SEQ_OFFSYNC (1 << 0)
48 57
49#define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) 58#define PHY_TO_OFF_PM_MASTER(p) (p - 0x36)
@@ -606,6 +615,44 @@ twl4030_power_configure_resources(const struct twl4030_power_data *pdata)
606 return 0; 615 return 0;
607} 616}
608 617
618static int twl4030_starton_mask_and_set(u8 bitmask, u8 bitvalues)
619{
620 u8 regs[3] = { TWL4030_PM_MASTER_CFG_P1_TRANSITION,
621 TWL4030_PM_MASTER_CFG_P2_TRANSITION,
622 TWL4030_PM_MASTER_CFG_P3_TRANSITION, };
623 u8 val;
624 int i, err;
625
626 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
627 TWL4030_PM_MASTER_PROTECT_KEY);
628 if (err)
629 goto relock;
630 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
631 TWL4030_PM_MASTER_KEY_CFG2,
632 TWL4030_PM_MASTER_PROTECT_KEY);
633 if (err)
634 goto relock;
635
636 for (i = 0; i < sizeof(regs); i++) {
637 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER,
638 &val, regs[i]);
639 if (err)
640 break;
641 val = (~bitmask & val) | (bitmask & bitvalues);
642 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
643 val, regs[i]);
644 if (err)
645 break;
646 }
647
648 if (err)
649 pr_err("TWL4030 Register access failed: %i\n", err);
650
651relock:
652 return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
653 TWL4030_PM_MASTER_PROTECT_KEY);
654}
655
609/* 656/*
610 * In master mode, start the power off sequence. 657 * In master mode, start the power off sequence.
611 * After a successful execution, TWL shuts down the power to the SoC 658 * After a successful execution, TWL shuts down the power to the SoC
@@ -615,6 +662,11 @@ void twl4030_power_off(void)
615{ 662{
616 int err; 663 int err;
617 664
665 /* Disable start on charger or VBUS as it can break poweroff */
666 err = twl4030_starton_mask_and_set(STARTON_VBUS | STARTON_CHG, 0);
667 if (err)
668 pr_err("TWL4030 Unable to configure start-up\n");
669
618 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF, 670 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
619 TWL4030_PM_MASTER_P1_SW_EVENTS); 671 TWL4030_PM_MASTER_P1_SW_EVENTS);
620 if (err) 672 if (err)