diff options
author | Anson Huang <b20788@freescale.com> | 2014-06-23 21:59:22 -0400 |
---|---|---|
committer | Anson Huang <b20788@freescale.com> | 2014-07-04 00:39:28 -0400 |
commit | 2d7ed778613773fa7d8bfec33ffb9b6952f7bb9b (patch) | |
tree | 985abf9128673bcd2846a8c888f9f9ccb5954b2f /arch | |
parent | 8f87c4e16fb82eea770769da543b8831118f205e (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.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/ddr3_freq_imx6sx.S | 119 |
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 | |||
103 | unsigned long ddr3_dll_mx6sx[][2] = { | 103 | unsigned 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 | |||
101 | skip_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 | */ | ||
96 | skip_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 | |||
149 | skip_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 | */ | ||
126 | skip_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 | ||
673 | done: | 637 | done: |
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 |