diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
index 93f970f..8aeaf6e 100644
--- a/arch/arm/mach-omap2/pm33xx.c
+++ b/arch/arm/mach-omap2/pm33xx.c
@@ -47,10 +47,14 @@
 void (*am33xx_do_wfi_sram)(void);
 
 static void __iomem *am33xx_emif_base;
+static void __iomem *am33xx_i2c1_base;
 static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm;
 static struct clockdomain *gfx_l4ls_clkdm;
 static struct omap_hwmod *usb_oh, *cpsw_oh, *tptc0_oh, *tptc1_oh, *tptc2_oh;
+static struct omap_hwmod *i2c1_oh;
 static struct wkup_m3_context *wkup_m3;
+static char *am33xx_i2c_sleep_sequence;
+static char *am33xx_i2c_wake_sequence;
 
 static DECLARE_COMPLETION(wkup_m3_sync);
 
@@ -88,7 +92,10 @@ static int am33xx_pm_suspend(void)
 	/* Try to put GFX to sleep */
 	pwrdm_set_next_fpwrst(gfx_pwrdm, PWRDM_FUNC_PWRST_OFF);
 
+	/* We need I2C to send the sleep/wake sequences */
+	omap_hwmod_enable(i2c1_oh);
 	ret = cpu_suspend(0, am33xx_do_sram_idle);
+	omap_hwmod_idle(i2c1_oh);
 
 	status = pwrdm_read_fpwrst(gfx_pwrdm);
 	if (status != PWRDM_FUNC_PWRST_OFF)
@@ -403,6 +410,101 @@ void __iomem *am33xx_get_emif_base(void)
 	return am33xx_emif_base;
 }
 
