]>
Commit | Line | Data |
---|---|---|
858b1a64 WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
858b1a64 WD |
6 | * |
7 | * TODO: clean-up | |
8 | */ | |
9 | ||
10 | /* | |
11 | * How do I program the SDRAM Timing Register (SDRAM0_TR) for a specific SDRAM or DIMM? | |
12 | * | |
13 | * As an example, consider a case where PC133 memory with CAS Latency equal to 2 is being | |
14 | * used with a 200MHz 405GP. For a typical 128Mb, PC133 SDRAM, the relevant minimum | |
15 | * parameters from the datasheet are: | |
16 | * Tclk = 7.5ns (CL = 2) | |
17 | * Trp = 15ns | |
18 | * Trc = 60ns | |
19 | * Trcd = 15ns | |
20 | * Trfc = 66ns | |
21 | * | |
22 | * If we are operating the 405GP with the MemClk output frequency set to 100 MHZ, the clock | |
23 | * period is 10ns and the parameters needed for the Timing Register are: | |
24 | * CASL = CL = 2 clock cycles | |
25 | * PTA = Trp = 15ns / 10ns = 2 clock cycles | |
26 | * CTP = Trc - Trcd - Trp = (60ns - 15ns - 15ns) / 10ns= 3 clock cycles | |
27 | * LDF = 2 clock cycles (but can be extended to meet board-level timing) | |
28 | * RFTA = Trfc = 66ns / 10ns= 7 clock cycles | |
29 | * RCD = Trcd = 15ns / 10ns= 2 clock cycles | |
30 | * | |
31 | * The actual bit settings in the register would be: | |
32 | * | |
33 | * CASL = 0b01 | |
34 | * PTA = 0b01 | |
35 | * CTP = 0b10 | |
36 | * LDF = 0b01 | |
37 | * RFTA = 0b011 | |
38 | * RCD = 0b01 | |
39 | * | |
40 | * If Trfc is not specified in the datasheet for PC100 or PC133 memory, set RFTA = Trc | |
41 | * instead. Figure 24 in the PC SDRAM Specification Rev. 1.7 shows refresh to active delay | |
42 | * defined as Trc rather than Trfc. | |
43 | * When using DIMM modules, most but not all of the required timing parameters can be read | |
44 | * from the Serial Presence Detect (SPD) EEPROM on the module. Specifically, Trc and Trfc | |
45 | * are not available from the EEPROM | |
46 | */ | |
47 | ||
48 | #include <common.h> | |
49 | #include "mip405.h" | |
50 | #include <asm/processor.h> | |
afabb498 | 51 | #include <asm/ppc4xx.h> |
b36df561 | 52 | #include <asm/ppc4xx-i2c.h> |
858b1a64 WD |
53 | #include <miiphy.h> |
54 | #include "../common/common_util.h" | |
28c34504 | 55 | #include <stdio_dev.h> |
858b1a64 | 56 | #include <i2c.h> |
27b207fd | 57 | #include <rtc.h> |
d87080b7 WD |
58 | |
59 | DECLARE_GLOBAL_DATA_PTR; | |
60 | ||
858b1a64 | 61 | #undef SDRAM_DEBUG |
f3e0de60 | 62 | #define ENABLE_ECC /* for ecc boards */ |
858b1a64 WD |
63 | |
64 | /* stdlib.h causes some compatibility problems; should fixe these! -- wd */ | |
65 | #ifndef __ldiv_t_defined | |
66 | typedef struct { | |
67 | long int quot; /* Quotient */ | |
68 | long int rem; /* Remainder */ | |
69 | } ldiv_t; | |
70 | extern ldiv_t ldiv (long int __numer, long int __denom); | |
71 | # define __ldiv_t_defined 1 | |
72 | #endif | |
73 | ||
74 | ||
53677ef1 WD |
75 | #define PLD_PART_REG PER_PLD_ADDR + 0 |
76 | #define PLD_VERS_REG PER_PLD_ADDR + 1 | |
77 | #define PLD_BOARD_CFG_REG PER_PLD_ADDR + 2 | |
78 | #define PLD_IRQ_REG PER_PLD_ADDR + 3 | |
79 | #define PLD_COM_MODE_REG PER_PLD_ADDR + 4 | |
80 | #define PLD_EXT_CONF_REG PER_PLD_ADDR + 5 | |
858b1a64 WD |
81 | |
82 | #define MEGA_BYTE (1024*1024) | |
83 | ||
84 | typedef struct { | |
85 | unsigned char boardtype; /* Board revision and Population Options */ | |
86 | unsigned char cal; /* cas Latency (will be programmend as cal-1) */ | |
87 | unsigned char trp; /* datain27 in clocks */ | |
88 | unsigned char trcd; /* datain29 in clocks */ | |
89 | unsigned char tras; /* datain30 in clocks */ | |
90 | unsigned char tctp; /* tras - trcd in clocks */ | |
91 | unsigned char am; /* Address Mod (will be programmed as am-1) */ | |
92 | unsigned char sz; /* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */ | |
93 | unsigned char ecc; /* if true, ecc is enabled */ | |
94 | } sdram_t; | |
adf32adb | 95 | #if defined(CONFIG_TARGET_MIP405T) |
f3e0de60 | 96 | const sdram_t sdram_table[] = { |
27b207fd | 97 | { 0x0F, /* MIP405T Rev A, 64MByte -1 Board */ |
f3e0de60 WD |
98 | 3, /* Case Latenty = 3 */ |
99 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
100 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ | |
101 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
102 | 4, /* tcpt 44 - 20ns = 24ns */ | |
27b207fd WD |
103 | 2, /* Address Mode = 2 (12x9x4) */ |
104 | 3, /* size value (32MByte) */ | |
f3e0de60 WD |
105 | 0}, /* ECC disabled */ |
106 | { 0xff, /* terminator */ | |
107 | 0xff, | |
108 | 0xff, | |
109 | 0xff, | |
110 | 0xff, | |
111 | 0xff, | |
112 | 0xff, | |
113 | 0xff } | |
114 | }; | |
115 | #else | |
858b1a64 WD |
116 | const sdram_t sdram_table[] = { |
117 | { 0x0f, /* Rev A, 128MByte -1 Board */ | |
118 | 3, /* Case Latenty = 3 */ | |
119 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
33149b88 WD |
120 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ |
121 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
858b1a64 | 122 | 4, /* tcpt 44 - 20ns = 24ns */ |
33149b88 | 123 | 3, /* Address Mode = 3 */ |
858b1a64 WD |
124 | 5, /* size value */ |
125 | 1}, /* ECC enabled */ | |
126 | { 0x07, /* Rev A, 64MByte -2 Board */ | |
127 | 3, /* Case Latenty = 3 */ | |
128 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
33149b88 WD |
129 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ |
130 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
858b1a64 | 131 | 4, /* tcpt 44 - 20ns = 24ns */ |
33149b88 | 132 | 2, /* Address Mode = 2 */ |
858b1a64 WD |
133 | 4, /* size value */ |
134 | 1}, /* ECC enabled */ | |
3e38691e WD |
135 | { 0x03, /* Rev A, 128MByte -4 Board */ |
136 | 3, /* Case Latenty = 3 */ | |
137 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
33149b88 WD |
138 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ |
139 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
3e38691e | 140 | 4, /* tcpt 44 - 20ns = 24ns */ |
33149b88 WD |
141 | 3, /* Address Mode = 3 */ |
142 | 5, /* size value */ | |
143 | 1}, /* ECC enabled */ | |
144 | { 0x1f, /* Rev B, 128MByte -3 Board */ | |
145 | 3, /* Case Latenty = 3 */ | |
146 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
147 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ | |
148 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
149 | 4, /* tcpt 44 - 20ns = 24ns */ | |
150 | 3, /* Address Mode = 3 */ | |
3e38691e WD |
151 | 5, /* size value */ |
152 | 1}, /* ECC enabled */ | |
4a551709 WD |
153 | { 0x2f, /* Rev C, 128MByte -3 Board */ |
154 | 3, /* Case Latenty = 3 */ | |
155 | 3, /* trp 20ns / 7.5 ns datain[27] */ | |
156 | 3, /* trcd 20ns /7.5 ns (datain[29]) */ | |
157 | 6, /* tras 44ns /7.5 ns (datain[30]) */ | |
158 | 4, /* tcpt 44 - 20ns = 24ns */ | |
159 | 3, /* Address Mode = 3 */ | |
160 | 5, /* size value */ | |
161 | 1}, /* ECC enabled */ | |
858b1a64 WD |
162 | { 0xff, /* terminator */ |
163 | 0xff, | |
164 | 0xff, | |
165 | 0xff, | |
166 | 0xff, | |
167 | 0xff, | |
168 | 0xff, | |
169 | 0xff } | |
170 | }; | |
adf32adb | 171 | #endif /*CONFIG_TARGET_MIP405T */ |
858b1a64 WD |
172 | void SDRAM_err (const char *s) |
173 | { | |
174 | #ifndef SDRAM_DEBUG | |
858b1a64 WD |
175 | (void) get_clocks (); |
176 | gd->baudrate = 9600; | |
177 | serial_init (); | |
178 | #endif | |
179 | serial_puts ("\n"); | |
180 | serial_puts (s); | |
181 | serial_puts ("\n enable SDRAM_DEBUG for more info\n"); | |
182 | for (;;); | |
183 | } | |
184 | ||
185 | ||
186 | unsigned char get_board_revcfg (void) | |
187 | { | |
188 | out8 (PER_BOARD_ADDR, 0); | |
189 | return (in8 (PER_BOARD_ADDR)); | |
190 | } | |
191 | ||
192 | ||
193 | #ifdef SDRAM_DEBUG | |
194 | ||
195 | void write_hex (unsigned char i) | |
196 | { | |
197 | char cc; | |
198 | ||
199 | cc = i >> 4; | |
200 | cc &= 0xf; | |
201 | if (cc > 9) | |
202 | serial_putc (cc + 55); | |
203 | else | |
204 | serial_putc (cc + 48); | |
205 | cc = i & 0xf; | |
206 | if (cc > 9) | |
207 | serial_putc (cc + 55); | |
208 | else | |
209 | serial_putc (cc + 48); | |
210 | } | |
211 | ||
212 | void write_4hex (unsigned long val) | |
213 | { | |
214 | write_hex ((unsigned char) (val >> 24)); | |
215 | write_hex ((unsigned char) (val >> 16)); | |
216 | write_hex ((unsigned char) (val >> 8)); | |
217 | write_hex ((unsigned char) val); | |
218 | } | |
219 | ||
220 | #endif | |
221 | ||
222 | ||
223 | int init_sdram (void) | |
224 | { | |
858b1a64 WD |
225 | unsigned long tmp, baseaddr; |
226 | unsigned short i; | |
227 | unsigned char trp_clocks, | |
228 | trcd_clocks, | |
229 | tras_clocks, | |
4233fafe | 230 | trc_clocks; |
858b1a64 WD |
231 | unsigned char cal_val; |
232 | unsigned char bc; | |
f3e0de60 | 233 | unsigned long sdram_tim, sdram_bank; |
858b1a64 | 234 | |
6d0f6bcf | 235 | /*i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);*/ |
858b1a64 WD |
236 | (void) get_clocks (); |
237 | gd->baudrate = 9600; | |
238 | serial_init (); | |
f3e0de60 | 239 | /* set up the pld */ |
d1c3b275 SR |
240 | mtdcr (EBC0_CFGADDR, PB7AP); |
241 | mtdcr (EBC0_CFGDATA, PLD_AP); | |
242 | mtdcr (EBC0_CFGADDR, PB7CR); | |
243 | mtdcr (EBC0_CFGDATA, PLD_CR); | |
f3e0de60 WD |
244 | /* THIS IS OBSOLETE */ |
245 | /* set up the board rev reg*/ | |
d1c3b275 SR |
246 | mtdcr (EBC0_CFGADDR, PB5AP); |
247 | mtdcr (EBC0_CFGDATA, BOARD_AP); | |
248 | mtdcr (EBC0_CFGADDR, PB5CR); | |
249 | mtdcr (EBC0_CFGDATA, BOARD_CR); | |
f3e0de60 WD |
250 | #ifdef SDRAM_DEBUG |
251 | /* get all informations from PLD */ | |
252 | serial_puts ("\nPLD Part 0x"); | |
253 | bc = in8 (PLD_PART_REG); | |
254 | write_hex (bc); | |
255 | serial_puts ("\nPLD Vers 0x"); | |
256 | bc = in8 (PLD_VERS_REG); | |
257 | write_hex (bc); | |
258 | serial_puts ("\nBoard Rev 0x"); | |
259 | bc = in8 (PLD_BOARD_CFG_REG); | |
260 | write_hex (bc); | |
261 | serial_puts ("\n"); | |
262 | #endif | |
263 | /* check board */ | |
264 | bc = in8 (PLD_PART_REG); | |
adf32adb | 265 | #if defined(CONFIG_TARGET_MIP405T) |
f3e0de60 WD |
266 | if((bc & 0x80)==0) |
267 | SDRAM_err ("U-Boot configured for a MIP405T not for a MIP405!!!\n"); | |
268 | #else | |
269 | if((bc & 0x80)==0x80) | |
270 | SDRAM_err ("U-Boot configured for a MIP405 not for a MIP405T!!!\n"); | |
271 | #endif | |
f3e0de60 | 272 | /* set-up the chipselect machine */ |
d1c3b275 SR |
273 | mtdcr (EBC0_CFGADDR, PB0CR); /* get cs0 config reg */ |
274 | tmp = mfdcr (EBC0_CFGDATA); | |
f3e0de60 | 275 | if ((tmp & 0x00002000) == 0) { |
858b1a64 | 276 | /* MPS Boot, set up the flash */ |
d1c3b275 SR |
277 | mtdcr (EBC0_CFGADDR, PB1AP); |
278 | mtdcr (EBC0_CFGDATA, FLASH_AP); | |
279 | mtdcr (EBC0_CFGADDR, PB1CR); | |
280 | mtdcr (EBC0_CFGDATA, FLASH_CR); | |
858b1a64 WD |
281 | } else { |
282 | /* Flash boot, set up the MPS */ | |
d1c3b275 SR |
283 | mtdcr (EBC0_CFGADDR, PB1AP); |
284 | mtdcr (EBC0_CFGDATA, MPS_AP); | |
285 | mtdcr (EBC0_CFGADDR, PB1CR); | |
286 | mtdcr (EBC0_CFGDATA, MPS_CR); | |
858b1a64 WD |
287 | } |
288 | /* set up UART0 (CS2) and UART1 (CS3) */ | |
d1c3b275 SR |
289 | mtdcr (EBC0_CFGADDR, PB2AP); |
290 | mtdcr (EBC0_CFGDATA, UART0_AP); | |
291 | mtdcr (EBC0_CFGADDR, PB2CR); | |
292 | mtdcr (EBC0_CFGDATA, UART0_CR); | |
293 | mtdcr (EBC0_CFGADDR, PB3AP); | |
294 | mtdcr (EBC0_CFGDATA, UART1_AP); | |
295 | mtdcr (EBC0_CFGADDR, PB3CR); | |
296 | mtdcr (EBC0_CFGDATA, UART1_CR); | |
f3e0de60 | 297 | bc = in8 (PLD_BOARD_CFG_REG); |
858b1a64 WD |
298 | #ifdef SDRAM_DEBUG |
299 | serial_puts ("\nstart SDRAM Setup\n"); | |
300 | serial_puts ("\nBoard Rev: "); | |
301 | write_hex (bc); | |
302 | serial_puts ("\n"); | |
303 | #endif | |
304 | i = 0; | |
6d0f6bcf | 305 | baseaddr = CONFIG_SYS_SDRAM_BASE; |
858b1a64 WD |
306 | while (sdram_table[i].sz != 0xff) { |
307 | if (sdram_table[i].boardtype == bc) | |
308 | break; | |
309 | i++; | |
310 | } | |
311 | if (sdram_table[i].boardtype != bc) | |
312 | SDRAM_err ("No SDRAM table found for this board!!!\n"); | |
313 | #ifdef SDRAM_DEBUG | |
314 | serial_puts (" found table "); | |
315 | write_hex (i); | |
316 | serial_puts (" \n"); | |
317 | #endif | |
27b207fd WD |
318 | /* since the ECC initialisation needs some time, |
319 | * we show that we're alive | |
320 | */ | |
321 | if (sdram_table[i].ecc) | |
322 | serial_puts ("\nInitializing SDRAM, Please stand by"); | |
858b1a64 WD |
323 | cal_val = sdram_table[i].cal - 1; /* Cas Latency */ |
324 | trp_clocks = sdram_table[i].trp; /* 20ns / 7.5 ns datain[27] */ | |
325 | trcd_clocks = sdram_table[i].trcd; /* 20ns /7.5 ns (datain[29]) */ | |
326 | tras_clocks = sdram_table[i].tras; /* 44ns /7.5 ns (datain[30]) */ | |
327 | /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ | |
858b1a64 WD |
328 | /* trc_clocks is sum of trp_clocks + tras_clocks */ |
329 | trc_clocks = trp_clocks + tras_clocks; | |
330 | /* get SDRAM timing register */ | |
95b602ba | 331 | mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); |
d1c3b275 | 332 | sdram_tim = mfdcr (SDRAM0_CFGDATA) & ~0x018FC01F; |
858b1a64 WD |
333 | /* insert CASL value */ |
334 | sdram_tim |= ((unsigned long) (cal_val)) << 23; | |
335 | /* insert PTA value */ | |
336 | sdram_tim |= ((unsigned long) (trp_clocks - 1)) << 18; | |
337 | /* insert CTP value */ | |
338 | sdram_tim |= | |
339 | ((unsigned long) (trc_clocks - trp_clocks - | |
340 | trcd_clocks)) << 16; | |
341 | /* insert LDF (always 01) */ | |
342 | sdram_tim |= ((unsigned long) 0x01) << 14; | |
343 | /* insert RFTA value */ | |
344 | sdram_tim |= ((unsigned long) (trc_clocks - 4)) << 2; | |
345 | /* insert RCD value */ | |
346 | sdram_tim |= ((unsigned long) (trcd_clocks - 1)) << 0; | |
347 | ||
348 | tmp = ((unsigned long) (sdram_table[i].am - 1) << 13); /* AM = 3 */ | |
349 | /* insert SZ value; */ | |
350 | tmp |= ((unsigned long) sdram_table[i].sz << 17); | |
351 | /* get SDRAM bank 0 register */ | |
95b602ba | 352 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); |
d1c3b275 | 353 | sdram_bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; |
858b1a64 WD |
354 | sdram_bank |= (baseaddr | tmp | 0x01); |
355 | ||
356 | #ifdef SDRAM_DEBUG | |
357 | serial_puts ("sdtr: "); | |
358 | write_4hex (sdram_tim); | |
359 | serial_puts ("\n"); | |
360 | #endif | |
361 | ||
362 | /* write SDRAM timing register */ | |
95b602ba | 363 | mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); |
d1c3b275 | 364 | mtdcr (SDRAM0_CFGDATA, sdram_tim); |
858b1a64 WD |
365 | |
366 | #ifdef SDRAM_DEBUG | |
367 | serial_puts ("mb0cf: "); | |
368 | write_4hex (sdram_bank); | |
369 | serial_puts ("\n"); | |
370 | #endif | |
371 | ||
372 | /* write SDRAM bank 0 register */ | |
95b602ba | 373 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); |
d1c3b275 | 374 | mtdcr (SDRAM0_CFGDATA, sdram_bank); |
858b1a64 WD |
375 | |
376 | if (get_bus_freq (tmp) > 110000000) { /* > 110MHz */ | |
377 | /* get SDRAM refresh interval register */ | |
95b602ba | 378 | mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); |
d1c3b275 | 379 | tmp = mfdcr (SDRAM0_CFGDATA) & ~0x3FF80000; |
858b1a64 WD |
380 | tmp |= 0x07F00000; |
381 | } else { | |
382 | /* get SDRAM refresh interval register */ | |
95b602ba | 383 | mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); |
d1c3b275 | 384 | tmp = mfdcr (SDRAM0_CFGDATA) & ~0x3FF80000; |
858b1a64 WD |
385 | tmp |= 0x05F00000; |
386 | } | |
387 | /* write SDRAM refresh interval register */ | |
95b602ba | 388 | mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); |
d1c3b275 | 389 | mtdcr (SDRAM0_CFGDATA, tmp); |
858b1a64 | 390 | /* enable ECC if used */ |
f3e0de60 | 391 | #if defined(ENABLE_ECC) && !defined(CONFIG_BOOT_PCI) |
858b1a64 WD |
392 | if (sdram_table[i].ecc) { |
393 | /* disable checking for all banks */ | |
f3e0de60 | 394 | unsigned long *p; |
858b1a64 WD |
395 | #ifdef SDRAM_DEBUG |
396 | serial_puts ("disable ECC.. "); | |
397 | #endif | |
95b602ba | 398 | mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); |
d1c3b275 | 399 | tmp = mfdcr (SDRAM0_CFGDATA); |
858b1a64 | 400 | tmp &= 0xff0fffff; /* disable all banks */ |
95b602ba | 401 | mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); |
858b1a64 WD |
402 | /* set up SDRAM Controller with ECC enabled */ |
403 | #ifdef SDRAM_DEBUG | |
404 | serial_puts ("setup SDRAM Controller.. "); | |
405 | #endif | |
d1c3b275 | 406 | mtdcr (SDRAM0_CFGDATA, tmp); |
95b602ba | 407 | mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); |
d1c3b275 | 408 | tmp = (mfdcr (SDRAM0_CFGDATA) & ~0xFFE00000) | 0x90800000; |
95b602ba | 409 | mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); |
d1c3b275 | 410 | mtdcr (SDRAM0_CFGDATA, tmp); |
858b1a64 WD |
411 | udelay (600); |
412 | #ifdef SDRAM_DEBUG | |
413 | serial_puts ("fill the memory..\n"); | |
414 | #endif | |
415 | serial_puts ("."); | |
416 | /* now, fill all the memory */ | |
417 | tmp = ((4 * MEGA_BYTE) << sdram_table[i].sz); | |
418 | p = (unsigned long) 0; | |
419 | while ((unsigned long) p < tmp) { | |
420 | *p++ = 0L; | |
421 | if (!((unsigned long) p % 0x00800000)) /* every 8MByte */ | |
422 | serial_puts ("."); | |
858b1a64 WD |
423 | } |
424 | /* enable bank 0 */ | |
425 | serial_puts ("."); | |
426 | #ifdef SDRAM_DEBUG | |
427 | serial_puts ("enable ECC\n"); | |
428 | #endif | |
429 | udelay (400); | |
95b602ba | 430 | mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); |
d1c3b275 | 431 | tmp = mfdcr (SDRAM0_CFGDATA); |
858b1a64 | 432 | tmp |= 0x00800000; /* enable bank 0 */ |
d1c3b275 | 433 | mtdcr (SDRAM0_CFGDATA, tmp); |
858b1a64 WD |
434 | udelay (400); |
435 | } else | |
436 | #endif | |
437 | { | |
438 | /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */ | |
95b602ba | 439 | mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); |
d1c3b275 | 440 | tmp = (mfdcr (SDRAM0_CFGDATA) & ~0xFFE00000) | 0x80C00000; |
95b602ba | 441 | mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); |
d1c3b275 | 442 | mtdcr (SDRAM0_CFGDATA, tmp); |
858b1a64 WD |
443 | udelay (400); |
444 | } | |
445 | serial_puts ("\n"); | |
446 | return (0); | |
447 | } | |
448 | ||
c837dcb1 | 449 | int board_early_init_f (void) |
858b1a64 WD |
450 | { |
451 | init_sdram (); | |
452 | ||
453 | /*-------------------------------------------------------------------------+ | |
454 | | Interrupt controller setup for the PIP405 board. | |
455 | | Note: IRQ 0-15 405GP internally generated; active high; level sensitive | |
456 | | IRQ 16 405GP internally generated; active low; level sensitive | |
457 | | IRQ 17-24 RESERVED | |
458 | | IRQ 25 (EXT IRQ 0) SouthBridge; active low; level sensitive | |
459 | | IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive | |
460 | | IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive | |
461 | | IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive | |
462 | | IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive | |
463 | | IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive | |
464 | | IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive | |
465 | | Note for MIP405 board: | |
466 | | An interrupt taken for the SouthBridge (IRQ 25) indicates that | |
467 | | the Interrupt Controller in the South Bridge has caused the | |
468 | | interrupt. The IC must be read to determine which device | |
469 | | caused the interrupt. | |
470 | | | |
471 | +-------------------------------------------------------------------------*/ | |
952e7760 SR |
472 | mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ |
473 | mtdcr (UIC0ER, 0x00000000); /* disable all ints */ | |
474 | mtdcr (UIC0CR, 0x00000000); /* set all to be non-critical (for now) */ | |
475 | mtdcr (UIC0PR, 0xFFFFFF80); /* set int polarities */ | |
476 | mtdcr (UIC0TR, 0x10000000); /* set int trigger levels */ | |
477 | mtdcr (UIC0VCR, 0x00000001); /* set vect base=0,INT0 highest priority */ | |
478 | mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ | |
858b1a64 WD |
479 | return 0; |
480 | } | |
481 | ||
39441b35 DM |
482 | int board_early_init_r(void) |
483 | { | |
484 | int mode; | |
485 | ||
486 | /* | |
487 | * since we are relocated, we can finally enable i-cache | |
488 | * and set up the flash CS correctly | |
489 | */ | |
490 | icache_enable(); | |
491 | setup_cs_reloc(); | |
492 | /* get and display boot mode */ | |
493 | mode = get_boot_mode(); | |
494 | if (mode & BOOT_PCI) | |
495 | printf("PCI Boot %s Map\n", (mode & BOOT_MPS) ? | |
496 | "MPS" : "Flash"); | |
497 | else | |
498 | printf("%s Boot\n", (mode & BOOT_MPS) ? | |
499 | "MPS" : "Flash"); | |
500 | ||
501 | return 0; | |
502 | } | |
858b1a64 WD |
503 | |
504 | /* | |
505 | * Get some PLD Registers | |
506 | */ | |
507 | ||
508 | unsigned short get_pld_parvers (void) | |
509 | { | |
510 | unsigned short result; | |
511 | unsigned char rc; | |
512 | ||
513 | rc = in8 (PLD_PART_REG); | |
514 | result = (unsigned short) rc << 8; | |
515 | rc = in8 (PLD_VERS_REG); | |
516 | result |= rc; | |
517 | return result; | |
518 | } | |
519 | ||
520 | ||
858b1a64 WD |
521 | void user_led0 (unsigned char on) |
522 | { | |
523 | if (on) | |
524 | out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) | 0x4)); | |
525 | else | |
526 | out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) & 0xfb)); | |
527 | } | |
528 | ||
529 | ||
530 | void ide_set_reset (int idereset) | |
531 | { | |
532 | /* if reset = 1 IDE reset will be asserted */ | |
533 | if (idereset) | |
534 | out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) | 0x1)); | |
535 | else { | |
536 | udelay (10000); | |
537 | out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) & 0xfe)); | |
538 | } | |
539 | } | |
540 | ||
541 | ||
542 | /* ------------------------------------------------------------------------- */ | |
543 | ||
f3e0de60 | 544 | void get_pcbrev_var(unsigned char *pcbrev, unsigned char *var) |
858b1a64 | 545 | { |
adf32adb | 546 | #if !defined(CONFIG_TARGET_MIP405T) |
f3e0de60 | 547 | unsigned char bc,rc,tmp; |
858b1a64 | 548 | int i; |
858b1a64 | 549 | |
f3e0de60 WD |
550 | bc = in8 (PLD_BOARD_CFG_REG); |
551 | tmp = ~bc; | |
552 | tmp &= 0xf; | |
858b1a64 WD |
553 | rc = 0; |
554 | for (i = 0; i < 4; i++) { | |
555 | rc <<= 1; | |
f3e0de60 WD |
556 | rc += (tmp & 0x1); |
557 | tmp >>= 1; | |
858b1a64 WD |
558 | } |
559 | rc++; | |
4a551709 WD |
560 | if(( (((bc>>4) & 0xf)==0x2) /* Rev C PCB or */ |
561 | || (((bc>>4) & 0xf)==0x1)) /* Rev B PCB with */ | |
33149b88 WD |
562 | && (rc==0x1)) /* Population Option 1 is a -3 */ |
563 | rc=3; | |
f3e0de60 WD |
564 | *pcbrev=(bc >> 4) & 0xf; |
565 | *var=rc; | |
566 | #else | |
567 | unsigned char bc; | |
568 | bc = in8 (PLD_BOARD_CFG_REG); | |
569 | *pcbrev=(bc >> 4) & 0xf; | |
27b207fd | 570 | *var=16-(bc & 0xf); |
f3e0de60 WD |
571 | #endif |
572 | } | |
573 | ||
574 | /* | |
575 | * Check Board Identity: | |
576 | */ | |
577 | /* serial String: "MIP405_1000" OR "MIP405T_1000" */ | |
adf32adb | 578 | #if !defined(CONFIG_TARGET_MIP405T) |
f3e0de60 WD |
579 | #define BOARD_NAME "MIP405" |
580 | #else | |
581 | #define BOARD_NAME "MIP405T" | |
582 | #endif | |
583 | ||
584 | int checkboard (void) | |
585 | { | |
77ddac94 | 586 | char s[50]; |
f3e0de60 WD |
587 | unsigned char bc, var; |
588 | int i; | |
589 | backup_t *b = (backup_t *) s; | |
590 | ||
591 | puts ("Board: "); | |
592 | get_pcbrev_var(&bc,&var); | |
cdb74977 | 593 | i = getenv_f("serial#", (char *)s, 32); |
77ddac94 | 594 | if ((i == 0) || strncmp ((char *)s, BOARD_NAME,sizeof(BOARD_NAME))) { |
858b1a64 WD |
595 | get_backup_values (b); |
596 | if (strncmp (b->signature, "MPL\0", 4) != 0) { | |
f3e0de60 WD |
597 | puts ("### No HW ID - assuming " BOARD_NAME); |
598 | printf ("-%d Rev %c", var, 'A' + bc); | |
858b1a64 | 599 | } else { |
f3e0de60 WD |
600 | b->serial_name[sizeof(BOARD_NAME)-1] = 0; |
601 | printf ("%s-%d Rev %c SN: %s", b->serial_name, var, | |
602 | 'A' + bc, &b->serial_name[sizeof(BOARD_NAME)]); | |
858b1a64 WD |
603 | } |
604 | } else { | |
f3e0de60 WD |
605 | s[sizeof(BOARD_NAME)-1] = 0; |
606 | printf ("%s-%d Rev %c SN: %s", s, var,'A' + bc, | |
607 | &s[sizeof(BOARD_NAME)]); | |
858b1a64 WD |
608 | } |
609 | bc = in8 (PLD_EXT_CONF_REG); | |
610 | printf (" Boot Config: 0x%x\n", bc); | |
611 | return (0); | |
612 | } | |
613 | ||
614 | ||
615 | /* ------------------------------------------------------------------------- */ | |
616 | /* ------------------------------------------------------------------------- */ | |
617 | /* | |
f1683aa7 | 618 | dram_init() reads EEPROM via I2c. EEPROM contains all of |
858b1a64 WD |
619 | the necessary info for SDRAM controller configuration |
620 | */ | |
621 | /* ------------------------------------------------------------------------- */ | |
622 | /* ------------------------------------------------------------------------- */ | |
623 | static int test_dram (unsigned long ramsize); | |
624 | ||
f1683aa7 | 625 | int dram_init(void) |
858b1a64 WD |
626 | { |
627 | ||
628 | unsigned long bank_reg[4], tmp, bank_size; | |
4233fafe | 629 | int i; |
858b1a64 WD |
630 | unsigned long TotalSize; |
631 | ||
858b1a64 WD |
632 | /* since the DRAM controller is allready set up, calculate the size with the |
633 | bank registers */ | |
95b602ba | 634 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); |
d1c3b275 | 635 | bank_reg[0] = mfdcr (SDRAM0_CFGDATA); |
95b602ba | 636 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B1CR); |
d1c3b275 | 637 | bank_reg[1] = mfdcr (SDRAM0_CFGDATA); |
95b602ba | 638 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B2CR); |
d1c3b275 | 639 | bank_reg[2] = mfdcr (SDRAM0_CFGDATA); |
95b602ba | 640 | mtdcr (SDRAM0_CFGADDR, SDRAM0_B3CR); |
d1c3b275 | 641 | bank_reg[3] = mfdcr (SDRAM0_CFGDATA); |
858b1a64 WD |
642 | TotalSize = 0; |
643 | for (i = 0; i < 4; i++) { | |
644 | if ((bank_reg[i] & 0x1) == 0x1) { | |
645 | tmp = (bank_reg[i] >> 17) & 0x7; | |
646 | bank_size = 4 << tmp; | |
647 | TotalSize += bank_size; | |
4233fafe | 648 | } |
858b1a64 | 649 | } |
95b602ba | 650 | mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); |
d1c3b275 | 651 | tmp = mfdcr (SDRAM0_CFGDATA); |
858b1a64 WD |
652 | |
653 | if (!tmp) | |
654 | printf ("No "); | |
655 | printf ("ECC "); | |
656 | ||
657 | test_dram (TotalSize * MEGA_BYTE); | |
088454cd SG |
658 | gd->ram_size = TotalSize * MEGA_BYTE; |
659 | ||
660 | return 0; | |
858b1a64 WD |
661 | } |
662 | ||
663 | /* ------------------------------------------------------------------------- */ | |
664 | ||
858b1a64 WD |
665 | |
666 | static int test_dram (unsigned long ramsize) | |
667 | { | |
668 | #ifdef SDRAM_DEBUG | |
669 | mem_test (0L, ramsize, 1); | |
670 | #endif | |
671 | /* not yet implemented */ | |
672 | return (1); | |
673 | } | |
674 | ||
27b207fd WD |
675 | /* used to check if the time in RTC is valid */ |
676 | static unsigned long start; | |
677 | static struct rtc_time tm; | |
678 | ||
858b1a64 WD |
679 | int misc_init_r (void) |
680 | { | |
7205e407 WD |
681 | /* adjust flash start and size as well as the offset */ |
682 | gd->bd->bi_flashstart=0-flash_info[0].size; | |
6d0f6bcf | 683 | gd->bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN; |
7205e407 WD |
684 | gd->bd->bi_flashoffset=0; |
685 | ||
27b207fd WD |
686 | /* check, if RTC is running */ |
687 | rtc_get (&tm); | |
688 | start=get_timer(0); | |
f3e0de60 | 689 | /* if MIP405 has booted from PCI, reset CCR0[24] as described in errata PCI_18 */ |
d1c3b275 | 690 | if (mfdcr(CPC0_PSR) & PSR_ROM_LOC) |
58ea142f | 691 | mtspr(SPRN_CCR0, (mfspr(SPRN_CCR0) & ~0x80)); |
f3e0de60 | 692 | |
858b1a64 WD |
693 | return (0); |
694 | } | |
695 | ||
696 | ||
697 | void print_mip405_rev (void) | |
698 | { | |
f3e0de60 WD |
699 | unsigned char part, vers, pcbrev, var; |
700 | ||
701 | get_pcbrev_var(&pcbrev,&var); | |
858b1a64 WD |
702 | part = in8 (PLD_PART_REG); |
703 | vers = in8 (PLD_VERS_REG); | |
f3e0de60 WD |
704 | printf ("Rev: " BOARD_NAME "-%d Rev %c PLD %d Vers %d\n", |
705 | var, pcbrev + 'A', part & 0x7F, vers); | |
858b1a64 WD |
706 | } |
707 | ||
63e73c9a | 708 | |
27b207fd | 709 | extern int mk_date (char *, struct rtc_time *); |
858b1a64 WD |
710 | |
711 | int last_stage_init (void) | |
712 | { | |
27b207fd WD |
713 | unsigned long stop; |
714 | struct rtc_time newtm; | |
77ddac94 | 715 | char *s; |
331ab60c | 716 | |
3e38691e | 717 | /* write correct LED configuration */ |
63ff004c | 718 | if (miiphy_write("ppc_4xx_eth0", 0x1, 0x14, 0x2402) != 0) { |
858b1a64 WD |
719 | printf ("Error writing to the PHY\n"); |
720 | } | |
3e38691e WD |
721 | /* since LED/CFG2 is not connected on the -2, |
722 | * write to correct capability information */ | |
63ff004c | 723 | if (miiphy_write("ppc_4xx_eth0", 0x1, 0x4, 0x01E1) != 0) { |
3e38691e WD |
724 | printf ("Error writing to the PHY\n"); |
725 | } | |
858b1a64 | 726 | print_mip405_rev (); |
28c34504 | 727 | stdio_print_current_devices (); |
858b1a64 | 728 | check_env (); |
27b207fd WD |
729 | /* check if RTC time is valid */ |
730 | stop=get_timer(start); | |
731 | while(stop<1200) { /* we wait 1.2 sec to check if the RTC is running */ | |
732 | udelay(1000); | |
733 | stop=get_timer(start); | |
734 | } | |
735 | rtc_get (&newtm); | |
736 | if(tm.tm_sec==newtm.tm_sec) { | |
737 | s=getenv("defaultdate"); | |
738 | if(!s) | |
739 | mk_date ("010112001970", &newtm); | |
740 | else | |
741 | if(mk_date (s, &newtm)!=0) { | |
742 | printf("RTC: Bad date format in defaultdate\n"); | |
743 | return 0; | |
744 | } | |
745 | rtc_reset (); | |
746 | rtc_set(&newtm); | |
747 | } | |
858b1a64 WD |
748 | return 0; |
749 | } | |
750 | ||
751 | /*************************************************************************** | |
752 | * some helping routines | |
753 | */ | |
754 | ||
755 | int overwrite_console (void) | |
756 | { | |
472d5460 YS |
757 | /* return true if console should be overwritten */ |
758 | return ((in8(PLD_EXT_CONF_REG) & 0x1) == 0); | |
858b1a64 WD |
759 | } |
760 | ||
761 | ||
762 | /************************************************************************ | |
763 | * Print MIP405 Info | |
764 | ************************************************************************/ | |
765 | void print_mip405_info (void) | |
766 | { | |
767 | unsigned char part, vers, cfg, irq_reg, com_mode, ext; | |
768 | ||
769 | part = in8 (PLD_PART_REG); | |
770 | vers = in8 (PLD_VERS_REG); | |
771 | cfg = in8 (PLD_BOARD_CFG_REG); | |
772 | irq_reg = in8 (PLD_IRQ_REG); | |
773 | com_mode = in8 (PLD_COM_MODE_REG); | |
774 | ext = in8 (PLD_EXT_CONF_REG); | |
775 | ||
f3e0de60 | 776 | printf ("PLD Part %d version %d\n", part & 0x7F, vers); |
858b1a64 WD |
777 | printf ("Board Revision %c\n", ((cfg >> 4) & 0xf) + 'A'); |
778 | printf ("Population Options %d %d %d %d\n", (cfg) & 0x1, | |
779 | (cfg >> 1) & 0x1, (cfg >> 2) & 0x1, (cfg >> 3) & 0x1); | |
780 | printf ("User LED %s\n", (com_mode & 0x4) ? "on" : "off"); | |
781 | printf ("UART Clocks %d\n", (com_mode >> 4) & 0x3); | |
adf32adb | 782 | #if !defined(CONFIG_TARGET_MIP405T) |
858b1a64 WD |
783 | printf ("User Config Switch %d %d %d %d %d %d %d %d\n", |
784 | (ext) & 0x1, (ext >> 1) & 0x1, (ext >> 2) & 0x1, | |
785 | (ext >> 3) & 0x1, (ext >> 4) & 0x1, (ext >> 5) & 0x1, | |
786 | (ext >> 6) & 0x1, (ext >> 7) & 0x1); | |
787 | printf ("SER1 uses handshakes %s\n", | |
788 | (ext & 0x80) ? "DTR/DSR" : "RTS/CTS"); | |
f3e0de60 | 789 | #else |
27b207fd | 790 | printf ("User Config Switch %d %d %d %d %d %d %d %d\n", |
f3e0de60 WD |
791 | (ext) & 0x1, (ext >> 1) & 0x1, (ext >> 2) & 0x1, |
792 | (ext >> 3) & 0x1, (ext >> 4) & 0x1, (ext >> 5) & 0x1, | |
27b207fd | 793 | (ext >> 6) & 0x1,(ext >> 7) & 0x1); |
f3e0de60 | 794 | #endif |
858b1a64 WD |
795 | printf ("IDE Reset %s\n", (ext & 0x01) ? "asserted" : "not asserted"); |
796 | printf ("IRQs:\n"); | |
797 | printf (" PIIX INTR: %s\n", (irq_reg & 0x80) ? "inactive" : "active"); | |
adf32adb | 798 | #if !defined(CONFIG_TARGET_MIP405T) |
858b1a64 WD |
799 | printf (" UART0 IRQ: %s\n", (irq_reg & 0x40) ? "inactive" : "active"); |
800 | printf (" UART1 IRQ: %s\n", (irq_reg & 0x20) ? "inactive" : "active"); | |
f3e0de60 | 801 | #endif |
858b1a64 WD |
802 | printf (" PIIX SMI: %s\n", (irq_reg & 0x10) ? "inactive" : "active"); |
803 | printf (" PIIX INIT: %s\n", (irq_reg & 0x8) ? "inactive" : "active"); | |
804 | printf (" PIIX NMI: %s\n", (irq_reg & 0x4) ? "inactive" : "active"); | |
805 | } |