aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-06-23 21:59:22 -0400
committerAnson Huang <b20788@freescale.com>2014-07-04 00:39:28 -0400
commit2d7ed778613773fa7d8bfec33ffb9b6952f7bb9b (patch)
tree985abf9128673bcd2846a8c888f9f9ccb5954b2f /arch
parent8f87c4e16fb82eea770769da543b8831118f205e (diff)
ENGR00320383-2 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 precharge command. 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.S119
2 files changed, 43 insertions, 79 deletions
diff --git a/arch/arm/mach-imx/busfreq_ddr3.c b/arch/arm/mach-imx/busfreq_ddr3.c
index 6854f78d3f47..579519267d51 100644
--- a/arch/arm/mach-imx/busfreq_ddr3.c
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -103,9 +103,8 @@ extern unsigned long imx6sx_ddr3_freq_change_end asm("imx6sx_ddr3_freq_change_en
103unsigned long ddr3_dll_mx6sx[][2] = { 103unsigned long ddr3_dll_mx6sx[][2] = {
104 {0x0c, 0x0}, 104 {0x0c, 0x0},
105 {0x10, 0x0}, 105 {0x10, 0x0},
106 {0x30, 0x0},
107 {0x1C, 0x04008032}, 106 {0x1C, 0x04008032},
108 {0x1C, 0x00068031}, 107 {0x1C, 0x00048031},
109 {0x1C, 0x05208030}, 108 {0x1C, 0x05208030},
110 {0x1C, 0x04008040}, 109 {0x1C, 0x04008040},
111 {0x818, 0x0}, 110 {0x818, 0x0},
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6sx.S b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
index 23a34d43c1ce..fff0c3460296 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6sx.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -59,7 +59,8 @@
59 add r9, r9, #4 59 add r9, r9, #4
60 cmp r9, #16 60 cmp r9, #16
61 bne 2b 61 bne 2b
62 subs r8, r8, #1 62 sub r8, r8, #1
63 cmp r8, #0
63 bgt 1b 64 bgt 1b
64 65
65 .endm 66 .endm
@@ -78,33 +79,7 @@
78 /* check whether periph2_clk is already from top path */ 79 /* check whether periph2_clk is already from top path */
79 ldr r8, [r5, #CCM_CBCDR] 80 ldr r8, [r5, #CCM_CBCDR]
80 ands r8, #(1 << 26) 81 ands r8, #(1 << 26)
81 bne skip_periph2_clk2_switch_400m 82 beq skip_periph2_clk2_switch_400m
82
83 /* change periph2_clk2 to be sourced from pll3_clk. */
84 ldr r8, [r5, #CCM_CBCMR]
85 bic r8, r8, #(1 << 20)
86 str r8, [r5, #CCM_CBCMR]
87
88 /* make sure periph2_clk2 freq not exceed 400MHz */
89 ldr r8, [r5, #CCM_CBCDR]
90 bic r8, r8, #0x7
91 orr r8, r8, #0x1
92 str r8, [r5, #CCM_CBCDR]
93
94 /* now switch periph2_clk to pll3_main_clk. */
95 ldr r8, [r5, #CCM_CBCDR]
96 orr r8, r8, #(1 << 26)
97 str r8, [r5, #CCM_CBCDR]
98
99 wait_for_ccm_handshake
100
101skip_periph2_clk2_switch_400m:
102
103 /* now switch pre_periph2_clk to PFD_400MHz. */
104 ldr r8, [r5, #CCM_CBCMR]
105 bic r8, r8, #(0x3 << 21)
106 orr r8, r8, #(0x1 << 21)
107 str r8, [r5, #CCM_CBCMR]
108 83
109 /* now switch periph2_clk back. */ 84 /* now switch periph2_clk back. */
110 ldr r8, [r5, #CCM_CBCDR] 85 ldr r8, [r5, #CCM_CBCDR]
@@ -113,6 +88,13 @@ skip_periph2_clk2_switch_400m:
113 88
114 wait_for_ccm_handshake 89 wait_for_ccm_handshake
115 90
91 /*
92 * on i.MX6SX, pre_periph2_clk will be always from
93 * pll2_pfd2, so no need to set pre_periph2_clk
94 * parent, just set the mmdc divider directly.
95 */
96skip_periph2_clk2_switch_400m:
97
116 /* fabric_mmdc_podf to 0 */ 98 /* fabric_mmdc_podf to 0 */
117 ldr r8, [r5, #CCM_CBCDR] 99 ldr r8, [r5, #CCM_CBCDR]
118 bic r8, r8, #(0x7 << 3) 100 bic r8, r8, #(0x7 << 3)
@@ -127,32 +109,7 @@ skip_periph2_clk2_switch_400m:
127 /* check whether periph2_clk is already from top path */ 109 /* check whether periph2_clk is already from top path */
128 ldr r8, [r5, #CCM_CBCDR] 110 ldr r8, [r5, #CCM_CBCDR]
129 ands r8, #(1 << 26) 111 ands r8, #(1 << 26)
130 bne skip_periph2_clk2_switch_50m 112 beq skip_periph2_clk2_switch_50m
131
132 /* change periph2_clk2 to be sourced from pll3_clk. */
133 ldr r8, [r5, #CCM_CBCMR]
134 bic r8, r8, #(1 << 20)
135 str r8, [r5, #CCM_CBCMR]
136
137 ldr r8, [r5, #CCM_CBCDR]
138 bic r8, r8, #0x7
139 orr r8, r8, #0x1
140 str r8, [r5, #CCM_CBCDR]
141
142 /* now switch periph2_clk to pll3_main_clk. */
143 ldr r8, [r5, #CCM_CBCDR]
144 orr r8, r8, #(1 << 26)
145 str r8, [r5, #CCM_CBCDR]
146
147 wait_for_ccm_handshake
148
149skip_periph2_clk2_switch_50m:
150
151 /* now switch pre_periph2_clk to PFD_400MHz. */
152 ldr r8, [r5, #CCM_CBCMR]
153 bic r8, r8, #(0x3 << 21)
154 orr r8, r8, #(0x1 << 21)
155 str r8, [r5, #CCM_CBCMR]
156 113
157 /* now switch periph2_clk back. */ 114 /* now switch periph2_clk back. */
158 ldr r8, [r5, #CCM_CBCDR] 115 ldr r8, [r5, #CCM_CBCDR]
@@ -161,6 +118,13 @@ skip_periph2_clk2_switch_50m:
161 118
162 wait_for_ccm_handshake 119 wait_for_ccm_handshake
163 120
121 /*
122 * on i.MX6SX, pre_periph2_clk will be always from
123 * pll2_pfd2, so no need to set pre_periph2_clk
124 * parent, just set the mmdc divider directly.
125 */
126skip_periph2_clk2_switch_50m:
127
164 /* fabric_mmdc_podf to 7 so that mmdc is 400 / 8 = 50MHz */ 128 /* fabric_mmdc_podf to 7 so that mmdc is 400 / 8 = 50MHz */
165 ldr r8, [r5, #CCM_CBCDR] 129 ldr r8, [r5, #CCM_CBCDR]
166 orr r8, r8, #(0x7 << 3) 130 orr r8, r8, #(0x7 << 3)
@@ -227,22 +191,24 @@ imx6sx_ddr3_freq_change_start:
227 * and 2-4G is translated by TTBR1. 191 * and 2-4G is translated by TTBR1.
228 */ 192 */
229 193
194 ldr r6, =iram_tlb_phys_addr
195 ldr r7, [r6]
196
230 /* Disable Branch Prediction, Z bit in SCTLR. */ 197 /* Disable Branch Prediction, Z bit in SCTLR. */
231 mrc p15, 0, r7, c1, c0, 0 198 mrc p15, 0, r6, c1, c0, 0
232 bic r7, r7, #0x800 199 bic r6, r6, #0x800
233 mcr p15, 0, r7, c1, c0, 0 200 mcr p15, 0, r6, c1, c0, 0
234 201
235 /* Flush the Branch Target Address Cache (BTAC) */ 202 /* Flush the Branch Target Address Cache (BTAC) */
236 ldr r6, =0x0 203 ldr r6, =0x0
237 mcr p15, 0, r6, c7, c1, 6 204 mcr p15, 0, r6, c7, c1, 6
238 ldr r6, =iram_tlb_phys_addr
239 ldr r6, [r6]
240 205
241 dsb 206 dsb
242 isb 207 isb
243 208
244 /* Store the IRAM table in TTBR1 */ 209 /* Store the IRAM table in TTBR1 */
245 mcr p15, 0, r6, c2, c0, 1 210 mcr p15, 0, r7, c2, c0, 1
211
246 /* Read TTBCR and set PD0=1, N = 1 */ 212 /* Read TTBCR and set PD0=1, N = 1 */
247 mrc p15, 0, r6, c2, c0, 2 213 mrc p15, 0, r6, c2, c0, 2
248 orr r6, r6, #0x11 214 orr r6, r6, #0x11
@@ -259,9 +225,9 @@ imx6sx_ddr3_freq_change_start:
259 isb 225 isb
260 226
261 /* Disable L1 data cache. */ 227 /* Disable L1 data cache. */
262 mrc p15, 0, r7, c1, c0, 0 228 mrc p15, 0, r6, c1, c0, 0
263 bic r7, r7, #0x4 229 bic r6, r6, #0x4
264 mcr p15, 0, r7, c1, c0, 0 230 mcr p15, 0, r6, c1, c0, 0
265 231
266 ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR) 232 ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
267 ldr r5, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR) 233 ldr r5, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
@@ -318,11 +284,6 @@ poll_conreq_set_1:
318 cmp r8, #(0x4 << 12) 284 cmp r8, #(0x4 << 12)
319 bne poll_conreq_set_1 285 bne poll_conreq_set_1
320 286
321 ldr r8, =0x00008010
322 str r8, [r4, #MMDC0_MDSCR]
323 ldr r8, =0x00008018
324 str r8, [r4, #MMDC0_MDSCR]
325
326 /* 287 /*
327 * if requested frequency is greater than 288 * if requested frequency is greater than
328 * 300MHz go to DLL on mode. 289 * 300MHz go to DLL on mode.
@@ -400,10 +361,10 @@ poll_dvfs_clear_1:
400 ldr r8, =0x00018039 361 ldr r8, =0x00018039
401 str r8, [r4, #MMDC0_MDSCR] 362 str r8, [r4, #MMDC0_MDSCR]
402 363
403 ldr r8, =0x08208030 364 ldr r8, =0x04208030
404 str r8, [r4, #MMDC0_MDSCR] 365 str r8, [r4, #MMDC0_MDSCR]
405 366
406 ldr r8, =0x08208038 367 ldr r8, =0x04208038
407 str r8, [r4, #MMDC0_MDSCR] 368 str r8, [r4, #MMDC0_MDSCR]
408 369
409 ldr r8, =0x00088032 370 ldr r8, =0x00088032
@@ -441,7 +402,8 @@ update_iomux:
441 orr r11, r11, #0x28 402 orr r11, r11, #0x28
442 str r11, [r6, r10] 403 str r11, [r6, r10]
443 add r3, r3, #8 404 add r3, r3, #8
444 subs r8, r8, #1 405 sub r8, r8, #1
406 cmp r8, #0
445 bgt update_iomux 407 bgt update_iomux
446 408
447 /* ODT disabled. */ 409 /* ODT disabled. */
@@ -541,7 +503,8 @@ update_iomux1:
541 ldr r11, [r3, #0x4] 503 ldr r11, [r3, #0x4]
542 str r11, [r6, r10] 504 str r11, [r6, r10]
543 add r3, r3, #8 505 add r3, r3, #8
544 subs r8, r8, #1 506 sub r8, r8, #1
507 cmp r8, #0
545 bgt update_iomux1 508 bgt update_iomux1
546 509
547 /* config MMDC timings to 400MHz. */ 510 /* config MMDC timings to 400MHz. */
@@ -650,7 +613,8 @@ update_calib:
650 ldr r11, [r1, #0x4] 613 ldr r11, [r1, #0x4]
651 str r11, [r4, r10] 614 str r11, [r4, r10]
652 add r1, r1, #8 615 add r1, r1, #8
653 subs r8, r8, #1 616 sub r8, r8, #1
617 cmp r8, #0
654 bgt update_calib 618 bgt update_calib
655 619
656 /* perform a force measurement. */ 620 /* perform a force measurement. */
@@ -671,10 +635,6 @@ poll_conreq_clear_2:
671 beq poll_conreq_clear_2 635 beq poll_conreq_clear_2
672 636
673done: 637done:
674 /* Enable L1 data cache. */
675 mrc p15, 0, r7, c1, c0, 0
676 orr r7, r7, #0x4
677 mcr p15, 0, r7, c1, c0, 0
678 638
679 /* MMDC0_MAPSR adopt power down enable. */ 639 /* MMDC0_MAPSR adopt power down enable. */
680 ldr r8, [r4, #MMDC0_MAPSR] 640 ldr r8, [r4, #MMDC0_MAPSR]
@@ -688,6 +648,11 @@ done:
688 str r7, [r8, #0x100] 648 str r7, [r8, #0x100]
689#endif 649#endif
690 650
651 /* Enable L1 data cache. */
652 mrc p15, 0, r7, c1, c0, 0
653 orr r7, r7, #0x4
654 mcr p15, 0, r7, c1, c0, 0
655
691 /* Restore the TTBCR */ 656 /* Restore the TTBCR */
692 dsb 657 dsb
693 isb 658 isb