blob: d520cd3ff4c1ccac13cc63917b66e7825e2dbc83 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roese8d982302007-01-18 10:25:34 +01002 * (C) Copyright 2005-2007
Stefan Roesec443fe92005-11-22 13:20:42 +01003 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
Stefan Roesefd637932006-03-17 10:28:24 +01005 * (C) Copyright 2006
6 * DAVE Srl <www.dave-tech.it>
7 *
stroese55ca7492004-07-15 14:41:13 +00008 * (C) Copyright 2002-2004
wdenkc6097192002-11-03 00:24:07 +00009 * 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
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenkc6097192002-11-03 00:24:07 +000022 * 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>
Stefan Roesefd637932006-03-17 10:28:24 +010033#include "sdram.h"
wdenkc6097192002-11-03 00:24:07 +000034
wdenkc6097192002-11-03 00:24:07 +000035#ifdef CONFIG_SDRAM_BANK0
36
Stefan Roese8d982302007-01-18 10:25:34 +010037#ifndef CONFIG_440
wdenkc6097192002-11-03 00:24:07 +000038
Stefan Roesec443fe92005-11-22 13:20:42 +010039#ifndef CFG_SDRAM_TABLE
stroese55ca7492004-07-15 14:41:13 +000040sdram_conf_t mb0cf[] = {
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020041 {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */
42 {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */
43 {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */
44 {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */
45 {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */
stroese55ca7492004-07-15 14:41:13 +000046};
Stefan Roesec443fe92005-11-22 13:20:42 +010047#else
48sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
49#endif
50
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020051#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
stroese55ca7492004-07-15 14:41:13 +000052
Stefan Roesefd637932006-03-17 10:28:24 +010053#ifdef CFG_SDRAM_CASL
54static ulong ns2clks(ulong ns)
55{
56 ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
57
58 return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
59}
60#endif /* CFG_SDRAM_CASL */
61
62static ulong compute_sdtr1(ulong speed)
63{
64#ifdef CFG_SDRAM_CASL
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020065 ulong tmp;
66 ulong sdtr1 = 0;
Stefan Roesefd637932006-03-17 10:28:24 +010067
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020068 /* CASL */
69 if (CFG_SDRAM_CASL < 2)
70 sdtr1 |= (1 << SDRAM0_TR_CASL);
71 else
72 if (CFG_SDRAM_CASL > 4)
73 sdtr1 |= (3 << SDRAM0_TR_CASL);
74 else
75 sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL);
Stefan Roesefd637932006-03-17 10:28:24 +010076
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020077 /* PTA */
78 tmp = ns2clks(CFG_SDRAM_PTA);
79 if ((tmp >= 2) && (tmp <= 4))
80 sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
81 else
82 sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
Stefan Roesefd637932006-03-17 10:28:24 +010083
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020084 /* CTP */
85 tmp = ns2clks(CFG_SDRAM_CTP);
86 if ((tmp >= 2) && (tmp <= 4))
87 sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
88 else
89 sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
Stefan Roesefd637932006-03-17 10:28:24 +010090
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020091 /* LDF */
92 tmp = ns2clks(CFG_SDRAM_LDF);
93 if ((tmp >= 2) && (tmp <= 4))
94 sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
95 else
96 sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
Stefan Roesefd637932006-03-17 10:28:24 +010097
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020098 /* RFTA */
99 tmp = ns2clks(CFG_SDRAM_RFTA);
100 if ((tmp >= 4) && (tmp <= 10))
101 sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
102 else
103 sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
Stefan Roesefd637932006-03-17 10:28:24 +0100104
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200105 /* RCD */
106 tmp = ns2clks(CFG_SDRAM_RCD);
107 if ((tmp >= 2) && (tmp <= 4))
108 sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
109 else
110 sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
Stefan Roesefd637932006-03-17 10:28:24 +0100111
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200112 return sdtr1;
Stefan Roesefd637932006-03-17 10:28:24 +0100113#else /* CFG_SDRAM_CASL */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200114 /*
115 * If no values are configured in the board config file
116 * use the default values, which seem to be ok for most
117 * boards.
118 *
119 * REMARK:
120 * For new board ports we strongly recommend to define the
121 * correct values for the used SDRAM chips in your board
122 * config file (see PPChameleonEVB.h)
123 */
124 if (speed > 100000000) {
125 /*
126 * 133 MHz SDRAM
127 */
128 return 0x01074015;
129 } else {
130 /*
131 * default: 100 MHz SDRAM
132 */
133 return 0x0086400d;
134 }
Stefan Roesefd637932006-03-17 10:28:24 +0100135#endif /* CFG_SDRAM_CASL */
136}
137
138/* refresh is expressed in ms */
139static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
140{
141#ifdef CFG_SDRAM_CASL
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200142 ulong tmp;
Stefan Roesefd637932006-03-17 10:28:24 +0100143
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200144 tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
145 tmp /= 1000000;
Stefan Roesefd637932006-03-17 10:28:24 +0100146
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200147 return ((tmp & 0x00003FF8) << 16);
Stefan Roesefd637932006-03-17 10:28:24 +0100148#else /* CFG_SDRAM_CASL */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200149 if (speed > 100000000) {
150 /*
151 * 133 MHz SDRAM
152 */
Stefan Roesefd637932006-03-17 10:28:24 +0100153 return 0x07f00000;
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200154 } else {
155 /*
156 * default: 100 MHz SDRAM
157 */
Stefan Roesefd637932006-03-17 10:28:24 +0100158 return 0x05f00000;
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200159 }
Stefan Roesefd637932006-03-17 10:28:24 +0100160#endif /* CFG_SDRAM_CASL */
161}
162
Stefan Roesec443fe92005-11-22 13:20:42 +0100163/*
164 * Autodetect onboard SDRAM on 405 platforms
165 */
wdenkc6097192002-11-03 00:24:07 +0000166void sdram_init(void)
167{
Stefan Roesefd637932006-03-17 10:28:24 +0100168 ulong speed;
wdenkc6097192002-11-03 00:24:07 +0000169 ulong sdtr1;
stroese55ca7492004-07-15 14:41:13 +0000170 int i;
wdenkc6097192002-11-03 00:24:07 +0000171
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200172 /*
173 * Determine SDRAM speed
174 */
175 speed = get_bus_freq(0); /* parameter not used on ppc4xx */
Stefan Roesefd637932006-03-17 10:28:24 +0100176
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200177 /*
178 * sdtr1 (register SDRAM0_TR) must take into account timings listed
179 * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
180 * account actual SDRAM size. So we can set up sdtr1 according to what
181 * is specified in board configuration file while rtr dependds on SDRAM
182 * size we are assuming before detection.
183 */
184 sdtr1 = compute_sdtr1(speed);
wdenkc6097192002-11-03 00:24:07 +0000185
stroese55ca7492004-07-15 14:41:13 +0000186 for (i=0; i<N_MB0CF; i++) {
stroese51c57b92003-02-10 16:26:37 +0000187 /*
stroese55ca7492004-07-15 14:41:13 +0000188 * Disable memory controller.
stroese51c57b92003-02-10 16:26:37 +0000189 */
stroese55ca7492004-07-15 14:41:13 +0000190 mtsdram0(mem_mcopt1, 0x00000000);
wdenk41e2e052003-02-11 01:49:43 +0000191
wdenkc6097192002-11-03 00:24:07 +0000192 /*
stroese55ca7492004-07-15 14:41:13 +0000193 * Set MB0CF for bank 0.
wdenkc6097192002-11-03 00:24:07 +0000194 */
stroese55ca7492004-07-15 14:41:13 +0000195 mtsdram0(mem_mb0cf, mb0cf[i].reg);
196 mtsdram0(mem_sdtr1, sdtr1);
Stefan Roesefd637932006-03-17 10:28:24 +0100197 mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
wdenk41e2e052003-02-11 01:49:43 +0000198
stroese55ca7492004-07-15 14:41:13 +0000199 udelay(200);
wdenkc6097192002-11-03 00:24:07 +0000200
wdenkc6097192002-11-03 00:24:07 +0000201 /*
stroese55ca7492004-07-15 14:41:13 +0000202 * Set memory controller options reg, MCOPT1.
203 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
204 * read/prefetch.
wdenkc6097192002-11-03 00:24:07 +0000205 */
stroese55ca7492004-07-15 14:41:13 +0000206 mtsdram0(mem_mcopt1, 0x80800000);
wdenkc6097192002-11-03 00:24:07 +0000207
stroese55ca7492004-07-15 14:41:13 +0000208 udelay(10000);
wdenkc6097192002-11-03 00:24:07 +0000209
stroese55ca7492004-07-15 14:41:13 +0000210 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
211 /*
212 * OK, size detected -> all done
213 */
214 return;
215 }
stroese51c57b92003-02-10 16:26:37 +0000216 }
wdenkc6097192002-11-03 00:24:07 +0000217}
218
Stefan Roesec443fe92005-11-22 13:20:42 +0100219#else /* CONFIG_440 */
220
Stefan Roese8d982302007-01-18 10:25:34 +0100221/*
222 * Define some default values. Those can be overwritten in the
223 * board config file.
224 */
225
226#ifndef CFG_SDRAM_TABLE
227sdram_conf_t mb0cf[] = {
228 {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */
229 {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */
230};
231#else
232sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
233#endif
234
235#ifndef CFG_SDRAM0_TR0
236#define CFG_SDRAM0_TR0 0x41094012
237#endif
238
239#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
240
Stefan Roesefd637932006-03-17 10:28:24 +0100241#define NUM_TRIES 64
242#define NUM_READS 10
243
244static void sdram_tr1_set(int ram_address, int* tr1_value)
245{
246 int i;
247 int j, k;
248 volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
249 int first_good = -1, last_bad = 0x1ff;
250
251 unsigned long test[NUM_TRIES] = {
252 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
253 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
254 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
255 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
256 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
257 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
258 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
259 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
260 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
261 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
262 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
263 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
264 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
265 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
266 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
267 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
268
269 /* go through all possible SDRAM0_TR1[RDCT] values */
270 for (i=0; i<=0x1ff; i++) {
271 /* set the current value for TR1 */
272 mtsdram(mem_tr1, (0x80800800 | i));
273
274 /* write values */
275 for (j=0; j<NUM_TRIES; j++) {
276 ram_pointer[j] = test[j];
277
278 /* clear any cache at ram location */
279 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
280 }
281
282 /* read values back */
283 for (j=0; j<NUM_TRIES; j++) {
284 for (k=0; k<NUM_READS; k++) {
285 /* clear any cache at ram location */
286 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
287
288 if (ram_pointer[j] != test[j])
289 break;
290 }
291
292 /* read error */
293 if (k != NUM_READS)
294 break;
295 }
296
297 /* we have a SDRAM0_TR1[RDCT] that is part of the window */
298 if (j == NUM_TRIES) {
299 if (first_good == -1)
300 first_good = i; /* found beginning of window */
301 } else { /* bad read */
302 /* if we have not had a good read then don't care */
303 if (first_good != -1) {
304 /* first failure after a good read */
305 last_bad = i-1;
306 break;
307 }
308 }
309 }
310
311 /* return the current value for TR1 */
312 *tr1_value = (first_good + last_bad) / 2;
313}
314
Stefan Roesefd637932006-03-17 10:28:24 +0100315#ifdef CONFIG_SDRAM_ECC
316static void ecc_init(ulong start, ulong size)
317{
318 ulong current_addr; /* current byte address */
319 ulong end_addr; /* end of memory region */
320 ulong addr_inc; /* address skip between writes */
321 ulong cfg0_reg; /* for restoring ECC state */
322
323 /*
324 * TODO: Enable dcache before running this test (speedup)
325 */
326
327 mfsdram(mem_cfg0, cfg0_reg);
328 mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
329
330 /*
331 * look at geometry of SDRAM (data width) to determine whether we
332 * can skip words when writing
333 */
334 if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
335 addr_inc = 4;
336 else
337 addr_inc = 8;
338
339 current_addr = start;
340 end_addr = start + size;
341
342 while (current_addr < end_addr) {
343 *((ulong *)current_addr) = 0x00000000;
344 current_addr += addr_inc;
345 }
346
347 /*
348 * TODO: Flush dcache and disable it again
349 */
350
351 /*
352 * Enable ecc checking and parity errors
353 */
354 mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
355}
356#endif
357
Stefan Roesec443fe92005-11-22 13:20:42 +0100358/*
359 * Autodetect onboard DDR SDRAM on 440 platforms
360 *
361 * NOTE: Some of the hardcoded values are hardware dependant,
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200362 * so this should be extended for other future boards
363 * using this routine!
Stefan Roesec443fe92005-11-22 13:20:42 +0100364 */
365long int initdram(int board_type)
366{
367 int i;
Stefan Roesefd637932006-03-17 10:28:24 +0100368 int tr1_bank1;
Stefan Roesec443fe92005-11-22 13:20:42 +0100369
Stefan Roese8d982302007-01-18 10:25:34 +0100370#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
371 defined(CONFIG_440GR) || defined(CONFIG_440SP)
Stefan Roese49639682006-08-15 14:22:35 +0200372 /*
373 * Soft-reset SDRAM controller.
374 */
375 mtsdr(sdr_srst, SDR0_SRST_DMC);
376 mtsdr(sdr_srst, 0x00000000);
377#endif
378
Stefan Roesec443fe92005-11-22 13:20:42 +0100379 for (i=0; i<N_MB0CF; i++) {
380 /*
381 * Disable memory controller.
382 */
383 mtsdram(mem_cfg0, 0x00000000);
384
385 /*
386 * Setup some default
387 */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200388 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */
389 mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */
Stefan Roesec443fe92005-11-22 13:20:42 +0100390 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */
391 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200392 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */
Stefan Roesec443fe92005-11-22 13:20:42 +0100393
394 /*
395 * Following for CAS Latency = 2.5 @ 133 MHz PLB
396 */
397 mtsdram(mem_b0cr, mb0cf[i].reg);
Stefan Roese8d982302007-01-18 10:25:34 +0100398 mtsdram(mem_tr0, CFG_SDRAM0_TR0);
Stefan Roesec443fe92005-11-22 13:20:42 +0100399 mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
Stefan Roese76e3d2a2007-01-06 15:58:09 +0100400 mtsdram(mem_rtr, 0x04100000); /* Interval 7.8µs @ 133MHz PLB */
Stefan Roesec443fe92005-11-22 13:20:42 +0100401 mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM*/
402 udelay(400); /* Delay 200 usecs (min) */
403
404 /*
405 * Enable the controller, then wait for DCEN to complete
406 */
Stefan Roesee335ee02006-07-28 18:34:58 +0200407 mtsdram(mem_cfg0, 0x82000000); /* DCEN=1, PMUD=0, 64-bit */
Stefan Roesec443fe92005-11-22 13:20:42 +0100408 udelay(10000);
409
410 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
411 /*
Stefan Roesefd637932006-03-17 10:28:24 +0100412 * Optimize TR1 to current hardware environment
413 */
414 sdram_tr1_set(0x00000000, &tr1_bank1);
415 mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
416
417#ifdef CONFIG_SDRAM_ECC
418 ecc_init(0, mb0cf[i].size);
419#endif
420
421 /*
Stefan Roesec443fe92005-11-22 13:20:42 +0100422 * OK, size detected -> all done
423 */
424 return mb0cf[i].size;
425 }
426 }
427
428 return 0; /* nothing found ! */
429}
430
431#endif /* CONFIG_440 */
432
wdenkc6097192002-11-03 00:24:07 +0000433#endif /* CONFIG_SDRAM_BANK0 */