From 69d4255b139274f71faca28bc93bb49da8eb1a91 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:27:09 -0600 Subject: OMAP3 SRAM: add ARM barriers to omap3_sram_configure_core_dpll Add more barriers in the SRAM CORE DPLL M2 divider change code. - Add a DSB SY after the function's entry point to flush all cached and buffered writes and wait for the interconnect to claim that they have completed[1]. The idea here is to force all delayed write traffic going to the SDRAM to at least post to the L3 interconnect before continuing. If these writes are allowed to occur after the SDRC is idled, the writes will not be acknowledged and the ARM will stall. Note that in this case, it does not matter if the writes actually complete to the SDRAM - it is only necessary for the writes to leave the ARM itself. If the writes are posted by the interconnect when the SDRC goes into idle, the writes will be delayed until the SDRC returns from idle[2]. If the SDRC is in the middle of a write when it is requested to enter idle, the SDRC will not acknowledge the idle request until the writes complete to the SDRAM.[3] The old-style DMB in sdram_in_selfrefresh is now superfluous, so, remove it. - Add an ISB before the function's exit point to prevent the ARM from speculatively executing into SDRAM before the SDRAM is enabled[4]. ... 1. ARMv7 ARM (DDI 0406A) A3-47, A3-48. 2. Private communication with Richard Woodruff . 3. Private communication with Richard Woodruff . 4. ARMv7 ARM (DDI 0406A) A3-48. Signed-off-by: Paul Walmsley Cc: Richard Woodruff --- arch/arm/mach-omap2/sram34xx.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-omap2/sram34xx.S') diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 2c714613634..f4a356d5d2d 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -43,6 +43,7 @@ */ ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack + dsb @ flush buffered writes to interconnect cmp r3, #0x2 blne configure_sdrc cmp r3, #0x2 @@ -58,6 +59,7 @@ ENTRY(omap3_sram_configure_core_dpll) blne wait_dll_lock cmp r3, #0x1 blne configure_sdrc + isb @ prevent speculative exec past here mov r0, #0 @ return value ldmfd sp!, {r1-r12, pc} @ restore regs and return unlock_dll: @@ -73,8 +75,6 @@ lock_dll: str r5, [r4] bx lr sdram_in_selfrefresh: - mov r5, #0x0 @ Move 0 to R5 - mcr p15, 0, r5, c7, c10, 5 @ memory barrier ldr r4, omap3_sdrc_power @ read the SDRC_POWER register ldr r5, [r4] @ read the contents of SDRC_POWER orr r5, r5, #0x40 @ enable self refresh on idle req -- cgit v1.2.3 From d75d9e73cd59127a4d926a2bf5e9cdcc90f033d6 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:27:09 -0600 Subject: OMAP3 clock: add interconnect barriers to CORE DPLL M2 change Where necessary, add interconnect barriers to force posted writes to complete before continuing. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/sram34xx.S | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-omap2/sram34xx.S') diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index f4a356d5d2d..8d524f30563 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -66,22 +66,23 @@ unlock_dll: ldr r4, omap3_sdrc_dlla_ctrl ldr r5, [r4] orr r5, r5, #0x4 - str r5, [r4] + str r5, [r4] @ (no OCP barrier needed) bx lr lock_dll: ldr r4, omap3_sdrc_dlla_ctrl ldr r5, [r4] bic r5, r5, #0x4 - str r5, [r4] + str r5, [r4] @ (no OCP barrier needed) bx lr sdram_in_selfrefresh: ldr r4, omap3_sdrc_power @ read the SDRC_POWER register ldr r5, [r4] @ read the contents of SDRC_POWER orr r5, r5, #0x40 @ enable self refresh on idle req str r5, [r4] @ write back to SDRC_POWER register + ldr r5, [r4] @ posted-write barrier for SDRC ldr r4, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg ldr r5, [r4] - bic r5, r5, #0x2 @ disable iclk bit for SRDC + bic r5, r5, #0x2 @ disable iclk bit for SDRC str r5, [r4] wait_sdrc_idle: ldr r4, omap3_cm_idlest1_core @@ -97,6 +98,7 @@ configure_core_dpll: and r5, r5, r6 orr r5, r5, r3, lsl #0x1B @ r3 contains the M2 val str r5, [r4] + ldr r5, [r4] @ posted-write barrier for CM mov r5, #0x800 @ wait for the clock to stabilise cmp r3, #2 bne wait_clk_stable @@ -152,6 +154,7 @@ configure_sdrc: str r1, [r4] ldr r4, omap3_sdrc_actim_ctrlb str r2, [r4] + ldr r2, [r4] @ posted-write barrier for SDRC bx lr omap3_sdrc_power: -- cgit v1.2.3 From fa0406a8d8c3a4a302085ccd031d999161405f70 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:27:09 -0600 Subject: OMAP3 SRAM: clear the SDRC PWRENA bit during SDRC frequency change Clear the SDRC_POWER.PWRENA bit before putting the SDRAM into self-refresh mode. This prevents the SDRC from attempting to power off the SDRAM, which can cause the system to hang. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/sram34xx.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-omap2/sram34xx.S') diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 8d524f30563..9a454151c42 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -77,7 +77,9 @@ lock_dll: sdram_in_selfrefresh: ldr r4, omap3_sdrc_power @ read the SDRC_POWER register ldr r5, [r4] @ read the contents of SDRC_POWER + mov r9, r5 @ keep a copy of SDRC_POWER bits orr r5, r5, #0x40 @ enable self refresh on idle req + bic r5, r5, #0x4 @ clear PWDENA str r5, [r4] @ write back to SDRC_POWER register ldr r5, [r4] @ posted-write barrier for SDRC ldr r4, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg @@ -128,10 +130,9 @@ wait_sdrc_idle1: and r5, r5, #0x2 cmp r5, #0 bne wait_sdrc_idle1 +restore_sdrc_power_val: ldr r4, omap3_sdrc_power - ldr r5, [r4] - bic r5, r5, #0x40 - str r5, [r4] + str r9, [r4] @ restore SDRC_POWER, no barrier needed bx lr wait_dll_lock: ldr r4, omap3_sdrc_dlla_status -- cgit v1.2.3 From b2abb271a5705bc80478e79d95fc9f3babc2605c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:27:10 -0600 Subject: OMAP3 SRAM: renumber registers to make space for argument passing Renumber registers in omap3_sram_configure_core_dpll() assembly code to make space for additional parameters. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/sram34xx.S | 114 ++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 57 deletions(-) (limited to 'arch/arm/mach-omap2/sram34xx.S') diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 9a454151c42..35131e5bc7d 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -63,50 +63,50 @@ ENTRY(omap3_sram_configure_core_dpll) mov r0, #0 @ return value ldmfd sp!, {r1-r12, pc} @ restore regs and return unlock_dll: - ldr r4, omap3_sdrc_dlla_ctrl - ldr r5, [r4] - orr r5, r5, #0x4 - str r5, [r4] @ (no OCP barrier needed) + ldr r11, omap3_sdrc_dlla_ctrl + ldr r12, [r11] + orr r12, r12, #0x4 + str r12, [r11] @ (no OCP barrier needed) bx lr lock_dll: - ldr r4, omap3_sdrc_dlla_ctrl - ldr r5, [r4] - bic r5, r5, #0x4 - str r5, [r4] @ (no OCP barrier needed) + ldr r11, omap3_sdrc_dlla_ctrl + ldr r12, [r11] + bic r12, r12, #0x4 + str r12, [r11] @ (no OCP barrier needed) bx lr sdram_in_selfrefresh: - ldr r4, omap3_sdrc_power @ read the SDRC_POWER register - ldr r5, [r4] @ read the contents of SDRC_POWER - mov r9, r5 @ keep a copy of SDRC_POWER bits - orr r5, r5, #0x40 @ enable self refresh on idle req - bic r5, r5, #0x4 @ clear PWDENA - str r5, [r4] @ write back to SDRC_POWER register - ldr r5, [r4] @ posted-write barrier for SDRC - ldr r4, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg - ldr r5, [r4] - bic r5, r5, #0x2 @ disable iclk bit for SDRC - str r5, [r4] + ldr r11, omap3_sdrc_power @ read the SDRC_POWER register + ldr r12, [r11] @ read the contents of SDRC_POWER + mov r9, r12 @ keep a copy of SDRC_POWER bits + orr r12, r12, #0x40 @ enable self refresh on idle req + bic r12, r12, #0x4 @ clear PWDENA + str r12, [r11] @ write back to SDRC_POWER register + ldr r12, [r11] @ posted-write barrier for SDRC + ldr r11, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg + ldr r12, [r11] + bic r12, r12, #0x2 @ disable iclk bit for SDRC + str r12, [r11] wait_sdrc_idle: - ldr r4, omap3_cm_idlest1_core - ldr r5, [r4] - and r5, r5, #0x2 @ check for SDRC idle - cmp r5, #2 + ldr r11, omap3_cm_idlest1_core + ldr r12, [r11] + and r12, r12, #0x2 @ check for SDRC idle + cmp r12, #2 bne wait_sdrc_idle bx lr configure_core_dpll: - ldr r4, omap3_cm_clksel1_pll - ldr r5, [r4] - ldr r6, core_m2_mask_val @ modify m2 for core dpll - and r5, r5, r6 - orr r5, r5, r3, lsl #0x1B @ r3 contains the M2 val - str r5, [r4] - ldr r5, [r4] @ posted-write barrier for CM - mov r5, #0x800 @ wait for the clock to stabilise + ldr r11, omap3_cm_clksel1_pll + ldr r12, [r11] + ldr r10, core_m2_mask_val @ modify m2 for core dpll + and r12, r12, r10 + orr r12, r12, r3, lsl #0x1B @ r3 contains the M2 val + str r12, [r11] + ldr r12, [r11] @ posted-write barrier for CM + mov r12, #0x800 @ wait for the clock to stabilise cmp r3, #2 bne wait_clk_stable bx lr wait_clk_stable: - subs r5, r5, #1 + subs r12, r12, #1 bne wait_clk_stable nop nop @@ -120,42 +120,42 @@ wait_clk_stable: nop bx lr enable_sdrc: - ldr r4, omap3_cm_iclken1_core - ldr r5, [r4] - orr r5, r5, #0x2 @ enable iclk bit for SDRC - str r5, [r4] + ldr r11, omap3_cm_iclken1_core + ldr r12, [r11] + orr r12, r12, #0x2 @ enable iclk bit for SDRC + str r12, [r11] wait_sdrc_idle1: - ldr r4, omap3_cm_idlest1_core - ldr r5, [r4] - and r5, r5, #0x2 - cmp r5, #0 + ldr r11, omap3_cm_idlest1_core + ldr r12, [r11] + and r12, r12, #0x2 + cmp r12, #0 bne wait_sdrc_idle1 restore_sdrc_power_val: - ldr r4, omap3_sdrc_power - str r9, [r4] @ restore SDRC_POWER, no barrier needed + ldr r11, omap3_sdrc_power + str r9, [r11] @ restore SDRC_POWER, no barrier needed bx lr wait_dll_lock: - ldr r4, omap3_sdrc_dlla_status - ldr r5, [r4] - and r5, r5, #0x4 - cmp r5, #0x4 + ldr r11, omap3_sdrc_dlla_status + ldr r12, [r11] + and r12, r12, #0x4 + cmp r12, #0x4 bne wait_dll_lock bx lr wait_dll_unlock: - ldr r4, omap3_sdrc_dlla_status - ldr r5, [r4] - and r5, r5, #0x4 - cmp r5, #0x0 + ldr r11, omap3_sdrc_dlla_status + ldr r12, [r11] + and r12, r12, #0x4 + cmp r12, #0x0 bne wait_dll_unlock bx lr configure_sdrc: - ldr r4, omap3_sdrc_rfr_ctrl - str r0, [r4] - ldr r4, omap3_sdrc_actim_ctrla - str r1, [r4] - ldr r4, omap3_sdrc_actim_ctrlb - str r2, [r4] - ldr r2, [r4] @ posted-write barrier for SDRC + ldr r11, omap3_sdrc_rfr_ctrl + str r0, [r11] + ldr r11, omap3_sdrc_actim_ctrla + str r1, [r11] + ldr r11, omap3_sdrc_actim_ctrlb + str r2, [r11] + ldr r2, [r11] @ posted-write barrier for SDRC bx lr omap3_sdrc_power: -- cgit v1.2.3 From 4519c2bf433b97d091635eb51e4ba8ffa1c84d62 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:26:32 -0600 Subject: OMAP3 clock: only unlock SDRC DLL if SDRC clk < 83MHz According to the 34xx TRM Rev. K section 11.2.4.4.11.1 "Purpose of the DLL/CDL Module," the SDRC delay-locked-loop can be locked at any SDRC clock frequency from 83MHz to 166MHz. CDP code unconditionally unlocked the DLL whenever shifting to a lower SDRC speed, but this seems unnecessary and error-prone, as the DLL is no longer able to compensate for process, voltage, and temperature variations. Instead, only unlock the DLL when the SDRC clock rate would be less than 83MHz. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/sram34xx.S | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-omap2/sram34xx.S') diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 35131e5bc7d..c080c82521e 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -40,22 +40,23 @@ /* * Change frequency of core dpll * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2 + * r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for + * SDRC rates < 83MHz */ ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack + ldr r4, [sp, #52] @ pull extra args off the stack dsb @ flush buffered writes to interconnect cmp r3, #0x2 blne configure_sdrc - cmp r3, #0x2 + cmp r4, #0x1 + bleq unlock_dll blne lock_dll - cmp r3, #0x1 - blne unlock_dll bl sdram_in_selfrefresh @ put the SDRAM in self refresh bl configure_core_dpll bl enable_sdrc - cmp r3, #0x1 - blne wait_dll_unlock - cmp r3, #0x2 + cmp r4, #0x1 + bleq wait_dll_unlock blne wait_dll_lock cmp r3, #0x1 blne configure_sdrc -- cgit v1.2.3