]>
Commit | Line | Data |
---|---|---|
c609719b | 1 | /* |
5fb692ca | 2 | * (C) Copyright 2005-2007 |
5568e613 SR |
3 | * Stefan Roese, DENX Software Engineering, sr@denx.de. |
4 | * | |
62534beb SR |
5 | * (C) Copyright 2006 |
6 | * DAVE Srl <www.dave-tech.it> | |
7 | * | |
de8d5a36 | 8 | * (C) Copyright 2002-2004 |
c609719b WD |
9 | * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com |
10 | * | |
11 | * See file CREDITS for list of people who contributed to this | |
12 | * project. | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or | |
15 | * modify it under the terms of the GNU General Public License as | |
16 | * published by the Free Software Foundation; either version 2 of | |
17 | * the License, or (at your option) any later version. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, | |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
cf48eb9a | 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
c609719b WD |
22 | * GNU General Public License for more details. |
23 | * | |
24 | * You should have received a copy of the GNU General Public License | |
25 | * along with this program; if not, write to the Free Software | |
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
27 | * MA 02111-1307 USA | |
28 | */ | |
29 | ||
30 | #include <common.h> | |
31 | #include <ppc4xx.h> | |
32 | #include <asm/processor.h> | |
62534beb | 33 | #include "sdram.h" |
c821b5f1 | 34 | #include "ecc.h" |
c609719b | 35 | |
c609719b WD |
36 | #ifdef CONFIG_SDRAM_BANK0 |
37 | ||
5fb692ca | 38 | #ifndef CONFIG_440 |
c609719b | 39 | |
6d0f6bcf | 40 | #ifndef CONFIG_SYS_SDRAM_TABLE |
de8d5a36 | 41 | sdram_conf_t mb0cf[] = { |
cf48eb9a WD |
42 | {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */ |
43 | {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */ | |
44 | {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */ | |
45 | {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */ | |
46 | {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */ | |
de8d5a36 | 47 | }; |
5568e613 | 48 | #else |
6d0f6bcf | 49 | sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE; |
5568e613 SR |
50 | #endif |
51 | ||
cf48eb9a | 52 | #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) |
c609719b | 53 | |
6d0f6bcf | 54 | #ifdef CONFIG_SYS_SDRAM_CASL |
62534beb SR |
55 | static ulong ns2clks(ulong ns) |
56 | { | |
57 | ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10); | |
58 | ||
59 | return ((ns * 10) + bus_period_x_10) / bus_period_x_10; | |
60 | } | |
6d0f6bcf | 61 | #endif /* CONFIG_SYS_SDRAM_CASL */ |
62534beb SR |
62 | |
63 | static ulong compute_sdtr1(ulong speed) | |
64 | { | |
6d0f6bcf | 65 | #ifdef CONFIG_SYS_SDRAM_CASL |
cf48eb9a WD |
66 | ulong tmp; |
67 | ulong sdtr1 = 0; | |
68 | ||
69 | /* CASL */ | |
6d0f6bcf | 70 | if (CONFIG_SYS_SDRAM_CASL < 2) |
cf48eb9a WD |
71 | sdtr1 |= (1 << SDRAM0_TR_CASL); |
72 | else | |
6d0f6bcf | 73 | if (CONFIG_SYS_SDRAM_CASL > 4) |
cf48eb9a WD |
74 | sdtr1 |= (3 << SDRAM0_TR_CASL); |
75 | else | |
6d0f6bcf | 76 | sdtr1 |= ((CONFIG_SYS_SDRAM_CASL-1) << SDRAM0_TR_CASL); |
cf48eb9a WD |
77 | |
78 | /* PTA */ | |
6d0f6bcf | 79 | tmp = ns2clks(CONFIG_SYS_SDRAM_PTA); |
cf48eb9a WD |
80 | if ((tmp >= 2) && (tmp <= 4)) |
81 | sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA); | |
82 | else | |
83 | sdtr1 |= ((4-1) << SDRAM0_TR_PTA); | |
84 | ||
85 | /* CTP */ | |
6d0f6bcf | 86 | tmp = ns2clks(CONFIG_SYS_SDRAM_CTP); |
cf48eb9a WD |
87 | if ((tmp >= 2) && (tmp <= 4)) |
88 | sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP); | |
89 | else | |
90 | sdtr1 |= ((4-1) << SDRAM0_TR_CTP); | |
91 | ||
92 | /* LDF */ | |
6d0f6bcf | 93 | tmp = ns2clks(CONFIG_SYS_SDRAM_LDF); |
cf48eb9a WD |
94 | if ((tmp >= 2) && (tmp <= 4)) |
95 | sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF); | |
96 | else | |
97 | sdtr1 |= ((2-1) << SDRAM0_TR_LDF); | |
98 | ||
99 | /* RFTA */ | |
6d0f6bcf | 100 | tmp = ns2clks(CONFIG_SYS_SDRAM_RFTA); |
cf48eb9a WD |
101 | if ((tmp >= 4) && (tmp <= 10)) |
102 | sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA); | |
103 | else | |
104 | sdtr1 |= ((10-4) << SDRAM0_TR_RFTA); | |
105 | ||
106 | /* RCD */ | |
6d0f6bcf | 107 | tmp = ns2clks(CONFIG_SYS_SDRAM_RCD); |
cf48eb9a WD |
108 | if ((tmp >= 2) && (tmp <= 4)) |
109 | sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD); | |
110 | else | |
111 | sdtr1 |= ((4-1) << SDRAM0_TR_RCD); | |
112 | ||
113 | return sdtr1; | |
6d0f6bcf | 114 | #else /* CONFIG_SYS_SDRAM_CASL */ |
cf48eb9a WD |
115 | /* |
116 | * If no values are configured in the board config file | |
117 | * use the default values, which seem to be ok for most | |
118 | * boards. | |
119 | * | |
120 | * REMARK: | |
121 | * For new board ports we strongly recommend to define the | |
122 | * correct values for the used SDRAM chips in your board | |
123 | * config file (see PPChameleonEVB.h) | |
124 | */ | |
125 | if (speed > 100000000) { | |
126 | /* | |
127 | * 133 MHz SDRAM | |
128 | */ | |
129 | return 0x01074015; | |
130 | } else { | |
131 | /* | |
132 | * default: 100 MHz SDRAM | |
133 | */ | |
134 | return 0x0086400d; | |
135 | } | |
6d0f6bcf | 136 | #endif /* CONFIG_SYS_SDRAM_CASL */ |
62534beb SR |
137 | } |
138 | ||
139 | /* refresh is expressed in ms */ | |
140 | static ulong compute_rtr(ulong speed, ulong rows, ulong refresh) | |
141 | { | |
6d0f6bcf | 142 | #ifdef CONFIG_SYS_SDRAM_CASL |
cf48eb9a | 143 | ulong tmp; |
62534beb | 144 | |
cf48eb9a WD |
145 | tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000); |
146 | tmp /= 1000000; | |
62534beb | 147 | |
cf48eb9a | 148 | return ((tmp & 0x00003FF8) << 16); |
6d0f6bcf | 149 | #else /* CONFIG_SYS_SDRAM_CASL */ |
cf48eb9a WD |
150 | if (speed > 100000000) { |
151 | /* | |
152 | * 133 MHz SDRAM | |
153 | */ | |
62534beb | 154 | return 0x07f00000; |
cf48eb9a WD |
155 | } else { |
156 | /* | |
157 | * default: 100 MHz SDRAM | |
158 | */ | |
62534beb | 159 | return 0x05f00000; |
cf48eb9a | 160 | } |
6d0f6bcf | 161 | #endif /* CONFIG_SYS_SDRAM_CASL */ |
62534beb SR |
162 | } |
163 | ||
5568e613 SR |
164 | /* |
165 | * Autodetect onboard SDRAM on 405 platforms | |
166 | */ | |
9973e3c6 | 167 | phys_size_t initdram(int board_type) |
c609719b | 168 | { |
62534beb | 169 | ulong speed; |
c609719b | 170 | ulong sdtr1; |
de8d5a36 | 171 | int i; |
c609719b | 172 | |
cf48eb9a WD |
173 | /* |
174 | * Determine SDRAM speed | |
175 | */ | |
176 | speed = get_bus_freq(0); /* parameter not used on ppc4xx */ | |
62534beb | 177 | |
cf48eb9a WD |
178 | /* |
179 | * sdtr1 (register SDRAM0_TR) must take into account timings listed | |
180 | * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into | |
181 | * account actual SDRAM size. So we can set up sdtr1 according to what | |
182 | * is specified in board configuration file while rtr dependds on SDRAM | |
183 | * size we are assuming before detection. | |
184 | */ | |
185 | sdtr1 = compute_sdtr1(speed); | |
c609719b | 186 | |
de8d5a36 | 187 | for (i=0; i<N_MB0CF; i++) { |
6177445d | 188 | /* |
de8d5a36 | 189 | * Disable memory controller. |
6177445d | 190 | */ |
779e9751 | 191 | mtsdram(mem_mcopt1, 0x00000000); |
e5ad56b1 | 192 | |
c609719b | 193 | /* |
de8d5a36 | 194 | * Set MB0CF for bank 0. |
c609719b | 195 | */ |
779e9751 SR |
196 | mtsdram(mem_mb0cf, mb0cf[i].reg); |
197 | mtsdram(mem_sdtr1, sdtr1); | |
198 | mtsdram(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64)); | |
e5ad56b1 | 199 | |
de8d5a36 | 200 | udelay(200); |
c609719b | 201 | |
c609719b | 202 | /* |
de8d5a36 SR |
203 | * Set memory controller options reg, MCOPT1. |
204 | * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst | |
205 | * read/prefetch. | |
c609719b | 206 | */ |
779e9751 | 207 | mtsdram(mem_mcopt1, 0x80800000); |
c609719b | 208 | |
de8d5a36 | 209 | udelay(10000); |
c609719b | 210 | |
de8d5a36 | 211 | if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { |
7bf5ecfa SR |
212 | phys_size_t size = mb0cf[i].size; |
213 | ||
de8d5a36 | 214 | /* |
d4024bb7 JO |
215 | * OK, size detected. Enable second bank if |
216 | * defined (assumes same type as bank 0) | |
de8d5a36 | 217 | */ |
d4024bb7 | 218 | #ifdef CONFIG_SDRAM_BANK1 |
779e9751 | 219 | mtsdram(mem_mcopt1, 0x00000000); |
7bf5ecfa | 220 | mtsdram(mem_mb1cf, mb0cf[i].size | mb0cf[i].reg); |
779e9751 | 221 | mtsdram(mem_mcopt1, 0x80800000); |
d4024bb7 | 222 | udelay(10000); |
779e9751 SR |
223 | |
224 | /* | |
225 | * Check if 2nd bank is really available. | |
226 | * If the size not equal to the size of the first | |
227 | * bank, then disable the 2nd bank completely. | |
228 | */ | |
229 | if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) != | |
230 | mb0cf[i].size) { | |
231 | mtsdram(mem_mb1cf, 0); | |
232 | mtsdram(mem_mcopt1, 0); | |
7bf5ecfa SR |
233 | } else { |
234 | /* | |
235 | * We have two identical banks, so the size | |
236 | * is twice the bank size | |
237 | */ | |
238 | size = 2 * size; | |
779e9751 | 239 | } |
d4024bb7 | 240 | #endif |
bbeff30c SR |
241 | |
242 | /* | |
243 | * OK, size detected -> all done | |
244 | */ | |
7bf5ecfa | 245 | return size; |
de8d5a36 | 246 | } |
6177445d | 247 | } |
bbeff30c SR |
248 | |
249 | return 0; | |
c609719b WD |
250 | } |
251 | ||
5568e613 SR |
252 | #else /* CONFIG_440 */ |
253 | ||
5fb692ca SR |
254 | /* |
255 | * Define some default values. Those can be overwritten in the | |
256 | * board config file. | |
257 | */ | |
258 | ||
6d0f6bcf | 259 | #ifndef CONFIG_SYS_SDRAM_TABLE |
5fb692ca SR |
260 | sdram_conf_t mb0cf[] = { |
261 | {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */ | |
262 | {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */ | |
263 | }; | |
264 | #else | |
6d0f6bcf | 265 | sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE; |
5fb692ca SR |
266 | #endif |
267 | ||
6d0f6bcf JCPV |
268 | #ifndef CONFIG_SYS_SDRAM0_TR0 |
269 | #define CONFIG_SYS_SDRAM0_TR0 0x41094012 | |
5fb692ca SR |
270 | #endif |
271 | ||
272 | #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) | |
273 | ||
62534beb SR |
274 | #define NUM_TRIES 64 |
275 | #define NUM_READS 10 | |
276 | ||
277 | static void sdram_tr1_set(int ram_address, int* tr1_value) | |
278 | { | |
279 | int i; | |
280 | int j, k; | |
281 | volatile unsigned int* ram_pointer = (unsigned int *)ram_address; | |
282 | int first_good = -1, last_bad = 0x1ff; | |
283 | ||
284 | unsigned long test[NUM_TRIES] = { | |
285 | 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, | |
286 | 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, | |
287 | 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, | |
288 | 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, | |
289 | 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, | |
290 | 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, | |
291 | 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, | |
292 | 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, | |
293 | 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, | |
294 | 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, | |
295 | 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, | |
296 | 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, | |
297 | 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, | |
298 | 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, | |
299 | 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, | |
300 | 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; | |
301 | ||
302 | /* go through all possible SDRAM0_TR1[RDCT] values */ | |
303 | for (i=0; i<=0x1ff; i++) { | |
304 | /* set the current value for TR1 */ | |
305 | mtsdram(mem_tr1, (0x80800800 | i)); | |
306 | ||
307 | /* write values */ | |
308 | for (j=0; j<NUM_TRIES; j++) { | |
309 | ram_pointer[j] = test[j]; | |
310 | ||
311 | /* clear any cache at ram location */ | |
312 | __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); | |
313 | } | |
314 | ||
315 | /* read values back */ | |
316 | for (j=0; j<NUM_TRIES; j++) { | |
317 | for (k=0; k<NUM_READS; k++) { | |
318 | /* clear any cache at ram location */ | |
319 | __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); | |
320 | ||
321 | if (ram_pointer[j] != test[j]) | |
322 | break; | |
323 | } | |
324 | ||
325 | /* read error */ | |
326 | if (k != NUM_READS) | |
327 | break; | |
328 | } | |
329 | ||
330 | /* we have a SDRAM0_TR1[RDCT] that is part of the window */ | |
331 | if (j == NUM_TRIES) { | |
332 | if (first_good == -1) | |
333 | first_good = i; /* found beginning of window */ | |
334 | } else { /* bad read */ | |
335 | /* if we have not had a good read then don't care */ | |
336 | if (first_good != -1) { | |
337 | /* first failure after a good read */ | |
338 | last_bad = i-1; | |
339 | break; | |
340 | } | |
341 | } | |
342 | } | |
343 | ||
344 | /* return the current value for TR1 */ | |
345 | *tr1_value = (first_good + last_bad) / 2; | |
346 | } | |
347 | ||
5568e613 SR |
348 | /* |
349 | * Autodetect onboard DDR SDRAM on 440 platforms | |
350 | * | |
351 | * NOTE: Some of the hardcoded values are hardware dependant, | |
cf48eb9a WD |
352 | * so this should be extended for other future boards |
353 | * using this routine! | |
5568e613 | 354 | */ |
9973e3c6 | 355 | phys_size_t initdram(int board_type) |
5568e613 SR |
356 | { |
357 | int i; | |
62534beb | 358 | int tr1_bank1; |
5568e613 | 359 | |
5fb692ca SR |
360 | #if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ |
361 | defined(CONFIG_440GR) || defined(CONFIG_440SP) | |
899620c2 SR |
362 | /* |
363 | * Soft-reset SDRAM controller. | |
364 | */ | |
365 | mtsdr(sdr_srst, SDR0_SRST_DMC); | |
366 | mtsdr(sdr_srst, 0x00000000); | |
367 | #endif | |
368 | ||
5568e613 SR |
369 | for (i=0; i<N_MB0CF; i++) { |
370 | /* | |
371 | * Disable memory controller. | |
372 | */ | |
373 | mtsdram(mem_cfg0, 0x00000000); | |
374 | ||
375 | /* | |
376 | * Setup some default | |
377 | */ | |
cf48eb9a WD |
378 | mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ |
379 | mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ | |
5568e613 SR |
380 | mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ |
381 | mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */ | |
cf48eb9a | 382 | mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ |
5568e613 SR |
383 | |
384 | /* | |
385 | * Following for CAS Latency = 2.5 @ 133 MHz PLB | |
386 | */ | |
387 | mtsdram(mem_b0cr, mb0cf[i].reg); | |
6d0f6bcf | 388 | mtsdram(mem_tr0, CONFIG_SYS_SDRAM0_TR0); |
5568e613 | 389 | mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/ |
f07ae7a9 | 390 |