]>
Commit | Line | Data |
---|---|---|
c609719b | 1 | /* |
512f8d5d | 2 | * (C) Copyright 2000-2006 |
c609719b WD |
3 | * Wolfgang Denk, DENX Software Engineering, [email protected]. |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | /* | |
c609719b WD |
25 | * CPU specific code |
26 | * | |
27 | * written or collected and sometimes rewritten by | |
28 | * Magnus Damm <[email protected]> | |
29 | * | |
30 | * minor modifications by | |
31 | * Wolfgang Denk <[email protected]> | |
32 | */ | |
33 | ||
34 | #include <common.h> | |
35 | #include <watchdog.h> | |
36 | #include <command.h> | |
37 | #include <asm/cache.h> | |
38 | #include <ppc4xx.h> | |
39 | ||
d87080b7 WD |
40 | #if !defined(CONFIG_405) |
41 | DECLARE_GLOBAL_DATA_PTR; | |
42 | #endif | |
43 | ||
f3443867 SR |
44 | #if defined(CONFIG_BOARD_RESET) |
45 | void board_reset(void); | |
46 | #endif | |
47 | ||
6e7fb6ea SR |
48 | #if defined(CONFIG_440) |
49 | #define FREQ_EBC (sys_info.freqEPB) | |
50 | #else | |
51 | #define FREQ_EBC (sys_info.freqPLB / sys_info.pllExtBusDiv) | |
3d9569b2 SR |
52 | #endif |
53 | ||
887e2ec9 SR |
54 | #if defined(CONFIG_405GP) || \ |
55 | defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ | |
56 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
6e7fb6ea SR |
57 | |
58 | #define PCI_ASYNC | |
59 | ||
60 | int pci_async_enabled(void) | |
61 | { | |
62 | #if defined(CONFIG_405GP) | |
63 | return (mfdcr(strap) & PSR_PCI_ASYNC_EN); | |
3d9569b2 SR |
64 | #endif |
65 | ||
887e2ec9 SR |
66 | #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ |
67 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
6e7fb6ea SR |
68 | unsigned long val; |
69 | ||
7481266e | 70 | mfsdr(sdr_sdstp1, val); |
6e7fb6ea SR |
71 | return (val & SDR0_SDSTP1_PAME_MASK); |
72 | #endif | |
73 | } | |
74 | #endif | |
75 | ||
a46726fd | 76 | #if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && !defined(CONFIG_405) |
6e7fb6ea SR |
77 | int pci_arbiter_enabled(void) |
78 | { | |
79 | #if defined(CONFIG_405GP) | |
80 | return (mfdcr(strap) & PSR_PCI_ARBIT_EN); | |
81 | #endif | |
3d9569b2 | 82 | |
6e7fb6ea SR |
83 | #if defined(CONFIG_405EP) |
84 | return (mfdcr(cpc0_pci) & CPC0_PCI_ARBIT_EN); | |
3d9569b2 SR |
85 | #endif |
86 | ||
87 | #if defined(CONFIG_440GP) | |
6e7fb6ea SR |
88 | return (mfdcr(cpc0_strp1) & CPC0_STRP1_PAE_MASK); |
89 | #endif | |
90 | ||
887e2ec9 SR |
91 | #if defined(CONFIG_440GX) || \ |
92 | defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ | |
93 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ | |
94 | defined(CONFIG_440SP) || defined(CONFIG_440SPE) | |
6e7fb6ea | 95 | unsigned long val; |
3d9569b2 | 96 | |
6e7fb6ea SR |
97 | mfsdr(sdr_sdstp1, val); |
98 | return (val & SDR0_SDSTP1_PAE_MASK); | |
3d9569b2 | 99 | #endif |
6e7fb6ea SR |
100 | } |
101 | #endif | |
102 | ||
887e2ec9 SR |
103 | #if defined(CONFIG_405EP) || defined(CONFIG_440GX) || \ |
104 | defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ | |
105 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ | |
106 | defined(CONFIG_440SP) || defined(CONFIG_440SPE) | |
3d9569b2 | 107 | |
6e7fb6ea | 108 | #define I2C_BOOTROM |
3d9569b2 | 109 | |
6e7fb6ea SR |
110 | int i2c_bootrom_enabled(void) |
111 | { | |
112 | #if defined(CONFIG_405EP) | |
113 | return (mfdcr(cpc0_boot) & CPC0_BOOT_SEP); | |
887e2ec9 | 114 | #else |
6e7fb6ea SR |
115 | unsigned long val; |
116 | ||
117 | mfsdr(sdr_sdcs, val); | |
118 | return (val & SDR0_SDCS_SDD); | |
119 | #endif | |
120 | } | |
887e2ec9 SR |
121 | |
122 | #if defined(CONFIG_440GX) | |
123 | #define SDR0_PINSTP_SHIFT 29 | |
124 | static char *bootstrap_str[] = { | |
125 | "EBC (16 bits)", | |
126 | "EBC (8 bits)", | |
127 | "EBC (32 bits)", | |
128 | "EBC (8 bits)", | |
129 | "PCI", | |
130 | "I2C (Addr 0x54)", | |
131 | "Reserved", | |
132 | "I2C (Addr 0x50)", | |
133 | }; | |
134 | #endif | |
135 | ||
136 | #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) | |
137 | #define SDR0_PINSTP_SHIFT 30 | |
138 | static char *bootstrap_str[] = { | |
139 | "EBC (8 bits)", | |
140 | "PCI", | |
141 | "I2C (Addr 0x54)", | |
142 | "I2C (Addr 0x50)", | |
143 | }; | |
144 | #endif | |
145 | ||
146 | #if defined(CONFIG_440EP) || defined(CONFIG_440GR) | |
147 | #define SDR0_PINSTP_SHIFT 29 | |
148 | static char *bootstrap_str[] = { | |
149 | "EBC (8 bits)", | |
150 | "PCI", | |
151 | "NAND (8 bits)", | |
152 | "EBC (16 bits)", | |
153 | "EBC (16 bits)", | |
154 | "I2C (Addr 0x54)", | |
155 | "PCI", | |
156 | "I2C (Addr 0x52)", | |
157 | }; | |
158 | #endif | |
159 | ||
160 | #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
161 | #define SDR0_PINSTP_SHIFT 29 | |
162 | static char *bootstrap_str[] = { | |
163 | "EBC (8 bits)", | |
164 | "EBC (16 bits)", | |
165 | "EBC (16 bits)", | |
166 | "NAND (8 bits)", | |
167 | "PCI", | |
168 | "I2C (Addr 0x54)", | |
169 | "PCI", | |
170 | "I2C (Addr 0x52)", | |
171 | }; | |
172 | #endif | |
173 | ||
174 | #if defined(SDR0_PINSTP_SHIFT) | |
175 | static int bootstrap_option(void) | |
176 | { | |
177 | unsigned long val; | |
178 | ||
179 | mfsdr(sdr_pinstp, val); | |
180 | return ((val & 0xe0000000) >> SDR0_PINSTP_SHIFT); | |
181 | } | |
182 | #endif /* SDR0_PINSTP_SHIFT */ | |
3d9569b2 SR |
183 | #endif |
184 | ||
185 | ||
c609719b | 186 | #if defined(CONFIG_440) |
3d9569b2 | 187 | static int do_chip_reset(unsigned long sys0, unsigned long sys1); |
c609719b WD |
188 | #endif |
189 | ||
c609719b WD |
190 | |
191 | int checkcpu (void) | |
192 | { | |
3d9569b2 | 193 | #if !defined(CONFIG_405) /* not used on Xilinx 405 FPGA implementations */ |
3d9569b2 | 194 | uint pvr = get_pvr(); |
c609719b WD |
195 | ulong clock = gd->cpu_clk; |
196 | char buf[32]; | |
c609719b | 197 | |
3d9569b2 | 198 | #if !defined(CONFIG_IOP480) |
ba999c53 | 199 | char addstr[64] = ""; |
3d9569b2 | 200 | sys_info_t sys_info; |
c609719b WD |
201 | |
202 | puts ("CPU: "); | |
203 | ||
204 | get_sys_info(&sys_info); | |
205 | ||
3d9569b2 SR |
206 | puts("AMCC PowerPC 4"); |
207 | ||
208 | #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) | |
209 | puts("05"); | |
b867d705 | 210 | #endif |
3d9569b2 SR |
211 | #if defined(CONFIG_440) |
212 | puts("40"); | |
c609719b | 213 | #endif |
3d9569b2 | 214 | |
c609719b WD |
215 | switch (pvr) { |
216 | case PVR_405GP_RB: | |
3d9569b2 | 217 | puts("GP Rev. B"); |
c609719b | 218 | break; |
3d9569b2 | 219 | |
c609719b | 220 | case PVR_405GP_RC: |
3d9569b2 | 221 | puts("GP Rev. C"); |
c609719b | 222 | break; |
3d9569b2 | 223 | |
c609719b | 224 | case PVR_405GP_RD: |
3d9569b2 | 225 | puts("GP Rev. D"); |
c609719b | 226 | break; |
3d9569b2 | 227 | |
42dfe7a1 | 228 | #ifdef CONFIG_405GP |
3d9569b2 SR |
229 | case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */ |
230 | puts("GP Rev. E"); | |
c609719b WD |
231 | break; |
232 | #endif | |
3d9569b2 | 233 | |
c609719b | 234 | case PVR_405CR_RA: |
3d9569b2 | 235 | puts("CR Rev. A"); |
c609719b | 236 | break; |
3d9569b2 | 237 | |
c609719b | 238 | case PVR_405CR_RB: |
3d9569b2 | 239 | puts("CR Rev. B"); |
c609719b | 240 | break; |
c609719b | 241 | |
3d9569b2 SR |
242 | #ifdef CONFIG_405CR |
243 | case PVR_405CR_RC: /* 405GP rev E and 405CR rev C have same PVR */ | |
244 | puts("CR Rev. C"); | |
245 | break; | |
c609719b WD |
246 | #endif |
247 | ||
3d9569b2 SR |
248 | case PVR_405GPR_RB: |
249 | puts("GPr Rev. B"); | |
250 | break; | |
c609719b | 251 | |
3d9569b2 SR |
252 | case PVR_405EP_RB: |
253 | puts("EP Rev. B"); | |
254 | break; | |
c609719b WD |
255 | |
256 | #if defined(CONFIG_440) | |
8bde7f77 | 257 | case PVR_440GP_RB: |
c157d8e2 | 258 | puts("GP Rev. B"); |
4d816774 WD |
259 | /* See errata 1.12: CHIP_4 */ |
260 | if ((mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0)) || | |
261 | (mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1)) ){ | |
262 | puts ( "\n\t CPC0_SYSx DCRs corrupted. " | |
263 | "Resetting chip ...\n"); | |
264 | udelay( 1000 * 1000 ); /* Give time for serial buf to clear */ | |
265 | do_chip_reset ( mfdcr(cpc0_strp0), | |
266 | mfdcr(cpc0_strp1) ); | |
267 | } | |
c609719b | 268 | break; |
3d9569b2 | 269 | |
8bde7f77 | 270 | case PVR_440GP_RC: |
c157d8e2 | 271 | puts("GP Rev. C"); |
ba56f625 | 272 | break; |
3d9569b2 | 273 | |
ba56f625 | 274 | case PVR_440GX_RA: |
c157d8e2 | 275 | puts("GX Rev. A"); |
ba56f625 | 276 | break; |
3d9569b2 | 277 | |
ba56f625 | 278 | case PVR_440GX_RB: |
c157d8e2 | 279 | puts("GX Rev. B"); |
c609719b | 280 | break; |
3d9569b2 | 281 | |
0a7c5391 | 282 | case PVR_440GX_RC: |
c157d8e2 | 283 | puts("GX Rev. C"); |
0a7c5391 | 284 | break; |
3d9569b2 | 285 | |
57275b69 SR |
286 | case PVR_440GX_RF: |
287 | puts("GX Rev. F"); | |
288 | break; | |
3d9569b2 | 289 | |
c157d8e2 SR |
290 | case PVR_440EP_RA: |
291 | puts("EP Rev. A"); | |
292 | break; | |
3d9569b2 | 293 | |
9a8d82fd SR |
294 | #ifdef CONFIG_440EP |
295 | case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */ | |
c157d8e2 SR |
296 | puts("EP Rev. B"); |
297 | break; | |
512f8d5d SR |
298 | |
299 | case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */ | |
300 | puts("EP Rev. C"); | |
301 | break; | |
9a8d82fd | 302 | #endif /* CONFIG_440EP */ |
3d9569b2 | 303 | |
9a8d82fd SR |
304 | #ifdef CONFIG_440GR |
305 | case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */ | |
306 | puts("GR Rev. A"); | |
307 | break; | |
512f8d5d | 308 | |
5770a1e4 | 309 | case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */ |
512f8d5d SR |
310 | puts("GR Rev. B"); |
311 | break; | |
9a8d82fd | 312 | #endif /* CONFIG_440GR */ |
3d9569b2 SR |
313 | #endif /* CONFIG_440 */ |
314 | ||
887e2ec9 | 315 | case PVR_440EPX1_RA: |
edf0b543 SR |
316 | puts("EPx Rev. A"); |
317 | strcpy(addstr, "Security/Kasumi support"); | |
887e2ec9 SR |
318 | break; |
319 | ||
320 | case PVR_440EPX2_RA: | |
edf0b543 SR |
321 | puts("EPx Rev. A"); |
322 | strcpy(addstr, "No Security/Kasumi support"); | |
887e2ec9 SR |
323 | break; |
324 | ||
325 | case PVR_440GRX1_RA: | |
edf0b543 SR |
326 | puts("GRx Rev. A"); |
327 | strcpy(addstr, "Security/Kasumi support"); | |
887e2ec9 SR |
328 | break; |
329 | ||
330 | case PVR_440GRX2_RA: | |
edf0b543 SR |
331 | puts("GRx Rev. A"); |
332 | strcpy(addstr, "No Security/Kasumi support"); | |
887e2ec9 SR |
333 | break; |
334 | ||
6e7fb6ea SR |
335 | case PVR_440SP_RA: |
336 | puts("SP Rev. A"); | |
337 | break; | |
338 | ||
339 | case PVR_440SP_RB: | |
340 | puts("SP Rev. B"); | |
341 | break; | |
342 | ||
6c5879f3 | 343 | case PVR_440SPe_RA: |
fe84b48a | 344 | puts("SPe Rev. A"); |
6c5879f3 | 345 | break; |
fe84b48a | 346 | |
6c5879f3 | 347 | case PVR_440SPe_RB: |
fe84b48a | 348 | puts("SPe Rev. B"); |
6c5879f3 | 349 | break; |
fe84b48a | 350 | |
8bde7f77 | 351 | default: |
17f50f22 | 352 | printf (" UNKNOWN (PVR=%08x)", pvr); |
c609719b WD |
353 | break; |
354 | } | |
3d9569b2 SR |
355 | |
356 | printf (" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock), | |
357 | sys_info.freqPLB / 1000000, | |
358 | sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, | |
359 | FREQ_EBC / 1000000); | |
360 | ||
edf0b543 SR |
361 | if (addstr[0] != 0) |
362 | printf(" %s\n", addstr); | |
363 | ||
6e7fb6ea SR |
364 | #if defined(I2C_BOOTROM) |
365 | printf (" I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis"); | |
887e2ec9 SR |
366 | #if defined(SDR0_PINSTP_SHIFT) |
367 | printf (" Bootstrap Option %c - ", (char)bootstrap_option() + 'A'); | |
368 | printf ("Boot ROM Location %s\n", bootstrap_str[bootstrap_option()]); | |
ba999c53 WD |
369 | #endif /* SDR0_PINSTP_SHIFT */ |
370 | #endif /* I2C_BOOTROM */ | |
3d9569b2 | 371 | |
6e7fb6ea SR |
372 | #if defined(CONFIG_PCI) |
373 | printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis"); | |
3d9569b2 SR |
374 | #endif |
375 | ||
6e7fb6ea SR |
376 | #if defined(PCI_ASYNC) |
377 | if (pci_async_enabled()) { | |
3d9569b2 SR |
378 | printf (", PCI async ext clock used"); |
379 | } else { | |
380 | printf (", PCI sync clock at %lu MHz", | |
381 | sys_info.freqPLB / sys_info.pllPciDiv / 1000000); | |
382 | } | |
c609719b | 383 | #endif |
3d9569b2 | 384 | |
6e7fb6ea | 385 | #if defined(CONFIG_PCI) |
3d9569b2 SR |
386 | putc('\n'); |
387 | #endif | |
388 | ||
389 | #if defined(CONFIG_405EP) | |
390 | printf (" 16 kB I-Cache 16 kB D-Cache"); | |
391 | #elif defined(CONFIG_440) | |
392 | printf (" 32 kB I-Cache 32 kB D-Cache"); | |
393 | #else | |
394 | printf (" 16 kB I-Cache %d kB D-Cache", | |
395 | ((pvr | 0x00000001) == PVR_405GPR_RB) ? 16 : 8); | |
396 | #endif | |
397 | #endif /* !defined(CONFIG_IOP480) */ | |
398 | ||
399 | #if defined(CONFIG_IOP480) | |
400 | printf ("PLX IOP480 (PVR=%08x)", pvr); | |
401 | printf (" at %s MHz:", strmhz(buf, clock)); | |
402 | printf (" %u kB I-Cache", 4); | |
403 | printf (" %u kB D-Cache", 2); | |
404 | #endif | |
405 | ||
406 | #endif /* !defined(CONFIG_405) */ | |
407 | ||
408 | putc ('\n'); | |
c609719b WD |
409 | |
410 | return 0; | |
411 | } | |
412 | ||
692519b1 RJ |
413 | #if defined (CONFIG_440SPE) |
414 | int ppc440spe_revB() { | |
415 | unsigned int pvr; | |
416 | ||
417 | pvr = get_pvr(); | |
418 | if (pvr == PVR_440SPe_RB) | |
419 | return 1; | |
420 | else | |
421 | return 0; | |
422 | } | |
423 | #endif | |
c609719b WD |
424 | |
425 | /* ------------------------------------------------------------------------- */ | |
426 | ||
8bde7f77 | 427 | int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
c609719b | 428 | { |
1f94d162 SR |
429 | #if defined(CONFIG_BOARD_RESET) |
430 | board_reset(); | |
431 | #else /* defined(CONFIG_BOARD_RESET) */ | |
1c2ce226 SR |
432 | #if defined(CFG_4xx_RESET_TYPE) |
433 | mtspr(dbcr0, CFG_4xx_RESET_TYPE << 28); | |
c157d8e2 | 434 | #else |
8bde7f77 WD |
435 | /* |
436 | * Initiate system reset in debug control register DBCR | |
437 | */ | |
f3443867 SR |
438 | mtspr(dbcr0, 0x30000000); |
439 | #endif /* defined(CONFIG_BOARD_RESET) */ | |
c157d8e2 | 440 | |
c609719b WD |
441 | return 1; |
442 | } | |
443 | ||
444 | #if defined(CONFIG_440) | |
3d9569b2 | 445 | static int do_chip_reset (unsigned long sys0, unsigned long sys1) |
c609719b | 446 | { |
4d816774 WD |
447 | /* Changes to cpc0_sys0 and cpc0_sys1 require chip |
448 | * reset. | |
449 | */ | |
450 | mtdcr (cntrl0, mfdcr (cntrl0) | 0x80000000); /* Set SWE */ | |
451 | mtdcr (cpc0_sys0, sys0); | |
452 | mtdcr (cpc0_sys1, sys1); | |
453 | mtdcr (cntrl0, mfdcr (cntrl0) & ~0x80000000); /* Clr SWE */ | |
454 | mtspr (dbcr0, 0x20000000); /* Reset the chip */ | |
455 | ||
456 | return 1; | |
c609719b WD |
457 | } |
458 | #endif | |
459 | ||
460 | ||
461 | /* | |
462 | * Get timebase clock frequency | |
463 | */ | |
464 | unsigned long get_tbclk (void) | |
465 | { | |
3d9569b2 | 466 | #if !defined(CONFIG_IOP480) |
c609719b WD |
467 | sys_info_t sys_info; |
468 | ||
469 | get_sys_info(&sys_info); | |
470 | return (sys_info.freqProcessor); | |
c609719b | 471 | #else |
3d9569b2 | 472 | return (66000000); |
c609719b WD |
473 | #endif |
474 | ||
475 | } | |
476 | ||
477 | ||
478 | #if defined(CONFIG_WATCHDOG) | |
479 | void | |
480 | watchdog_reset(void) | |
481 | { | |
482 | int re_enable = disable_interrupts(); | |
483 | reset_4xx_watchdog(); | |
484 | if (re_enable) enable_interrupts(); | |
485 | } | |
486 | ||
487 | void | |
488 | reset_4xx_watchdog(void) | |
489 | { | |
490 | /* | |
491 | * Clear TSR(WIS) bit | |
492 | */ | |
493 | mtspr(tsr, 0x40000000); | |
494 | } | |
495 | #endif /* CONFIG_WATCHDOG */ |