blob: 901d650cea18f6f8855eff63412843a350b82e4b [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roese5fb692c2007-01-18 10:25:34 +01002 * (C) Copyright 2005-2007
Stefan Roese5568e612005-11-22 13:20:42 +01003 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
Stefan Roese62534be2006-03-17 10:28:24 +01005 * (C) Copyright 2006
6 * DAVE Srl <www.dave-tech.it>
7 *
stroesede8d5a32004-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 Denkcf48eb92006-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 Roese62534be2006-03-17 10:28:24 +010033#include "sdram.h"
Grant Ericksonc821b5f2008-05-22 14:44:14 -070034#include "ecc.h"
wdenkc6097192002-11-03 00:24:07 +000035
wdenkc6097192002-11-03 00:24:07 +000036#ifdef CONFIG_SDRAM_BANK0
37
Stefan Roese5fb692c2007-01-18 10:25:34 +010038#ifndef CONFIG_440
wdenkc6097192002-11-03 00:24:07 +000039
Stefan Roese5568e612005-11-22 13:20:42 +010040#ifndef CFG_SDRAM_TABLE
stroesede8d5a32004-07-15 14:41:13 +000041sdram_conf_t mb0cf[] = {
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020042 {(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) */
stroesede8d5a32004-07-15 14:41:13 +000047};
Stefan Roese5568e612005-11-22 13:20:42 +010048#else
49sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
50#endif
51
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020052#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
stroesede8d5a32004-07-15 14:41:13 +000053
Stefan Roese62534be2006-03-17 10:28:24 +010054#ifdef CFG_SDRAM_CASL
55static 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
63static ulong compute_sdtr1(ulong speed)
64{
65#ifdef CFG_SDRAM_CASL
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020066 ulong tmp;
67 ulong sdtr1 = 0;
Stefan Roese62534be2006-03-17 10:28:24 +010068
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020069 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +010077
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020078 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +010084
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020085 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +010091
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020092 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +010098
Wolfgang Denkcf48eb92006-04-16 10:51:58 +020099 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +0100105
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200106 /* 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);
Stefan Roese62534be2006-03-17 10:28:24 +0100112
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200113 return sdtr1;
Stefan Roese62534be2006-03-17 10:28:24 +0100114#else /* CFG_SDRAM_CASL */
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200115 /*
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 }
Stefan Roese62534be2006-03-17 10:28:24 +0100136#endif /* CFG_SDRAM_CASL */
137}
138
139/* refresh is expressed in ms */
140static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
141{
142#ifdef CFG_SDRAM_CASL
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200143 ulong tmp;
Stefan Roese62534be2006-03-17 10:28:24 +0100144
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200145 tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
146 tmp /= 1000000;
Stefan Roese62534be2006-03-17 10:28:24 +0100147
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200148 return ((tmp & 0x00003FF8) << 16);
Stefan Roese62534be2006-03-17 10:28:24 +0100149#else /* CFG_SDRAM_CASL */
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200150 if (speed > 100000000) {
151 /*
152 * 133 MHz SDRAM
153 */
Stefan Roese62534be2006-03-17 10:28:24 +0100154 return 0x07f00000;
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200155 } else {
156 /*
157 * default: 100 MHz SDRAM
158 */
Stefan Roese62534be2006-03-17 10:28:24 +0100159 return 0x05f00000;
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200160 }
Stefan Roese62534be2006-03-17 10:28:24 +0100161#endif /* CFG_SDRAM_CASL */
162}
163
Stefan Roese5568e612005-11-22 13:20:42 +0100164/*
165 * Autodetect onboard SDRAM on 405 platforms
166 */
wdenkc6097192002-11-03 00:24:07 +0000167void sdram_init(void)
168{
Stefan Roese62534be2006-03-17 10:28:24 +0100169 ulong speed;
wdenkc6097192002-11-03 00:24:07 +0000170 ulong sdtr1;
stroesede8d5a32004-07-15 14:41:13 +0000171 int i;
wdenkc6097192002-11-03 00:24:07 +0000172
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200173 /*
174 * Determine SDRAM speed
175 */
176 speed = get_bus_freq(0); /* parameter not used on ppc4xx */
Stefan Roese62534be2006-03-17 10:28:24 +0100177
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200178 /*
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);
wdenkc6097192002-11-03 00:24:07 +0000186
stroesede8d5a32004-07-15 14:41:13 +0000187 for (i=0; i<N_MB0CF; i++) {
stroese61774452003-02-10 16:26:37 +0000188 /*
stroesede8d5a32004-07-15 14:41:13 +0000189 * Disable memory controller.
stroese61774452003-02-10 16:26:37 +0000190 */
Stefan Roese779e9752007-08-14 14:44:41 +0200191 mtsdram(mem_mcopt1, 0x00000000);
wdenke5ad56b2003-02-11 01:49:43 +0000192
wdenkc6097192002-11-03 00:24:07 +0000193 /*
stroesede8d5a32004-07-15 14:41:13 +0000194 * Set MB0CF for bank 0.
wdenkc6097192002-11-03 00:24:07 +0000195 */
Stefan Roese779e9752007-08-14 14:44:41 +0200196 mtsdram(mem_mb0cf, mb0cf[i].reg);
197 mtsdram(mem_sdtr1, sdtr1);
198 mtsdram(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
wdenke5ad56b2003-02-11 01:49:43 +0000199
stroesede8d5a32004-07-15 14:41:13 +0000200 udelay(200);
wdenke5ad56b2003-02-11 01:49:43 +0000201
wdenkc6097192002-11-03 00:24:07 +0000202 /*
stroesede8d5a32004-07-15 14:41:13 +0000203 * 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.
wdenkc6097192002-11-03 00:24:07 +0000206 */
Stefan Roese779e9752007-08-14 14:44:41 +0200207 mtsdram(mem_mcopt1, 0x80800000);
stroesede8d5a32004-07-15 14:41:13 +0000208
209 udelay(10000);
210
211 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
212 /*
John Otkend4024bb2007-07-26 17:49:11 +0200213 * OK, size detected. Enable second bank if
214 * defined (assumes same type as bank 0)
stroesede8d5a32004-07-15 14:41:13 +0000215 */
John Otkend4024bb2007-07-26 17:49:11 +0200216#ifdef CONFIG_SDRAM_BANK1
217 u32 b1cr = mb0cf[i].size | mb0cf[i].reg;
218
Stefan Roese779e9752007-08-14 14:44:41 +0200219 mtsdram(mem_mcopt1, 0x00000000);
220 mtsdram(mem_mb1cf, b1cr); /* SDRAM0_B1CR */
221 mtsdram(mem_mcopt1, 0x80800000);
John Otkend4024bb2007-07-26 17:49:11 +0200222 udelay(10000);
Stefan Roese779e9752007-08-14 14:44:41 +0200223
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 }
John Otkend4024bb2007-07-26 17:49:11 +0200234#endif
stroesede8d5a32004-07-15 14:41:13 +0000235 return;
236 }
wdenkc6097192002-11-03 00:24:07 +0000237 }
wdenkc6097192002-11-03 00:24:07 +0000238}
239
Stefan Roese5568e612005-11-22 13:20:42 +0100240#else /* CONFIG_440 */
241
Stefan Roese5fb692c2007-01-18 10:25:34 +0100242/*
243 * Define some default values. Those can be overwritten in the
244 * board config file.
245 */
246
247#ifndef CFG_SDRAM_TABLE
248sdram_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
253sdram_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
Stefan Roese62534be2006-03-17 10:28:24 +0100262#define NUM_TRIES 64
263#define NUM_READS 10
264
265static 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
Stefan Roese5568e612005-11-22 13:20:42 +0100336/*
337 * Autodetect onboard DDR SDRAM on 440 platforms
338 *
339 * NOTE: Some of the hardcoded values are hardware dependant,
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200340 * so this should be extended for other future boards
341 * using this routine!
Stefan Roese5568e612005-11-22 13:20:42 +0100342 */
343long int initdram(int board_type)
344{
345 int i;
Stefan Roese62534be2006-03-17 10:28:24 +0100346 int tr1_bank1;
Stefan Roese5568e612005-11-22 13:20:42 +0100347
Stefan Roese5fb692c2007-01-18 10:25:34 +0100348#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
349 defined(CONFIG_440GR) || defined(CONFIG_440SP)
Stefan Roese899620c2006-08-15 14:22:35 +0200350 /*
351 * Soft-reset SDRAM controller.
352 */
353 mtsdr(sdr_srst, SDR0_SRST_DMC);
354 mtsdr(sdr_srst, 0x00000000);
355#endif
356
Stefan Roese5568e612005-11-22 13:20:42 +0100357 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 */
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200366 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */
367 mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */
Stefan Roese5568e612005-11-22 13:20:42 +0100368 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */
369 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */
Wolfgang Denkcf48eb92006-04-16 10:51:58 +0200370 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */
Stefan Roese5568e612005-11-22 13:20:42 +0100371
372 /*
373 * Following for CAS Latency = 2.5 @ 133 MHz PLB
374 */
375 mtsdram(mem_b0cr, mb0cf[i].reg);
Stefan Roese5fb692c2007-01-18 10:25:34 +0100376 mtsdram(mem_tr0, CFG_SDRAM0_TR0);
Stefan Roese5568e612005-11-22 13:20:42 +0100377 mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
Stefan Roesef07ae7a2007-01-06 15:58:09 +0100378 mtsdram(mem_rtr, 0x04100000); /* Interval 7.8µs @ 133MHz PLB */
Stefan Roese5568e612005-11-22 13:20:42 +0100379 mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM*/
380 udelay(400); /* Delay 200 usecs (min) */
381
382 /*
383 * Enable the controller, then wait for DCEN to complete
384 */
Stefan Roesea2c95a72006-07-28 18:34:58 +0200385 mtsdram(mem_cfg0, 0x82000000); /* DCEN=1, PMUD=0, 64-bit */
Stefan Roese5568e612005-11-22 13:20:42 +0100386 udelay(10000);
387
388 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
389 /*
Stefan Roese62534be2006-03-17 10:28:24 +0100390 * Optimize TR1 to current hardware environment
391 */
392 sdram_tr1_set(0x00000000, &tr1_bank1);
393 mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
394
395#ifdef CONFIG_SDRAM_ECC
396 ecc_init(0, mb0cf[i].size);
397#endif
398
399 /*
Stefan Roese5568e612005-11-22 13:20:42 +0100400 * OK, size detected -> all done
401 */
402 return mb0cf[i].size;
403 }
404 }
405
406 return 0; /* nothing found ! */
407}
408
409#endif /* CONFIG_440 */
410
wdenkc6097192002-11-03 00:24:07 +0000411#endif /* CONFIG_SDRAM_BANK0 */