]>
Commit | Line | Data |
---|---|---|
2a6c2d7a | 1 | /* |
d2a9568c | 2 | * Copyright 2008-2011 Freescale Semiconductor, Inc. |
2a6c2d7a KG |
3 | * |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * Version 2 as published by the Free Software Foundation. | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <asm/io.h> | |
11 | #include <asm/fsl_ddr_sdram.h> | |
d2a9568c | 12 | #include <asm/processor.h> |
2a6c2d7a KG |
13 | |
14 | #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) | |
15 | #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL | |
16 | #endif | |
17 | ||
18 | void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, | |
19 | unsigned int ctrl_num) | |
20 | { | |
21 | unsigned int i; | |
22 | volatile ccsr_ddr_t *ddr; | |
e1be0d25 | 23 | u32 temp_sdram_cfg; |
91671913 YS |
24 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 |
25 | volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR; | |
26 | u32 total_gb_size_per_controller; | |
eb672e92 YS |
27 | unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t; |
28 | int csn = -1; | |
91671913 | 29 | #endif |
2a6c2d7a KG |
30 | |
31 | switch (ctrl_num) { | |
32 | case 0: | |
6d0f6bcf | 33 | ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; |
2a6c2d7a KG |
34 | break; |
35 | case 1: | |
6d0f6bcf | 36 | ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; |
2a6c2d7a KG |
37 | break; |
38 | default: | |
39 | printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); | |
40 | return; | |
41 | } | |
42 | ||
7fd101c9 YS |
43 | out_be32(&ddr->eor, regs->ddr_eor); |
44 | ||
eb672e92 YS |
45 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 |
46 | for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { | |
47 | cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; | |
48 | cs_ea = regs->cs[i].bnds & 0xfff; | |
49 | if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) { | |
50 | csn = i; | |
51 | csn_bnds_backup = regs->cs[i].bnds; | |
52 | csn_bnds_t = (unsigned int *) ®s->cs[i].bnds; | |
53 | *csn_bnds_t = regs->cs[i].bnds ^ 0x0F000F00; | |
54 | debug("Found cs%d_bns (0x%08x) covering 0xff000000, " | |
55 | "change it to 0x%x\n", | |
56 | csn, csn_bnds_backup, regs->cs[i].bnds); | |
57 | break; | |
58 | } | |
59 | } | |
60 | #endif | |
2a6c2d7a KG |
61 | for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { |
62 | if (i == 0) { | |
63 | out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); | |
64 | out_be32(&ddr->cs0_config, regs->cs[i].config); | |
65 | out_be32(&ddr->cs0_config_2, regs->cs[i].config_2); | |
66 | ||
67 | } else if (i == 1) { | |
68 | out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); | |
69 | out_be32(&ddr->cs1_config, regs->cs[i].config); | |
70 | out_be32(&ddr->cs1_config_2, regs->cs[i].config_2); | |
71 | ||
72 | } else if (i == 2) { | |
73 | out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); | |
74 | out_be32(&ddr->cs2_config, regs->cs[i].config); | |
75 | out_be32(&ddr->cs2_config_2, regs->cs[i].config_2); | |
76 | ||
77 | } else if (i == 3) { | |
78 | out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); | |
79 | out_be32(&ddr->cs3_config, regs->cs[i].config); | |
80 | out_be32(&ddr->cs3_config_2, regs->cs[i].config_2); | |
81 | } | |
82 | } | |
83 | ||
84 | out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); | |
85 | out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); | |
86 | out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); | |
87 | out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); | |
88 | out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); | |
89 | out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); | |
90 | out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); | |
e1fd16b6 YS |
91 | out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3); |
92 | out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4); | |
93 | out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5); | |
94 | out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6); | |
95 | out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7); | |
96 | out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8); | |
2a6c2d7a KG |
97 | out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); |
98 | out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); | |
99 | out_be32(&ddr->sdram_data_init, regs->ddr_data_init); | |
100 | out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); | |
101 | out_be32(&ddr->init_addr, regs->ddr_init_addr); | |
102 | out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); | |
103 | ||
104 | out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4); | |
105 | out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5); | |
106 | out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); | |
107 | out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); | |
2a6c2d7a KG |
108 | out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); |
109 | out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); | |
110 | out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); | |
d2a9568c YS |
111 | out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1); |
112 | out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); | |
113 | out_be32(&ddr->err_disable, regs->err_disable); | |
114 | out_be32(&ddr->err_int_en, regs->err_int_en); | |
115 | for (i = 0; i < 32; i++) | |
116 | out_be32(&ddr->debug[i], regs->debug[i]); | |
2a6c2d7a | 117 | |
0ee84b88 ES |
118 | /* Set, but do not enable the memory */ |
119 | temp_sdram_cfg = regs->ddr_sdram_cfg; | |
e1be0d25 P |
120 | temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); |
121 | out_be32(&ddr->sdram_cfg, temp_sdram_cfg); | |
fa8d23c0 YS |
122 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003 |
123 | if (regs->ddr_sdram_rcw_2 & 0x00f00000) { | |
124 | out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); | |
125 | out_be32(&ddr->debug[2], 0x00000400); | |
126 | out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff); | |
127 | out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff); | |
128 | out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb); | |
129 | out_be32(&ddr->mtcr, 0); | |
130 | out_be32(&ddr->debug[12], 0x00000015); | |
131 | out_be32(&ddr->debug[21], 0x24000000); | |
132 | out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff); | |
133 | out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN); | |
134 | ||
135 | asm volatile("sync;isync"); | |
136 | while (!(in_be32(&ddr->debug[1]) & 0x2)) | |
137 | ; | |
138 | ||
139 | switch (regs->ddr_sdram_rcw_2 & 0x00f00000) { | |
140 | case 0x00000000: | |
141 | out_be32(&ddr->sdram_md_cntl, | |
142 | MD_CNTL_MD_EN | | |
143 | MD_CNTL_CS_SEL_CS0_CS1 | | |
144 | 0x04000000 | | |
145 | MD_CNTL_WRCW | | |
146 | MD_CNTL_MD_VALUE(0x02)); | |
147 | break; | |
148 | case 0x00100000: | |
149 | out_be32(&ddr->sdram_md_cntl, | |
150 | MD_CNTL_MD_EN | | |
151 | MD_CNTL_CS_SEL_CS0_CS1 | | |
152 | 0x04000000 | | |
153 | MD_CNTL_WRCW | | |
154 | MD_CNTL_MD_VALUE(0x0a)); | |
155 | break; | |
156 | case 0x00200000: | |
157 | out_be32(&ddr->sdram_md_cntl, | |
158 | MD_CNTL_MD_EN | | |
159 | MD_CNTL_CS_SEL_CS0_CS1 | | |
160 | 0x04000000 | | |
161 | MD_CNTL_WRCW | | |
162 | MD_CNTL_MD_VALUE(0x12)); | |
163 | break; | |
164 | case 0x00300000: | |
165 | out_be32(&ddr->sdram_md_cntl, | |
166 | MD_CNTL_MD_EN | | |
167 | MD_CNTL_CS_SEL_CS0_CS1 | | |
168 | 0x04000000 | | |
169 | MD_CNTL_WRCW | | |
170 | MD_CNTL_MD_VALUE(0x1a)); | |
171 | break; | |
172 | default: | |
173 | out_be32(&ddr->sdram_md_cntl, | |
174 | MD_CNTL_MD_EN | | |
175 | MD_CNTL_CS_SEL_CS0_CS1 | | |
176 | 0x04000000 | | |
177 | MD_CNTL_WRCW | | |
178 | MD_CNTL_MD_VALUE(0x02)); | |
179 | printf("Unsupported RC10\n"); | |
180 | break; | |
181 | } | |
182 | ||
183 | while (in_be32(&ddr->sdram_md_cntl) & 0x80000000) | |
184 | ; | |
185 | udelay(6); | |
186 | out_be32(&ddr->sdram_cfg, temp_sdram_cfg); | |
187 | out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); | |
188 | out_be32(&ddr->debug[2], 0x0); | |
189 | out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); | |
190 | out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); | |
191 | out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); | |
192 | out_be32(&ddr->debug[12], 0x0); | |
193 | out_be32(&ddr->debug[21], 0x0); | |
194 | out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); | |
195 | ||
196 | } | |
197 | #endif | |
2a6c2d7a | 198 | /* |
ae5f943b DL |
199 | * For 8572 DDR1 erratum - DDR controller may enter illegal state |
200 | * when operatiing in 32-bit bus mode with 4-beat bursts, | |
201 | * This erratum does not affect DDR3 mode, only for DDR2 mode. | |
2a6c2d7a | 202 | */ |
eb0aff77 | 203 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115 |
2a6c2d7a | 204 | if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2) |
ae5f943b | 205 | && in_be32(&ddr->sdram_cfg) & 0x80000) { |
2a6c2d7a | 206 | /* set DEBUG_1[31] */ |
d2a9568c | 207 | setbits_be32(&ddr->debug[0], 1); |
2a6c2d7a | 208 | } |
ae5f943b | 209 | #endif |
91671913 YS |
210 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 |
211 | /* | |
212 | * This is the combined workaround for DDR111 and DDR134 | |
213 | * following the published errata for MPC8572 | |
214 | */ | |
215 | ||
216 | /* 1. Set EEBACR[3] */ | |
217 | setbits_be32(&ecm->eebacr, 0x10000000); | |
218 | debug("Setting EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); | |
219 | ||
220 | /* 2. Set DINIT in SDRAM_CFG_2*/ | |
221 | setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_D_INIT); | |
222 | debug("Setting sdram_cfg_2[D_INIT] to 0x%08x\n", | |
223 | in_be32(&ddr->sdram_cfg_2)); | |
224 | ||
225 | /* 3. Set DEBUG_3[21] */ | |
226 | setbits_be32(&ddr->debug[2], 0x400); | |
227 | debug("Setting DEBUG_3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); | |
228 | ||
229 | #endif /* part 1 of the workaound */ | |
2a6c2d7a KG |
230 | |
231 | /* | |
c360ceac | 232 | * 500 painful micro-seconds must elapse between |
2a6c2d7a | 233 | * the DDR clock setup and the DDR config enable. |
c360ceac DL |
234 | * DDR2 need 200 us, and DDR3 need 500 us from spec, |
235 | * we choose the max, that is 500 us for all of case. | |
2a6c2d7a | 236 | */ |
c360ceac | 237 | udelay(500); |
2a6c2d7a KG |
238 | asm volatile("sync;isync"); |
239 | ||
e1be0d25 | 240 | /* Let the controller go */ |
fa8d23c0 | 241 | temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI; |
e1be0d25 | 242 | out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); |
fa8d23c0 | 243 | asm volatile("sync;isync"); |
2a6c2d7a KG |
244 | |
245 | /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ | |
91671913 | 246 | while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) |
2a6c2d7a | 247 | udelay(10000); /* throttle polling rate */ |
91671913 YS |
248 | |
249 | #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 | |
250 | /* continue this workaround */ | |
251 | ||
252 | /* 4. Clear DEBUG3[21] */ | |
253 | clrbits_be32(&ddr->debug[2], 0x400); | |
254 | debug("Clearing D3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); | |
255 | ||
256 | /* DDR134 workaround starts */ | |
257 | /* A: Clear sdram_cfg_2[odt_cfg] */ | |
258 | clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_ODT_CFG_MASK); | |
259 | debug("Clearing SDRAM_CFG2[ODT_CFG] to 0x%08x\n", | |
260 | in_be32(&ddr->sdram_cfg_2)); | |
261 | ||
262 | /* B: Set DEBUG1[15] */ | |
263 | setbits_be32(&ddr->debug[0], 0x10000); | |
264 | debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); | |
265 | ||
266 | /* C: Set timing_cfg_2[cpo] to 0b11111 */ | |
267 | setbits_be32(&ddr->timing_cfg_2, TIMING_CFG_2_CPO_MASK); | |
268 | debug("Setting TMING_CFG_2[CPO] to 0x%08x\n", | |
269 | in_be32(&ddr->timing_cfg_2)); | |
270 | ||
271 | /* D: Set D6 to 0x9f9f9f9f */ | |
272 | out_be32(&ddr->debug[5], 0x9f9f9f9f); | |
273 | debug("Setting D6 to 0x%08x\n", in_be32(&ddr->debug[5])); | |
274 | ||
275 | /* E: Set D7 to 0x9f9f9f9f */ | |
276 | out_be32(&ddr->debug[6], 0x9f9f9f9f); | |
277 | debug("Setting D7 to 0x%08x\n", in_be32(&ddr->debug[6])); | |
278 | ||
279 | /* F: Set D2[20] */ | |
280 | setbits_be32(&ddr->debug[1], 0x800); | |
281 | debug("Setting D2[20] to 0x%08x\n", in_be32(&ddr->debug[1])); | |
282 | ||
283 | /* G: Poll on D2[20] until cleared */ | |
284 | while (in_be32(&ddr->debug[1]) & 0x800) | |
285 | udelay(10000); /* throttle polling rate */ | |
286 | ||
287 | /* H: Clear D1[15] */ | |
288 | clrbits_be32(&ddr->debug[0], 0x10000); | |
289 | debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); | |
290 | ||
291 | /* I: Set sdram_cfg_2[odt_cfg] */ | |
292 | setbits_be32(&ddr->sdram_cfg_2, | |
293 | regs->ddr_sdram_cfg_2 & SDRAM_CFG2_ODT_CFG_MASK); | |
294 | debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); | |
295 | ||
296 | /* Continuing with the DDR111 workaround */ | |
297 | /* 5. Set D2[21] */ | |
298 | setbits_be32(&ddr->debug[1], 0x400); | |
299 | debug("Setting D2[21] to 0x%08x\n", in_be32(&ddr->debug[1])); | |
300 | ||
301 | /* 6. Poll D2[21] until its cleared */ | |
302 | while (in_be32(&ddr->debug[1]) & 0x400) | |
303 | udelay(10000); /* throttle polling rate */ | |
304 | ||
305 | /* 7. Wait for 400ms/GB */ | |
306 | total_gb_size_per_controller = 0; | |
307 | for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { | |
308 | total_gb_size_per_controller += | |
309 | ((regs->cs[i].bnds & 0xFFFF) >> 6) | |
310 | - (regs->cs[i].bnds >> 22) + 1; | |
2a6c2d7a | 311 | } |
91671913 YS |
312 | if (in_be32(&ddr->sdram_cfg) & 0x80000) |
313 | total_gb_size_per_controller <<= 1; | |
314 | debug("Wait for %d ms\n", total_gb_size_per_controller * 400); | |
315 | udelay(total_gb_size_per_controller * 400000); | |
316 | ||
317 | /* 8. Set sdram_cfg_2[dinit] if options requires */ | |
318 | setbits_be32(&ddr->sdram_cfg_2, | |
319 | regs->ddr_sdram_cfg_2 & SDRAM_CFG2_D_INIT); | |
320 | debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); | |
321 | ||
322 | /* 9. Poll until dinit is cleared */ | |
323 | while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) | |
324 | udelay(10000); | |
325 | ||
326 | /* 10. Clear EEBACR[3] */ | |
327 | clrbits_be32(&ecm->eebacr, 10000000); | |
328 | debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); | |
eb672e92 YS |
329 | |
330 | if (csn != -1) { | |
331 | csn_bnds_t = (unsigned int *) ®s->cs[csn].bnds; | |
332 | *csn_bnds_t = csn_bnds_backup; | |
333 | debug("Change cs%d_bnds back to 0x%08x\n", | |
334 | csn, regs->cs[csn].bnds); | |
335 | setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */ | |
336 | switch (csn) { | |
337 | case 0: | |
338 | out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds); | |
339 | break; | |
340 | case 1: | |
341 | out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); | |
342 | break; | |
343 | case 2: | |
344 | out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); | |
345 | break; | |
346 | case 3: | |
347 | out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); | |
348 | break; | |
349 | } | |
350 | clrbits_be32(&ddr->sdram_cfg, 0x2); | |
351 | } | |
91671913 | 352 | #endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */ |
2a6c2d7a | 353 | } |