summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-06-24 09:59:22 +0800
committerAnson Huang <b20788@freescale.com>2014-06-26 16:20:11 +0800
commit93510bfa720670b2f80a7f35ffb327f69fcb0f21 (patch)
treeb767d76acd13570ab32d7a797f7e3d0147c4a7cd /arch
parent5ca5fc373dc516d495104650b46d765f54d507e5 (diff)
ENGR00316496 ARM: imx: fix random failure for ddr3 freq scaling on i.mx6sx
Improve DDR3 freq scaling procedure of i.MX6SX: 1. some code of condition check is incorrect; 2. better to keep MMDC command same as ddr script; 3. improve the clock tree change of mmdc path; 4. remove CON_REG req for MMDC. Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/busfreq_ddr3.c3
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6sx.S140
2 files changed, 48 insertions, 95 deletions
diff --git a/arch/arm/mach-imx/busfreq_ddr3.c b/arch/arm/mach-imx/busfreq_ddr3.c
index 6854f78d3f47..f959c3c1ae08 100644
--- a/arch/arm/mach-imx/busfreq_ddr3.c
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -105,7 +105,8 @@ unsigned long ddr3_dll_mx6sx[][2] = {
{0x10, 0x0},
{0x30, 0x0},
{0x1C, 0x04008032},
- {0x1C, 0x00068031},
+ {0x1C, 0x00008033},
+ {0x1C, 0x00048031},
{0x1C, 0x05208030},
{0x1C, 0x04008040},
{0x818, 0x0},
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6sx.S b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
index c63bf570100d..f2e523f47a43 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6sx.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -59,7 +59,8 @@
add r9, r9, #4
cmp r9, #16
bne 2b
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt 1b
.endm
@@ -78,33 +79,7 @@
/* check whether periph2_clk is already from top path */
ldr r8, [r5, #CCM_CBCDR]
ands r8, #(1 << 26)
- bne skip_periph2_clk2_switch_400m
-
- /* change periph2_clk2 to be sourced from pll3_clk. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(1 << 20)
- str r8, [r5, #CCM_CBCMR]
-
- /* make sure periph2_clk2 freq not exceed 400MHz */
- ldr r8, [r5, #CCM_CBCDR]
- bic r8, r8, #0x7
- orr r8, r8, #0x1
- str r8, [r5, #CCM_CBCDR]
-
- /* now switch periph2_clk to pll3_main_clk. */
- ldr r8, [r5, #CCM_CBCDR]
- orr r8, r8, #(1 << 26)
- str r8, [r5, #CCM_CBCDR]
-
- wait_for_ccm_handshake
-
-skip_periph2_clk2_switch_400m:
-
- /* now switch pre_periph2_clk to PFD_400MHz. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(0x3 << 21)
- orr r8, r8, #(0x1 << 21)
- str r8, [r5, #CCM_CBCMR]
+ beq skip_periph2_clk2_switch_400m
/* now switch periph2_clk back. */
ldr r8, [r5, #CCM_CBCDR]
@@ -113,6 +88,13 @@ skip_periph2_clk2_switch_400m:
wait_for_ccm_handshake
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_400m:
+
/* fabric_mmdc_podf to 0 */
ldr r8, [r5, #CCM_CBCDR]
bic r8, r8, #(0x7 << 3)
@@ -127,32 +109,7 @@ skip_periph2_clk2_switch_400m:
/* check whether periph2_clk is already from top path */
ldr r8, [r5, #CCM_CBCDR]
ands r8, #(1 << 26)
- bne skip_periph2_clk2_switch_50m
-
- /* change periph2_clk2 to be sourced from pll3_clk. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(1 << 20)
- str r8, [r5, #CCM_CBCMR]
-
- ldr r8, [r5, #CCM_CBCDR]
- bic r8, r8, #0x7
- orr r8, r8, #0x1
- str r8, [r5, #CCM_CBCDR]
-
- /* now switch periph2_clk to pll3_main_clk. */
- ldr r8, [r5, #CCM_CBCDR]
- orr r8, r8, #(1 << 26)
- str r8, [r5, #CCM_CBCDR]
-
- wait_for_ccm_handshake
-
-skip_periph2_clk2_switch_50m:
-
- /* now switch pre_periph2_clk to PFD_400MHz. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(0x3 << 21)
- orr r8, r8, #(0x1 << 21)
- str r8, [r5, #CCM_CBCMR]
+ beq skip_periph2_clk2_switch_50m
/* now switch periph2_clk back. */
ldr r8, [r5, #CCM_CBCDR]
@@ -161,6 +118,13 @@ skip_periph2_clk2_switch_50m:
wait_for_ccm_handshake
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_50m:
+
/* fabric_mmdc_podf to 7 so that mmdc is 400 / 8 = 50MHz */
ldr r8, [r5, #CCM_CBCDR]
orr r8, r8, #(0x7 << 3)
@@ -227,22 +191,24 @@ imx6sx_ddr3_freq_change_start:
* and 2-4G is translated by TTBR1.
*/
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
/* Disable Branch Prediction, Z bit in SCTLR. */
- mrc p15, 0, r7, c1, c0, 0
- bic r7, r7, #0x800
- mcr p15, 0, r7, c1, c0, 0
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
/* Flush the Branch Target Address Cache (BTAC) */
ldr r6, =0x0
mcr p15, 0, r6, c7, c1, 6
- ldr r6, =iram_tlb_phys_addr
- ldr r6, [r6]
dsb
isb
/* Store the IRAM table in TTBR1 */
- mcr p15, 0, r6, c2, c0, 1
+ mcr p15, 0, r7, c2, c0, 1
+
/* Read TTBCR and set PD0=1, N = 1 */
mrc p15, 0, r6, c2, c0, 2
orr r6, r6, #0x11
@@ -259,9 +225,9 @@ imx6sx_ddr3_freq_change_start:
isb
/* Disable L1 data cache. */
- mrc p15, 0, r7, c1, c0, 0
- bic r7, r7, #0x4
- mcr p15, 0, r7, c1, c0, 0
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
ldr r5, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
@@ -309,20 +275,6 @@ wait_for_l2_to_idle:
ldr r8, =4
do_delay
- /* set CON_REG */
- ldr r8, =0x8000
- str r8, [r4, #MMDC0_MDSCR]
-poll_conreq_set_1:
- ldr r8, [r4, #MMDC0_MDSCR]
- and r8, r8, #(0x4 << 12)
- cmp r8, #(0x4 << 12)
- bne poll_conreq_set_1
-
- ldr r8, =0x00008010
- str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x00008018
- str r8, [r4, #MMDC0_MDSCR]
-
/*
* if requested frequency is greater than
* 300MHz go to DLL on mode.
@@ -400,10 +352,10 @@ poll_dvfs_clear_1:
ldr r8, =0x00018039
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x08208030
+ ldr r8, =0x04208030
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x08208038
+ ldr r8, =0x04208038
str r8, [r4, #MMDC0_MDSCR]
ldr r8, =0x00088032
@@ -441,7 +393,8 @@ update_iomux:
orr r11, r11, #0x28
str r11, [r6, r10]
add r3, r3, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_iomux
/* ODT disabled. */
@@ -459,10 +412,10 @@ update_iomux:
str r8, [r4, #MMDC0_MAPSR]
/* frc_msr + mu bypass */
- ldr r8, =0x00000060
+ ldr r8, =0x00000160
str r8, [r4, #MMDC0_MPMUR0]
- ldr r8, =0x00000460
+ ldr r8, =0x00000560
str r8, [r4, #MMDC0_MPMUR0]
ldr r8, =0x00000c60
@@ -490,10 +443,6 @@ dll_on_mode:
orr r8, r8, #(1 << 21)
str r8, [r4, #MMDC0_MAPSR]
- /* de-assert CON_REQ. */
- mov r8, #0x0
- str r8, [r4, #MMDC0_MDSCR]
-
/* poll DVFS ack. */
poll_dvfs_set_2:
ldr r8, [r4, #MMDC0_MAPSR]
@@ -546,7 +495,8 @@ update_iomux1:
ldr r11, [r3, #0x4]
str r11, [r6, r10]
add r3, r3, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_iomux1
/* config MMDC timings to 400MHz. */
@@ -579,10 +529,10 @@ update_iomux1:
do_delay
/* reset dll. */
- ldr r8, =0x09208030
+ ldr r8, =0x05208030
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x09208038
+ ldr r8, =0x05208038
str r8, [r4, #MMDC0_MDSCR]
/* delay for while. */
@@ -660,7 +610,8 @@ update_calib:
ldr r11, [r1, #0x4]
str r11, [r4, r10]
add r1, r1, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_calib
/* perform a force measurement. */
@@ -681,10 +632,6 @@ poll_conreq_clear_2:
beq poll_conreq_clear_2
done:
- /* Enable L1 data cache. */
- mrc p15, 0, r7, c1, c0, 0
- orr r7, r7, #0x4
- mcr p15, 0, r7, c1, c0, 0
#ifdef CONFIG_CACHE_L2X0
/* Enable L2. */
@@ -693,6 +640,11 @@ done:
str r7, [r8, #0x100]
#endif
+ /* Enable L1 data cache. */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #0x4
+ mcr p15, 0, r7, c1, c0, 0
+
/* Restore the TTBCR */
dsb
isb