power: twl4030: Power off support

This adds support for powering off (the omap3 SoC) from the twl4030. This is
especially useful when the kernel does not actually power off the device using
this method but reboots and leaves it up to the bootloader to actually turn the
power off.
Reviewed-by: Tom Rini <trini@konsulko.com>
Acked-by: Przemyslaw Marczak <p.marczak@samsung.com>
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c
index 7f1fdd1..8866bf1 100644
--- a/drivers/power/twl4030.c
+++ b/drivers/power/twl4030.c
@@ -46,6 +46,66 @@
 }
 
 /*
+ * Power off
+ */
+void twl4030_power_off(void)
+{
+	u8 data;
+
+	/* PM master unlock (CFG and TST keys) */
+
+	data = 0xCE;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_PROTECT_KEY, data);
+	data = 0xEC;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_PROTECT_KEY, data);
+
+	/* VBAT start disable */
+
+	twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
+			    TWL4030_PM_MASTER_CFG_P1_TRANSITION, &data);
+	data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_CFG_P1_TRANSITION, data);
+
+	twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
+			    TWL4030_PM_MASTER_CFG_P2_TRANSITION, &data);
+	data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_CFG_P2_TRANSITION, data);
+
+	twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
+			    TWL4030_PM_MASTER_CFG_P3_TRANSITION, &data);
+	data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_CFG_P3_TRANSITION, data);
+
+	/* High jitter for PWRANA2 */
+
+	twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
+			    TWL4030_PM_MASTER_CFG_PWRANA2, &data);
+	data &= ~(TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT0_LOWV |
+		  TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT1_LOWV);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_CFG_PWRANA2, data);
+
+	/* PM master lock */
+
+	data = 0xFF;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_PROTECT_KEY, data);
+
+	/* Power off */
+
+	twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
+			    TWL4030_PM_MASTER_P1_SW_EVENTS, &data);
+	data |= TWL4030_PM_MASTER_SW_EVENTS_DEVOFF;
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
+			     TWL4030_PM_MASTER_P1_SW_EVENTS, data);
+}
+
+/*
  * Set Device Group and Voltage
  */
 void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val,
diff --git a/include/twl4030.h b/include/twl4030.h
index 50f8da8..2d0ca18 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -129,14 +129,6 @@
 #define TWL4030_PM_MASTER_BB_CFG			0x6D
 #define TWL4030_PM_MASTER_MISC_TST			0x6E
 #define TWL4030_PM_MASTER_TRIM1				0x6F
-/* P[1-3]_SW_EVENTS */
-#define TWL4030_PM_MASTER_SW_EVENTS_STOPON_PWRON	(1 << 6)
-#define TWL4030_PM_MASTER_SW_EVENTS_STOPON_SYSEN	(1 << 5)
-#define TWL4030_PM_MASTER_SW_EVENTS_ENABLE_WARMRESET	(1 << 4)
-#define TWL4030_PM_MASTER_SW_EVENTS_LVL_WAKEUP		(1 << 3)
-#define TWL4030_PM_MASTER_SW_EVENTS_DEVACT		(1 << 2)
-#define TWL4030_PM_MASTER_SW_EVENTS_DEVSLP		(1 << 1)
-#define TWL4030_PM_MASTER_SW_EVENTS_DEVOFF		(1 << 0)
 
 /* Power bus message definitions */
 
@@ -207,6 +199,28 @@
 /* Power Reference */
 #define RES_Main_Ref            28
 
+/* P[1-3]_SW_EVENTS */
+#define TWL4030_PM_MASTER_SW_EVENTS_STOPON_PWRON	(1 << 6)
+#define TWL4030_PM_MASTER_SW_EVENTS_STOPON_SYSEN	(1 << 5)
+#define TWL4030_PM_MASTER_SW_EVENTS_ENABLE_WARMRESET	(1 << 4)
+#define TWL4030_PM_MASTER_SW_EVENTS_LVL_WAKEUP		(1 << 3)
+#define TWL4030_PM_MASTER_SW_EVENTS_DEVACT		(1 << 2)
+#define TWL4030_PM_MASTER_SW_EVENTS_DEVSLP		(1 << 1)
+#define TWL4030_PM_MASTER_SW_EVENTS_DEVOFF		(1 << 0)
+
+/* Power transition */
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_PWON	(1 << 0)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_CHG	(1 << 1)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_USB	(1 << 2)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_RTC	(1 << 3)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT	(1 << 4)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBUS	(1 << 5)
+#define TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_SWBUG	(1 << 7)
+
+/* PWRANA2 */
+#define TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT0_LOWV	(1 << 1)
+#define TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT1_LOWV	(1 << 2)
+
 #define TOTAL_RESOURCES		28
 /*
  * Power Bus Message Format ... these can be sent individually by Linux,
@@ -645,6 +659,8 @@
 
 /* For hardware resetting */
 void twl4030_power_reset_init(void);
+/* For power off */
+void twl4030_power_off(void);
 /* For setting device group and voltage */
 void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val,
 			     u8 dev_grp, u8 dev_grp_sel);