This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359 lpddr1 and linux suspend/resume

Hi,

I am working on a custom board with lpddr1 memory. It is running fully except for suspend and resume functionality.

I have implemented lpddr1 paths in am33xx_do_wfi() and am33xx_resume_from_deep_sleep(). I started from copying the DDR2 paths and modifying them slightly to accommodate the differences (ddr_io etc).

Patch that applies on top of v3.2_AM335xPSP_04.06.00.08 is included.

However with this patch I can enter deepsleep0 but not resume from it. I don't know what goes wrong. I suspect there is something in the resume sequence that is erroneous.

Can anyone assist?

Patch:

diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
index 34d5366..ce1abb5 100644
--- a/arch/arm/mach-omap2/pm33xx.c
+++ b/arch/arm/mach-omap2/pm33xx.c
@@ -514,9 +514,10 @@ static int __init am33xx_pm_init(void)
  */
 	if (reg == MEM_TYPE_DDR2)
 		suspend_cfg_param_list[SUSP_VTP_CTRL_VAL] = SUSP_VTP_CTRL_DDR2;
-	else
+	else if (reg == MEM_TYPE_DDR3)
 		suspend_cfg_param_list[SUSP_VTP_CTRL_VAL] = SUSP_VTP_CTRL_DDR3;
-
+	else if (reg == MEM_TYPE_LPDDR1)
+		suspend_cfg_param_list[SUSP_VTP_CTRL_VAL] = SUSP_VTP_CTRL_LPDDR1;
 
 	/* Get Board Id */
 	evm_id = am335x_evm_get_id();
diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
index adf56bf..e11f468 100644
--- a/arch/arm/mach-omap2/pm33xx.h
+++ b/arch/arm/mach-omap2/pm33xx.h
@@ -113,9 +113,13 @@ static struct am33xx_padconf_regs am33xx_lp_padconf[] = {
 #define DDR_DATA0_IOCTRL	(AM33XX_CTRL_BASE + 0x1440)
 #define DDR_DATA1_IOCTRL	(AM33XX_CTRL_BASE + 0x1444)
 
+#define MEM_TYPE_DDR1		0
+#define MEM_TYPE_LPDDR1		1
 #define MEM_TYPE_DDR2		2
+#define MEM_TYPE_DDR3		3
 
 #define SUSP_VTP_CTRL_DDR2	0x10117
 #define SUSP_VTP_CTRL_DDR3	0x0
+#define SUSP_VTP_CTRL_LPDDR1	0x0
 
 #endif
diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
index 4af2e3a..80d7d58 100644
--- a/arch/arm/mach-omap2/sleep33xx.S
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -169,10 +169,12 @@ wait_sc_\num:
 	dmb
 	isb
 
-	/* Different sleep sequences for DDR2 and DDR3 */
+	/* Different sleep sequences for LPDDR1, DDR2 and DDR3 */
 	ldr	r6, mem_type
 	cmp	r6, #MEM_TYPE_DDR2
 	beq	ddr2_susp_seq
+	cmp	r6, #MEM_TYPE_LPDDR1
+	beq	lpddr1_susp_seq
 
 	/* DDR3 suspend sequence */
 
@@ -257,6 +259,7 @@ wait_emif_disable3:
 	orr	r1, #1
 	str	r1, [r0]
 
+	/* DDR3 suspend ends */
 	b	put_pll_bypass
 
 ddr2_susp_seq:
@@ -269,11 +272,11 @@ ddr2_susp_seq:
 	str	r2, [r1]
 
 	ldr	r1, virt_emif_clkctrl
-wait_emif_disable:
+ddr2_wait_emif_disable:
 	ldr	r2, [r1]
 	ldr	r3, module_disabled_val
 	cmp	r2, r3
-	bne	wait_emif_disable
+	bne	ddr2_wait_emif_disable
 
 	/* DDR3 reset override and mDDR mode selection */
 	ldr	r0, virt_ddr_io_ctrl
@@ -300,6 +303,52 @@ wait_emif_disable:
 	orr	r1, #1
 	str	r1, [r0]
 
+	/* ddr2_susp_seq ends */
+	b	put_pll_bypass
+
+lpddr1_susp_seq:
+	ddr_self_refresh	3
+
+	/* Disable EMIF at this point */
+	ldr	r1, virt_emif_clkctrl
+	ldr	r2, [r1]
+	bic	r2, r2, #(3 << 0)
+	str	r2, [r1]
+
+	ldr	r1, virt_emif_clkctrl
+lpddr1_wait_emif_disable:
+	ldr	r2, [r1]
+	ldr	r3, module_disabled_val
+	cmp	r2, r3
+	bne	lpddr1_wait_emif_disable
+
+	/* DDR3 reset override and mDDR mode selection */
+	ldr	r0, virt_ddr_io_ctrl
+	mov	r1, #(0x9 << 28)
+	str	r1, [r0]
+
+	/* Weak pull down for DQ, DM */
+	ldr	r1, virt_ddr_io_pull1
+	ldr	r2, susp_io_pull_data
+	str	r2, [r1]
+
+	ldr	r1, virt_ddr_io_pull2
+	ldr	r2, susp_io_pull_data
+	str	r2, [r1]
+
+	/* Disable VTP */
+	ldr	r1, virt_ddr_vtp_ctrl
+	ldr	r2, susp_vtp_ctrl_val
+	str	r2, [r1]
+
+	/* Enable SRAM LDO ret mode */
+	ldr	r0, virt_sram_ldo_addr
+	ldr	r1, [r0]
+	orr	r1, #1
+	str	r1, [r0]
+
+	/* End lpddr1_susp_seq */
+
 put_pll_bypass:
 	/* Put the PLLs in bypass mode */
 	pll_bypass	core, virt_core_clk_mode, virt_core_idlest, core_val
@@ -339,6 +388,8 @@ put_pll_bypass:
 	ldr	r6, mem_type
 	cmp	r6, #MEM_TYPE_DDR2
 	beq	ddr2_resume_seq_abt
+	cmp	r6, #MEM_TYPE_LPDDR1
+	beq	lpddr1_resume_seq_abt
 
 	/* DDR3 resume path */
 
@@ -475,16 +526,77 @@ config_vtp_abt:
 	orr	r1, #1
 	str	r1, [r0]
 
-poll_vtp_ready_abt:
+poll_vtp_ready_abt2:
 	ldr	r1, [r0]	@ poll for VTP ready
 	tst	r1, #(1 << 5)
-	beq	poll_vtp_ready_abt
+	beq	poll_vtp_ready_abt2
 
 	/* DDR3 reset override and mDDR mode clear */
 	ldr	r0, virt_ddr_io_ctrl
 	mov	r1, #0
 	str	r1, [r0]
 
+	b	emif_self_refresh_dis
+
+	/* LPDDR1 resume path */
+lpddr1_resume_seq_abt:
+	/* Disable SRAM LDO ret mode */
+	ldr	r0, virt_sram_ldo_addr
+	ldr	r1, [r0]
+	bic	r1, #1
+	str	r1, [r0]
+
+	/* Restore the pull for DQ, DM */
+	ldr	r1, virt_ddr_io_pull1
+	ldr	r2, resume_io_pull_data
+	str	r2, [r1]
+
+	ldr	r1, virt_ddr_io_pull2
+	ldr	r2, resume_io_pull_data
+	str	r2, [r1]
+
+	/* Enable EMIF */
+	ldr	r1, virt_emif_clkctrl
+	mov	r2, #0x2
+	str	r2, [r1]
+lpddr1_wait_emif_enable:
+	ldr	r3, [r1]
+	cmp	r2, r3
+	bne	lpddr1_wait_emif_enable
+
+	/* Enable VTP */
+lpddr1_config_vtp_abt:
+	ldr	r0, virt_ddr_vtp_ctrl
+	ldr	r1, [r0]
+	mov	r2, #0x0	@ clear the register
+	str	r2, [r0]
+	mov	r2, #0x6	@ write the filter value
+	str	r2, [r0]
+
+	ldr	r1, [r0]
+	ldr	r2, vtp_enable	@ set the enable bit
+	orr	r2, r2, r1
+	str	r2, [r0]
+
+	ldr	r1, [r0]	@ toggle the CLRZ bit
+	bic	r1, #1
+	str	r1, [r0]
+
+	ldr	r1, [r0]
+	orr	r1, #1
+	str	r1, [r0]
+
+lpddr1_poll_vtp_ready_abt:
+	ldr	r1, [r0]	@ poll for VTP ready
+	tst	r1, #(1 << 5)
+	beq	lpddr1_poll_vtp_ready_abt
+
+	/* mDDR mode clear */
+	ldr	r0, virt_ddr_io_ctrl
+	/*mov	r1, #0 */
+	mov	r1, #(0x1 << 28)
+	str	r1, [r0]
+
 emif_self_refresh_dis:
 	/* Disable EMIF self-refresh */
 	ldr	r0, emif_addr_virt
@@ -526,6 +638,8 @@ ENTRY(am33xx_resume_from_deep_sleep)
 	ldr	r6, mem_type
 	cmp	r6, #MEM_TYPE_DDR2
 	beq	ddr2_resume_seq
+	cmp	r6, #MEM_TYPE_LPDDR1
+	beq	lpddr1_resume_seq
 
 	/* DDR3 resume path */
 
@@ -653,6 +767,58 @@ poll_vtp_ready:
 	mov	r1, #0
 	str	r1, [r0]
 
+	b	config_emif_timings
+
+	/* LPDDR1 resume path */
+lpddr1_resume_seq:
+	/* Disable SRAM LDO ret mode */
+	ldr	r0, phys_sram_ldo_addr
+	ldr	r1, [r0]
+	bic	r1, #1
+	str	r1, [r0]
+
+	/* Restore the pull for DQ, DM */
+	ldr	r1, phys_ddr_io_pull1
+	ldr	r2, resume_io_pull_data
+	str	r2, [r1]
+
+	ldr	r1, phys_ddr_io_pull2
+	ldr	r2, resume_io_pull_data
+	str	r2, [r1]
+
+lpddr1_config_vtp:
+	ldr	r0, phys_ddr_vtp_ctrl
+	ldr	r1, [r0]
+	mov	r2, #0x0	@ clear the register
+	str	r2, [r0]
+	mov	r2, #0x6	@ write the filter value
+	str	r2, [r0]
+
+	ldr	r1, [r0]
+	ldr	r2, vtp_enable	@ set the enable bit
+	orr	r2, r2, r1
+	str	r2, [r0]
+
+	ldr	r1, [r0]	@ toggle the CLRZ bit
+	bic	r1, #1
+	str	r1, [r0]
+
+	ldr	r1, [r0]
+	orr	r1, #1
+	str	r1, [r0]
+
+lpddr1_poll_vtp_ready:
+	ldr	r1, [r0]	@ poll for VTP ready
+	tst	r1, #(1 << 5)
+	beq	lpddr1_poll_vtp_ready
+
+	/* DDR3 reset override and mDDR mode clear */
+	ldr	r0, phys_ddr_io_ctrl
+	mov	r1, #(1 << 28)
+	str	r1, [r0]
+
+	/* lpddr1_resume_seq end */
+
 config_emif_timings:
 	ldr	r3, emif_phys_addr
 	ldr	r4, emif_rd_lat_val