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