diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 87099bb6de692771ce7d26a720f0bec5836d6beb..3c8bb8f0304d364be6bbb2715cd6ea1352ad2a01 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -50,6 +50,7 @@
 #include "sdrc.h"
 #include "sram.h"
 #include "control.h"
+#include "vc.h"
 
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
@@ -288,6 +289,9 @@ void omap_sram_idle(void)
 		}
 	}
 
+	/* Configure PMIC signaling for I2C4 or sys_off_mode */
+	omap3_vc_set_pmic_signaling(core_next_state);
+
 	omap3_intc_prepare_idle();
 
 	/*
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index cebad565ed374ae58230c1bba48465ba7fd3a487..106132db532b56165072f923e261dfbd4c4a7db4 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -123,8 +123,15 @@
 #define OMAP3430_GLOBAL_SW_RST_SHIFT			1
 #define OMAP3430_GLOBAL_COLD_RST_SHIFT			0
 #define OMAP3430_GLOBAL_COLD_RST_MASK			(1 << 0)
-#define OMAP3430_SEL_OFF_MASK				(1 << 3)
-#define OMAP3430_AUTO_OFF_MASK				(1 << 2)
+#define OMAP3430_PRM_VOLTCTRL_SEL_VMODE			(1 << 4)
+#define OMAP3430_PRM_VOLTCTRL_SEL_OFF			(1 << 3)
+#define OMAP3430_PRM_VOLTCTRL_AUTO_OFF			(1 << 2)
+#define OMAP3430_PRM_VOLTCTRL_AUTO_RET			(1 << 1)
+#define OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP		(1 << 0)
 #define OMAP3430_SETUP_TIME2_MASK			(0xffff << 16)
 #define OMAP3430_SETUP_TIME1_MASK			(0xffff << 0)
+#define OMAP3430_PRM_POLCTRL_OFFMODE_POL		(1 << 3)
+#define OMAP3430_PRM_POLCTRL_CLKOUT_POL			(1 << 2)
+#define OMAP3430_PRM_POLCTRL_CLKREQ_POL			(1 << 1)
+#define OMAP3430_PRM_POLCTRL_EXTVOL_POL			(1 << 0)
 #endif
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 49ac7977e03e5457e3c4855fb60bc3c3f76cdc9c..705eb35d7b351f7cf628e70d524bfe6e17e1afa4 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -220,6 +220,87 @@ static inline u32 omap_usec_to_32k(u32 usec)
 	return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
 }
 
+struct omap3_vc {
+	struct voltagedomain *vd;
+	u32 voltctrl;
+};
+static struct omap3_vc vc;
+
+void omap3_vc_set_pmic_signaling(int core_next_state)
+{
+	struct voltagedomain *vd = vc.vd;
+	u32 voltctrl;
+
+	voltctrl = vc.voltctrl;
+	switch (core_next_state) {
+	case PWRDM_POWER_OFF:
+		voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_RET |
+			      OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
+		voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_OFF;
+		break;
+	case PWRDM_POWER_RET:
+	default:
+		voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_OFF |
+			      OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
+		voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_RET;
+		break;
+	}
+	if (voltctrl != vc.voltctrl) {
+		vd->write(voltctrl, OMAP3_PRM_VOLTCTRL_OFFSET);
+		vc.voltctrl = voltctrl;
+	}
+}
+
+#define PRM_POLCTRL_TWL_MASK	(OMAP3430_PRM_POLCTRL_CLKREQ_POL | \
+					OMAP3430_PRM_POLCTRL_CLKREQ_POL)
+#define PRM_POLCTRL_TWL_VAL	OMAP3430_PRM_POLCTRL_CLKREQ_POL
+
+/*
+ * Configure signal polarity for sys_clkreq and sys_off_mode pins
+ * as the default values are wrong and can cause the system to hang
+ * if any twl4030 scripts are loaded.
+ */
+static void __init omap3_vc_init_pmic_signaling(struct voltagedomain *voltdm)
+{
+	u32 val;
+
+	if (vc.vd)
+		return;
+
+	vc.vd = voltdm;
+
+	val = voltdm->read(OMAP3_PRM_POLCTRL_OFFSET);
+	if (!(val & OMAP3430_PRM_POLCTRL_CLKREQ_POL) ||
+	    (val & OMAP3430_PRM_POLCTRL_CLKREQ_POL)) {
+		val |= OMAP3430_PRM_POLCTRL_CLKREQ_POL;
+		val &= ~OMAP3430_PRM_POLCTRL_OFFMODE_POL;
+		pr_debug("PM: fixing sys_clkreq and sys_off_mode polarity to 0x%x\n",
+			 val);
+		voltdm->write(val, OMAP3_PRM_POLCTRL_OFFSET);
+	}
+
+	/*
+	 * By default let's use I2C4 signaling for retention idle
+	 * and sys_off_mode pin signaling for off idle. This way we
+	 * have sys_clk_req pin go down for retention and both
+	 * sys_clk_req and sys_off_mode pins will go down for off
+	 * idle. And we can also scale voltages to zero for off-idle.
+	 * Note that no actual voltage scaling during off-idle will
+	 * happen unless the board specific twl4030 PMIC scripts are
+	 * loaded.
+	 */
+	val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
+	if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
+		val |= OMAP3430_PRM_VOLTCTRL_SEL_OFF;
+		pr_debug("PM: setting voltctrl sys_off_mode signaling to 0x%x\n",
+			 val);
+		voltdm->write(val, OMAP3_PRM_VOLTCTRL_OFFSET);
+	}
+	vc.voltctrl = val;
+
+	omap3_vc_set_pmic_signaling(PWRDM_POWER_ON);
+}
+
 /* Set oscillator setup time for omap3 */
 static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
 {
@@ -292,7 +373,7 @@ static void omap3_set_off_timings(struct voltagedomain *voltdm)
 
 	/* check if sys_off_mode is used to control off-mode voltages */
 	val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
-	if (!(val & OMAP3430_SEL_OFF_MASK)) {
+	if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
 		/* No, omap is controlling them over I2C */
 		omap3_set_i2c_timings(voltdm, true);
 		return;
@@ -337,6 +418,7 @@ static void omap3_set_off_timings(struct voltagedomain *voltdm)
 
 static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
 {
+	omap3_vc_init_pmic_signaling(voltdm);
 	omap3_set_off_timings(voltdm);
 }
 
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index 91c8d75bf2ead7759b7d19d3eb7a569c8e89422f..cdbdd78e755e2c60347ca66ca378d5895a9ab87e 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -117,6 +117,9 @@ extern struct omap_vc_param omap4_mpu_vc_data;
 extern struct omap_vc_param omap4_iva_vc_data;
 extern struct omap_vc_param omap4_core_vc_data;
 
+void omap3_vc_set_pmic_signaling(int core_next_state);
+
+
 void omap_vc_init_channel(struct voltagedomain *voltdm);
 int omap_vc_pre_scale(struct voltagedomain *voltdm,
 		      unsigned long target_volt,