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