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