blob: f06038e99833203d78befb5ffec4d39285d9b415 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roesefd637932006-03-17 10:28:24 +01002 * (C) Copyright 2005-2006
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
35
36#ifdef CONFIG_SDRAM_BANK0
37
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
53
Stefan Roesec443fe92005-11-22 13:20:42 +010054#ifndef CONFIG_440
55
Stefan Roesefd637932006-03-17 10:28:24 +010056#ifdef CFG_SDRAM_CASL
57static ulong ns2clks(ulong ns)
58{
59 ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
60
61 return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
62}
63#endif /* CFG_SDRAM_CASL */
64
65static ulong compute_sdtr1(ulong speed)
66{
67#ifdef CFG_SDRAM_CASL
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020068 ulong tmp;
69 ulong sdtr1 = 0;
Stefan Roesefd637932006-03-17 10:28:24 +010070
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020071 /* CASL */
72 if (CFG_SDRAM_CASL < 2)
73 sdtr1 |= (1 << SDRAM0_TR_CASL);
74 else
75 if (CFG_SDRAM_CASL > 4)
76 sdtr1 |= (3 << SDRAM0_TR_CASL);
77 else
78 sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL);
Stefan Roesefd637932006-03-17 10:28:24 +010079
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020080 /* PTA */
81 tmp = ns2clks(CFG_SDRAM_PTA);
82 if ((tmp >= 2) && (tmp <= 4))
83 sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
84 else
85 sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
Stefan Roesefd637932006-03-17 10:28:24 +010086
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020087 /* CTP */
88 tmp = ns2clks(CFG_SDRAM_CTP);
89 if ((tmp >= 2) && (tmp <= 4))
90 sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
91 else
92 sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
Stefan Roesefd637932006-03-17 10:28:24 +010093
Wolfgang Denkebd3deb2006-04-16 10:51:58 +020094 /* LDF */
95 tmp = ns2clks(CFG_SDRAM_LDF);
96 if ((tmp >= 2) && (tmp <= 4))
97 sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
98 else
99 sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
Stefan Roesefd637932006-03-17 10:28:24 +0100100
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200101 /* RFTA */
102 tmp = ns2clks(CFG_SDRAM_RFTA);
103 if ((tmp >= 4) && (tmp <= 10))
104 sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
105 else
106 sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
Stefan Roesefd637932006-03-17 10:28:24 +0100107
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200108 /* RCD */
109 tmp = ns2clks(CFG_SDRAM_RCD);
110 if ((tmp >= 2) && (tmp <= 4))
111 sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
112 else
113 sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
Stefan Roesefd637932006-03-17 10:28:24 +0100114
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200115 return sdtr1;
Stefan Roesefd637932006-03-17 10:28:24 +0100116#else /* CFG_SDRAM_CASL */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200117 /*
118 * If no values are configured in the board config file
119 * use the default values, which seem to be ok for most
120 * boards.
121 *
122 * REMARK:
123 * For new board ports we strongly recommend to define the
124 * correct values for the used SDRAM chips in your board
125 * config file (see PPChameleonEVB.h)
126 */
127 if (speed > 100000000) {
128 /*
129 * 133 MHz SDRAM
130 */
131 return 0x01074015;
132 } else {
133 /*
134 * default: 100 MHz SDRAM
135 */
136 return 0x0086400d;
137 }
Stefan Roesefd637932006-03-17 10:28:24 +0100138#endif /* CFG_SDRAM_CASL */
139}
140
141/* refresh is expressed in ms */
142static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
143{
144#ifdef CFG_SDRAM_CASL
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200145 ulong tmp;
Stefan Roesefd637932006-03-17 10:28:24 +0100146
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200147 tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
148 tmp /= 1000000;
Stefan Roesefd637932006-03-17 10:28:24 +0100149
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200150 return ((tmp & 0x00003FF8) << 16);
Stefan Roesefd637932006-03-17 10:28:24 +0100151#else /* CFG_SDRAM_CASL */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200152 if (speed > 100000000) {
153 /*
154 * 133 MHz SDRAM
155 */
Stefan Roesefd637932006-03-17 10:28:24 +0100156 return 0x07f00000;
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200157 } else {
158 /*
159 * default: 100 MHz SDRAM
160 */
Stefan Roesefd637932006-03-17 10:28:24 +0100161 return 0x05f00000;
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200162 }
Stefan Roesefd637932006-03-17 10:28:24 +0100163#endif /* CFG_SDRAM_CASL */
164}
165
Stefan Roesec443fe92005-11-22 13:20:42 +0100166/*
167 * Autodetect onboard SDRAM on 405 platforms
168 */
wdenkc6097192002-11-03 00:24:07 +0000169void sdram_init(void)
170{
Stefan Roesefd637932006-03-17 10:28:24 +0100171 ulong speed;
wdenkc6097192002-11-03 00:24:07 +0000172 ulong sdtr1;
stroese55ca7492004-07-15 14:41:13 +0000173 int i;
wdenkc6097192002-11-03 00:24:07 +0000174
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200175 /*
176 * Determine SDRAM speed
177 */
178 speed = get_bus_freq(0); /* parameter not used on ppc4xx */
Stefan Roesefd637932006-03-17 10:28:24 +0100179
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200180 /*
181 * sdtr1 (register SDRAM0_TR) must take into account timings listed
182 * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
183 * account actual SDRAM size. So we can set up sdtr1 according to what
184 * is specified in board configuration file while rtr dependds on SDRAM
185 * size we are assuming before detection.
186 */
187 sdtr1 = compute_sdtr1(speed);
wdenkc6097192002-11-03 00:24:07 +0000188
stroese55ca7492004-07-15 14:41:13 +0000189 for (i=0; i<N_MB0CF; i++) {
stroese51c57b92003-02-10 16:26:37 +0000190 /*
stroese55ca7492004-07-15 14:41:13 +0000191 * Disable memory controller.
stroese51c57b92003-02-10 16:26:37 +0000192 */
stroese55ca7492004-07-15 14:41:13 +0000193 mtsdram0(mem_mcopt1, 0x00000000);
wdenk41e2e052003-02-11 01:49:43 +0000194
wdenkc6097192002-11-03 00:24:07 +0000195 /*
stroese55ca7492004-07-15 14:41:13 +0000196 * Set MB0CF for bank 0.
wdenkc6097192002-11-03 00:24:07 +0000197 */
stroese55ca7492004-07-15 14:41:13 +0000198 mtsdram0(mem_mb0cf, mb0cf[i].reg);
199 mtsdram0(mem_sdtr1, sdtr1);
Stefan Roesefd637932006-03-17 10:28:24 +0100200 mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
wdenk41e2e052003-02-11 01:49:43 +0000201
stroese55ca7492004-07-15 14:41:13 +0000202 udelay(200);
wdenkc6097192002-11-03 00:24:07 +0000203
wdenkc6097192002-11-03 00:24:07 +0000204 /*
stroese55ca7492004-07-15 14:41:13 +0000205 * Set memory controller options reg, MCOPT1.
206 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
207 * read/prefetch.
wdenkc6097192002-11-03 00:24:07 +0000208 */
stroese55ca7492004-07-15 14:41:13 +0000209 mtsdram0(mem_mcopt1, 0x80800000);
wdenkc6097192002-11-03 00:24:07 +0000210
stroese55ca7492004-07-15 14:41:13 +0000211 udelay(10000);
wdenkc6097192002-11-03 00:24:07 +0000212
stroese55ca7492004-07-15 14:41:13 +0000213 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
214 /*
215 * OK, size detected -> all done
216 */
217 return;
218 }
stroese51c57b92003-02-10 16:26:37 +0000219 }
wdenkc6097192002-11-03 00:24:07 +0000220}
221
Stefan Roesec443fe92005-11-22 13:20:42 +0100222#else /* CONFIG_440 */
223
Stefan Roesefd637932006-03-17 10:28:24 +0100224#define NUM_TRIES 64
225#define NUM_READS 10
226
227static void sdram_tr1_set(int ram_address, int* tr1_value)
228{
229 int i;
230 int j, k;
231 volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
232 int first_good = -1, last_bad = 0x1ff;
233
234 unsigned long test[NUM_TRIES] = {
235 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
236 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
237 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
238 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
239 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
240 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
241 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
242 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
243 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
244 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
245 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
246 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
247 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
248 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
249 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
250 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
251
252 /* go through all possible SDRAM0_TR1[RDCT] values */
253 for (i=0; i<=0x1ff; i++) {
254 /* set the current value for TR1 */
255 mtsdram(mem_tr1, (0x80800800 | i));
256
257 /* write values */
258 for (j=0; j<NUM_TRIES; j++) {
259 ram_pointer[j] = test[j];
260
261 /* clear any cache at ram location */
262 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
263 }
264
265 /* read values back */
266 for (j=0; j<NUM_TRIES; j++) {
267 for (k=0; k<NUM_READS; k++) {
268 /* clear any cache at ram location */
269 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
270
271 if (ram_pointer[j] != test[j])
272 break;
273 }
274
275 /* read error */
276 if (k != NUM_READS)
277 break;
278 }
279
280 /* we have a SDRAM0_TR1[RDCT] that is part of the window */
281 if (j == NUM_TRIES) {
282 if (first_good == -1)
283 first_good = i; /* found beginning of window */
284 } else { /* bad read */
285 /* if we have not had a good read then don't care */
286 if (first_good != -1) {
287 /* first failure after a good read */
288 last_bad = i-1;
289 break;
290 }
291 }
292 }
293
294 /* return the current value for TR1 */
295 *tr1_value = (first_good + last_bad) / 2;
296}
297
298
299#ifdef CONFIG_SDRAM_ECC
300static void ecc_init(ulong start, ulong size)
301{
302 ulong current_addr; /* current byte address */
303 ulong end_addr; /* end of memory region */
304 ulong addr_inc; /* address skip between writes */
305 ulong cfg0_reg; /* for restoring ECC state */
306
307 /*
308 * TODO: Enable dcache before running this test (speedup)
309 */
310
311 mfsdram(mem_cfg0, cfg0_reg);
312 mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
313
314 /*
315 * look at geometry of SDRAM (data width) to determine whether we
316 * can skip words when writing
317 */
318 if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
319 addr_inc = 4;
320 else
321 addr_inc = 8;
322
323 current_addr = start;
324 end_addr = start + size;
325
326 while (current_addr < end_addr) {
327 *((ulong *)current_addr) = 0x00000000;
328 current_addr += addr_inc;
329 }
330
331 /*
332 * TODO: Flush dcache and disable it again
333 */
334
335 /*
336 * Enable ecc checking and parity errors
337 */
338 mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
339}
340#endif
341
Stefan Roesec443fe92005-11-22 13:20:42 +0100342/*
343 * Autodetect onboard DDR SDRAM on 440 platforms
344 *
345 * NOTE: Some of the hardcoded values are hardware dependant,
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200346 * so this should be extended for other future boards
347 * using this routine!
Stefan Roesec443fe92005-11-22 13:20:42 +0100348 */
349long int initdram(int board_type)
350{
351 int i;
Stefan Roesefd637932006-03-17 10:28:24 +0100352 int tr1_bank1;
Stefan Roesec443fe92005-11-22 13:20:42 +0100353
Stefan Roese49639682006-08-15 14:22:35 +0200354#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
355 /*
356 * Soft-reset SDRAM controller.
357 */
358 mtsdr(sdr_srst, SDR0_SRST_DMC);
359 mtsdr(sdr_srst, 0x00000000);
360#endif
361
Stefan Roesec443fe92005-11-22 13:20:42 +0100362 for (i=0; i<N_MB0CF; i++) {
363 /*
364 * Disable memory controller.
365 */
366 mtsdram(mem_cfg0, 0x00000000);
367
368 /*
369 * Setup some default
370 */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200371 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */
372 mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */
Stefan Roesec443fe92005-11-22 13:20:42 +0100373 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */
374 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */
Wolfgang Denkebd3deb2006-04-16 10:51:58 +0200375 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */
Stefan Roesec443fe92005-11-22 13:20:42 +0100376
377 /*
378 * Following for CAS Latency = 2.5 @ 133 MHz PLB
379 */
380 mtsdram(mem_b0cr, mb0cf[i].reg);
381 mtsdram(mem_tr0, 0x41094012);
382 mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
383 mtsdram(mem_rtr, 0x7e000000); /* Interval 15.20µs @ 133MHz PLB*/
384 mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM*/
385 udelay(400); /* Delay 200 usecs (min) */
386
387 /*
388 * Enable the controller, then wait for DCEN to complete
389 */
Stefan Roesee335ee02006-07-28 18:34:58 +0200390 mtsdram(mem_cfg0, 0x82000000); /* DCEN=1, PMUD=0, 64-bit */
Stefan Roesec443fe92005-11-22 13:20:42 +0100391 udelay(10000);
392
393 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
394 /*
Stefan Roesefd637932006-03-17 10:28:24 +0100395 * Optimize TR1 to current hardware environment
396 */
397 sdram_tr1_set(0x00000000, &tr1_bank1);
398 mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
399
400#ifdef CONFIG_SDRAM_ECC
401 ecc_init(0, mb0cf[i].size);
402#endif
403
404 /*
Stefan Roesec443fe92005-11-22 13:20:42 +0100405 * OK, size detected -> all done
406 */
407 return mb0cf[i].size;
408 }
409 }
410
411 return 0; /* nothing found ! */
412}
413
414#endif /* CONFIG_440 */
415
wdenkc6097192002-11-03 00:24:07 +0000416#endif /* CONFIG_SDRAM_BANK0 */