+void am33xx_fill_i2c_sequences(char *sleep, size_t ssz, char *wake, size_t wsz)
+{
+	if (am33xx_i2c_sleep_sequence)
+		memcpy(sleep, am33xx_i2c_sleep_sequence, ssz);
+	else
+		memset(sleep, 0, ssz);
+
+	if (am33xx_i2c_wake_sequence)
+		memcpy(wake, am33xx_i2c_wake_sequence, wsz);
+	else
+		memset(wake, 0, wsz);
+}
+
+static int __init am33xx_map_i2c1(void)
+{
+	am33xx_i2c1_base = ioremap(AM33XX_I2C0_BASE, SZ_4K);
+
+	if (!am33xx_i2c1_base)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void __iomem *am33xx_get_i2c1_base(void)
+{
+	return am33xx_i2c1_base;
+}
+
+static int __init am33xx_setup_sleep_sequence(void)
+{
+	int ret;
+	int sz;
+	const void *prop;
+	struct device *dev;
+	struct omap_hwmod *oh;
+
+	ret = am33xx_map_i2c1();
+	if (ret) {
+		pr_err("Could not ioremap i2c1\n");
+		return ret;
+	}
+
+	oh = omap_hwmod_lookup("i2c1");
+	if (!oh)
+		return -ENODEV;
+
+	/*
+	 * We put the device tree node in the I2C controller that will
+	 * be sending the sequence.
+	 */
+	dev = omap_device_get_by_hwmod_name("i2c1");
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+
+	prop = of_get_property(dev->of_node, "sleep_sequence", &sz);
+	if (prop) {
+		if (sz >= i2c_sleep_sequence_sz) {
+			pr_err("Sleep sequence too long\n");
+			return -EINVAL;
+		}
+		am33xx_i2c_sleep_sequence = kzalloc(i2c_sleep_sequence_sz,
+								GFP_KERNEL);
+		if (!am33xx_i2c_sleep_sequence)
+			return -ENOMEM;
+		memcpy(am33xx_i2c_sleep_sequence, prop, sz);
+	}
+
+	prop = of_get_property(dev->of_node, "wake_sequence", &sz);
+	if (prop) {
+		if (sz >= i2c_wake_sequence_sz) {
+			pr_err("Wake sequence too long\n");
+			ret = -EINVAL;
+			goto cleanup_sleep;
+		}
+		am33xx_i2c_wake_sequence = kzalloc(i2c_wake_sequence_sz,
+								GFP_KERNEL);
+		if (!am33xx_i2c_wake_sequence) {
+			ret = -ENOMEM;
+			goto cleanup_sleep;
+		}
+		memcpy(am33xx_i2c_wake_sequence, prop, sz);
+	}
+
+	/* Only take the I2C controller out of idle if a sequence exists */
+	if (am33xx_i2c_sleep_sequence || am33xx_i2c_wake_sequence)
+		i2c1_oh = oh;
+
+	return 0;
+
+cleanup_sleep:
+	kfree(am33xx_i2c_sleep_sequence);
+	am33xx_i2c_sleep_sequence = NULL;
+	return ret;
+}
+
 int __init am33xx_pm_init(void)
 {
 	int ret;
@@ -449,6 +551,12 @@ int __init am33xx_pm_init(void)
 		goto err;
 	}
 
+	ret = am33xx_setup_sleep_sequence();
+	if (ret) {
+		pr_err("Error fetching I2C sleep/wake sequence\n");
+		goto err;
+	}
+
 	(void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
 
 	/* CEFUSE domain can be turned off post bootup */
diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
index 13a2c85..69616ee 100644
--- a/arch/arm/mach-omap2/pm33xx.h
+++ b/arch/arm/mach-omap2/pm33xx.h
@@ -28,6 +28,9 @@ struct wkup_m3_context {
 	u8			state;
 };
 
+extern u32 i2c_sleep_sequence_sz;
+extern u32 i2c_wake_sequence_sz;
+
 #ifdef CONFIG_SUSPEND
 static void am33xx_m3_state_machine_reset(void);
 #else
@@ -52,5 +55,25 @@ extern void __iomem *am33xx_get_emif_base(void);
 
 #define AM33XX_OCMC_END			0x40310000
 #define AM33XX_EMIF_BASE		0x4C000000
+#define AM33XX_I2C0_BASE		0x44E0B000
+
+#define OMAP_I2C_STAT_BB		(1 << 12)
+#define OMAP_I2C_STAT_ARDY		(1 << 2)
+#define OMAP_I2C_STAT_NACK		(1 << 1)
+#define OMAP_I2C_STAT_AL		(1 << 0)
+
+#define OMAP_I2C_CON_EN			(1 << 15)
+#define OMAP_I2C_CON_MST		(1 << 10)
+#define OMAP_I2C_CON_TRX		(1 << 9)
+#define OMAP_I2C_CON_STP		(1 << 1)
+#define OMAP_I2C_CON_STT		(1 << 0)
+
+#define OMAP_I2C_STAT_RAW_REG		0x24
+#define OMAP_I2C_STAT_REG		0x28
+#define OMAP_I2C_IRQENABLE_CLR		0x30
+#define OMAP_I2C_CNT_REG		0x98
+#define OMAP_I2C_DATA_REG		0x9c
+#define OMAP_I2C_CON_REG		0xa4
+#define OMAP_I2C_SA_REG			0xac
 
 #endif
diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
index 98fa76c..85453e8 100644
--- a/arch/arm/mach-omap2/sleep33xx.S
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -95,6 +95,19 @@ ENTRY(am33xx_do_wfi)
 	/* Save it for later use */
 	str	r0, emif_addr_virt
 
+	/* Get/save the i2c1 base virtual address */
+	ldr	r0, i2c_addr_func
+	blx	r0
+	str	r0, i2c_addr_virt
+
+	/* Load the sleep/wake sequences */
+	ldr	r4, i2c_sequence_func
+	adrl	r0, i2c_sleep_sequence
+	ldr	r1, i2c_sleep_sequence_sz
+	adrl	r2, i2c_wake_sequence
+	ldr	r3, i2c_sleep_sequence_sz
+	blx	r4
+
 	/* This ensures isb */
 	ldr	r0, dcache_flush
 	blx	r0
@@ -187,6 +200,10 @@ put_pll_bypass:
 	pll_bypass	per, virt_per_clk_mode, virt_per_idlest, per_val
 	pll_bypass	mpu, virt_mpu_clk_mode, virt_mpu_idlest, mpu_val
 
+	/* Write the sleep sequence, abort on suspend on error */
+	bl	am33xx_i2c_write_sleep
+	bne	wfi_abort
+
 	dsb
 	dmb
 	isb
@@ -209,6 +226,8 @@ put_pll_bypass:
 	nop
 
 	/* We come here in case of an abort due to a late interrupt */
+wfi_abort:
+	bl	am33xx_i2c_write_wake
 
 	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
 	ldr	r1, virt_mpu_clkctrl
@@ -312,6 +331,9 @@ ENTRY(am33xx_resume_offset)
 	.word . - am33xx_do_wfi
 
 ENTRY(am33xx_resume_from_deep_sleep)
+
+	bl	am33xx_i2c_write_wake
+
 	/* Take the PLLs out of LP_BYPASS */
 	pll_lock	mpu, phys_mpu_clk_mode, phys_mpu_idlest, mpu_val
 	pll_lock	per, phys_per_clk_mode, phys_per_idlest, per_val
@@ -415,6 +437,87 @@ wait_resume:
 	ldr	pc, resume_addr
 ENDPROC(am33xx_resume_from_deep_sleep)
 
+am33xx_i2c_write_wake:
+	adrl	r3, i2c_wake_sequence
+	ldr	r2, i2c_addr_phys
+	b	am33xx_i2c_write
+
+am33xx_i2c_write_sleep:
+	adrl	r3, i2c_sleep_sequence
+	ldr	r2, i2c_addr_virt
+
+am33xx_i2c_write:
+	/* Early out check, don't touch the hardware */
+	ldrb	r4, [r3]
+	tst	r4, r4
+	moveq	pc, lr
+
+	/* Disable all event interrupts */
+	movw	r5, #0xffff
+	strh	r5, [r2, #OMAP_I2C_IRQENABLE_CLR]
+
+i2c_transfer:
+	/* Ack all events */
+	strh	r5, [r2, #OMAP_I2C_STAT_REG]
+
+	/*
+	 * Loop through the I2C transfer list, a zero byte transfer
+	 * terminates the list.
+	 */
+	ldrb	r4, [r3], #1
+	tst	r4, r4
+	moveq	pc, lr
+
+	/* Wait for bus to be ready */
+	mov	r0, #1000
+1:	ldr	r1, [r2, #OMAP_I2C_STAT_RAW_REG]
+	tst	r1, #OMAP_I2C_STAT_BB
+	beq	bb_cleared
+	subs	r0, r0, #1
+	bne	1b
+	b	i2c_err
+
+bb_cleared:
+	/* Ack all events */
+	strh	r5, [r2, #OMAP_I2C_STAT_REG]
+
+	/* Program I2C target address */
+	ldrb	r1, [r3], #1
+	strh	r1, [r2, #OMAP_I2C_SA_REG]
+
+	/* Store the length of the transfer */
+	strh	r4, [r2, #OMAP_I2C_CNT_REG]
+
+	/* Configure I2C controller for transfer */
+	movw	r1, #(OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_TRX | \
+			OMAP_I2C_CON_STP | OMAP_I2C_CON_STT)
+	strh	r1, [r2, #OMAP_I2C_CON_REG]
+
+	/* Ack all events */
+	strh	r5, [r2, #OMAP_I2C_STAT_REG]
+
+	/* Write out data */
+1:	ldrb	r1, [r3], #1
+	strh	r1, [r2, #OMAP_I2C_DATA_REG]
+	subs	r4, r4, #1
+	bne 	1b
+
+	/* Wait for transfer to complete */
+	mov	r0, #1000
+1:	ldr	r1, [r2, #OMAP_I2C_STAT_RAW_REG]
+	tst	r1, #OMAP_I2C_STAT_NACK
+	tsteq	r1, #OMAP_I2C_STAT_AL
+	bne	i2c_err
+	tst	r1, #OMAP_I2C_STAT_ARDY
+	bne	i2c_transfer
+	subs	r0, r0, #1
+	bne	1b
+
+i2c_err:
+	/* ACK all events and return NE */
+	strh	r5, [r2, #OMAP_I2C_STAT_REG]
+	movs	r0, #1
+	mov	pc, lr
 
 /*
  * Local variables
@@ -578,6 +681,87 @@ clk_mode_ddr_val:
 clk_mode_core_val:
 	.word	0xDEADBEEF
 
+i2c_addr_func:
+	.word	am33xx_get_i2c1_base
+i2c_addr_virt:
+	.word	0xDEADBEEF
+i2c_addr_phys:
+	.word	AM33XX_I2C0_BASE
+
+/* I2C sleep/wake sequence data */
+i2c_sleep_sequence:
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+ENTRY(i2c_sleep_sequence_sz)
+	.word	. - i2c_sleep_sequence
+i2c_wake_sequence:
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+	.word	0xDEADBEEF
+ENTRY(i2c_wake_sequence_sz)
+	.word	. - i2c_wake_sequence
+i2c_sequence_func:
+	.word	am33xx_fill_i2c_sequences
+
 	.align 3
 ENTRY(am33xx_do_wfi_sz)
 	.word	. - am33xx_do_wfi
