]>
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 | |
5568e613 | 40 | #ifndef CFG_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 SR |
48 | #else |
49 | sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE; | |
50 | #endif | |
51 | ||
cf48eb9a | 52 | #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) |
c609719b | 53 | |
62534beb SR |
54 | #ifdef CFG_SDRAM_CASL |
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 | } | |
61 | #endif /* CFG_SDRAM_CASL */ | |
62 | ||
63 | static ulong compute_sdtr1(ulong speed) | |
64 | { | |
65 | #ifdef CFG_SDRAM_CASL | |
cf48eb9a WD |
66 | ulong tmp; |
67 | ulong sdtr1 = 0; | |
68 | ||
69 | /* CASL */ | |
70 | if (CFG_SDRAM_CASL < 2) | |
71 | sdtr1 |= (1 << SDRAM0_TR_CASL); | |
72 | else | |
73 | if (CFG_SDRAM_CASL > 4) | |
74 | sdtr1 |= (3 << SDRAM0_TR_CASL); | |
75 | else | |
76 | sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL); | |
77 | ||
78 | /* PTA */ | |
79 | tmp = ns2clks(CFG_SDRAM_PTA); | |
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 */ | |
86 | tmp = ns2clks(CFG_SDRAM_CTP); | |
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 */ | |
93 | tmp = ns2clks(CFG_SDRAM_LDF); | |
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 */ | |
100 | tmp = ns2clks(CFG_SDRAM_RFTA); | |
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 */ | |
107 | tmp = ns2clks(CFG_SDRAM_RCD); | |
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; | |
62534beb | 114 | #else /* CFG_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 | } | |
62534beb SR |
136 | #endif /* CFG_SDRAM_CASL */ |
137 | } | |
138 | ||
139 | /* refresh is expressed in ms */ | |
140 | static ulong compute_rtr(ulong speed, ulong rows, ulong refresh) | |
141 | { | |
142 | #ifdef CFG_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); |
62534beb | 149 | #else /* CFG_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 | } |
62534beb SR |
161 | #endif /* CFG_SDRAM_CASL */ |
162 | } | |
163 | ||
5568e613 SR |
164 | /* |
165 | * Autodetect onboard SDRAM on 405 platforms | |
166 | */ | |
c609719b WD |
167 | void sdram_init(void) |
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 SR |
211 | if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { |
212 | /* | |
d4024bb7 JO |
213 | * OK, size detected. Enable second bank if |
214 | * defined (assumes same type as bank 0) | |
de8d5a36 | 215 | */ |
d4024bb7 JO |
216 | #ifdef CONFIG_SDRAM_BANK1 |
217 | u32 b1cr = mb0cf[i].size | mb0cf[i].reg; | |
218 | ||
779e9751 SR |
219 | mtsdram(mem_mcopt1, 0x00000000); |
220 | mtsdram(mem_mb1cf, b1cr); /* SDRAM0_B1CR */ | |
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); | |
233 | } | |
d4024bb7 | 234 | #endif |
de8d5a36 SR |
235 | return; |
236 | } | |
6177445d | 237 | } |
c609719b WD |
238 | } |
239 | ||
5568e613 SR |
240 | #else /* CONFIG_440 */ |
241 | ||
5fb692ca SR |
242 | /* |
243 | * Define some default values. Those can be overwritten in the | |
244 | * board config file. | |
245 | */ | |
246 | ||
247 | #ifndef CFG_SDRAM_TABLE | |
248 | sdram_conf_t mb0cf[] = { | |
249 | {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */ | |
250 | {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */ | |
251 | }; | |
252 | #else | |
253 | sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE; | |
254 | #endif | |
255 | ||
256 | #ifndef CFG_SDRAM0_TR0 | |
257 | #define CFG_SDRAM0_TR0 0x41094012 | |
258 | #endif | |
259 | ||
260 | #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) | |
261 | ||
62534beb SR |
262 | #define NUM_TRIES 64 |
263 | #define NUM_READS 10 | |
264 | ||
265 | static void sdram_tr1_set(int ram_address, int* tr1_value) | |
266 | { | |
267 | int i; | |
268 | int j, k; | |
269 | volatile unsigned int* ram_pointer = (unsigned int *)ram_address; | |
270 | int first_good = -1, last_bad = 0x1ff; | |
271 | ||
272 | unsigned long test[NUM_TRIES] = { | |
273 | 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, | |
274 | 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, | |
275 | 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, | |
276 | 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, | |
277 | 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, | |
278 | 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, | |
279 | 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, | |
280 | 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, | |
281 | 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, | |
282 | 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, | |
283 | 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, | |
284 | 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, | |
285 | 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, | |
286 | 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, | |
287 | 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, | |
288 | 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; | |
289 | ||
290 | /* go through all possible SDRAM0_TR1[RDCT] values */ | |
291 | for (i=0; i<=0x1ff; i++) { | |
292 | /* set the current value for TR1 */ | |
293 | mtsdram(mem_tr1, (0x80800800 | i)); | |
294 | ||
295 | /* write values */ | |
296 | for (j=0; j<NUM_TRIES; j++) { | |
297 | ram_pointer[j] = test[j]; | |
298 | ||
299 | /* clear any cache at ram location */ | |
300 | __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); | |
301 | } | |
302 | ||
303 | /* read values back */ | |
304 | for (j=0; j<NUM_TRIES; j++) { | |
305 | for (k=0; k<NUM_READS; k++) { | |
306 | /* clear any cache at ram location */ | |
307 | __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); | |
308 | ||
309 | if (ram_pointer[j] != test[j]) | |
310 | break; | |
311 | } | |
312 | ||
313 | /* read error */ | |
314 | if (k != NUM_READS) | |
315 | break; | |
316 | } | |
317 | ||
318 | /* we have a SDRAM0_TR1[RDCT] that is part of the window */ | |
319 | if (j == NUM_TRIES) { | |
320 | if (first_good == -1) | |
321 | first_good = i; /* found beginning of window */ | |
322 | } else { /* bad read */ | |
323 | /* if we have not had a good read then don't care */ | |
324 | if (first_good != -1) { | |
325 | /* first failure after a good read */ | |
326 | last_bad = i-1; | |
327 | break; | |
328 | } | |
329 | } | |
330 | } | |
331 | ||
332 | /* return the current value for TR1 */ | |
333 | *tr1_value = (first_good + last_bad) / 2; | |
334 | } | |
335 | ||
5568e613 SR |
336 | /* |
337 | * Autodetect onboard DDR SDRAM on 440 platforms | |
338 | * | |
339 | * NOTE: Some of the hardcoded values are hardware dependant, | |
cf48eb9a WD |
340 | * so this should be extended for other future boards |
341 | * using this routine! | |
5568e613 SR |
342 | */ |
343 | long int initdram(int board_type) | |
344 | { | |
345 | int i; | |
62534beb | 346 | int tr1_bank1; |
5568e613 | 347 | |
5fb692ca SR |
348 | #if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ |
349 | defined(CONFIG_440GR) || defined(CONFIG_440SP) | |
899620c2 SR |
350 | /* |
351 | * Soft-reset SDRAM controller. | |
352 | */ | |
353 | mtsdr(sdr_srst, SDR0_SRST_DMC); | |
354 | mtsdr(sdr_srst, 0x00000000); | |
355 | #endif | |
356 | ||
5568e613 SR |
357 | for (i=0; i<N_MB0CF; i++) { |
358 | /* | |
359 | * Disable memory controller. | |
360 | */ | |
361 | mtsdram(mem_cfg0, 0x00000000); | |
362 | ||
363 | /* | |
364 | * Setup some default | |
365 | */ | |
cf48eb9a WD |
366 | mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ |
367 | mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ | |
5568e613 SR |
368 | mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ |
369 | mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */ | |
cf48eb9a | 370 | mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ |
5568e613 SR |
371 | |
372 | /* | |
373 | * Following for CAS Latency = 2.5 @ 133 MHz PLB | |
374 | */ | |
375 | mtsdram(mem_b0cr, mb0cf[i].reg); | |
5fb692ca | 376 | mtsdram(mem_tr0, CFG_SDRAM0_TR0); |
5568e613 | 377 | mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/ |
f07ae7a9 | 378 |