4e81ce2401133130b79820c0c1eb977c0f9c7615
[oweals/u-boot.git] / cpu / ppc4xx / cpu.c
1 /*
2  * (C) Copyright 2000-2006
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
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 /*
25  * CPU specific code
26  *
27  * written or collected and sometimes rewritten by
28  * Magnus Damm <damm@bitsmart.com>
29  *
30  * minor modifications by
31  * Wolfgang Denk <wd@denx.de>
32  */
33
34 #include <common.h>
35 #include <watchdog.h>
36 #include <command.h>
37 #include <asm/cache.h>
38 #include <ppc4xx.h>
39
40 #if !defined(CONFIG_405)
41 DECLARE_GLOBAL_DATA_PTR;
42 #endif
43
44 #if defined(CONFIG_BOARD_RESET)
45 void board_reset(void);
46 #endif
47
48 #if defined(CONFIG_440)
49 #define FREQ_EBC                (sys_info.freqEPB)
50 #else
51 #define FREQ_EBC                (sys_info.freqPLB / sys_info.pllExtBusDiv)
52 #endif
53
54 #if defined(CONFIG_405GP) || \
55     defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
56     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
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);
64 #endif
65
66 #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
67     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
68         unsigned long val;
69
70         mfsdr(sdr_sdstp1, val);
71         return (val & SDR0_SDSTP1_PAME_MASK);
72 #endif
73 }
74 #endif
75
76 #if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && !defined(CONFIG_405)
77 int pci_arbiter_enabled(void)
78 {
79 #if defined(CONFIG_405GP)
80         return (mfdcr(strap) & PSR_PCI_ARBIT_EN);
81 #endif
82
83 #if defined(CONFIG_405EP)
84         return (mfdcr(cpc0_pci) & CPC0_PCI_ARBIT_EN);
85 #endif
86
87 #if defined(CONFIG_440GP)
88         return (mfdcr(cpc0_strp1) & CPC0_STRP1_PAE_MASK);
89 #endif
90
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)
95         unsigned long val;
96
97         mfsdr(sdr_sdstp1, val);
98         return (val & SDR0_SDSTP1_PAE_MASK);
99 #endif
100 }
101 #endif
102
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)
107
108 #define I2C_BOOTROM
109
110 int i2c_bootrom_enabled(void)
111 {
112 #if defined(CONFIG_405EP)
113         return (mfdcr(cpc0_boot) & CPC0_BOOT_SEP);
114 #else
115         unsigned long val;
116
117         mfsdr(sdr_sdcs, val);
118         return (val & SDR0_SDCS_SDD);
119 #endif
120 }
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 */
183 #endif
184
185
186 #if defined(CONFIG_440)
187 static int do_chip_reset(unsigned long sys0, unsigned long sys1);
188 #endif
189
190
191 int checkcpu (void)
192 {
193 #if !defined(CONFIG_405)        /* not used on Xilinx 405 FPGA implementations */
194         uint pvr = get_pvr();
195         ulong clock = gd->cpu_clk;
196         char buf[32];
197
198 #if !defined(CONFIG_IOP480)
199         sys_info_t sys_info;
200
201         puts ("CPU:   ");
202
203         get_sys_info(&sys_info);
204
205         puts("AMCC PowerPC 4");
206
207 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP)
208         puts("05");
209 #endif
210 #if defined(CONFIG_440)
211         puts("40");
212 #endif
213
214         switch (pvr) {
215         case PVR_405GP_RB:
216                 puts("GP Rev. B");
217                 break;
218
219         case PVR_405GP_RC:
220                 puts("GP Rev. C");
221                 break;
222
223         case PVR_405GP_RD:
224                 puts("GP Rev. D");
225                 break;
226
227 #ifdef CONFIG_405GP
228         case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */
229                 puts("GP Rev. E");
230                 break;
231 #endif
232
233         case PVR_405CR_RA:
234                 puts("CR Rev. A");
235                 break;
236
237         case PVR_405CR_RB:
238                 puts("CR Rev. B");
239                 break;
240
241 #ifdef CONFIG_405CR
242         case PVR_405CR_RC: /* 405GP rev E and 405CR rev C have same PVR */
243                 puts("CR Rev. C");
244                 break;
245 #endif
246
247         case PVR_405GPR_RB:
248                 puts("GPr Rev. B");
249                 break;
250
251         case PVR_405EP_RB:
252                 puts("EP Rev. B");
253                 break;
254
255 #if defined(CONFIG_440)
256         case PVR_440GP_RB:
257                 puts("GP Rev. B");
258                 /* See errata 1.12: CHIP_4 */
259                 if ((mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0)) ||
260                     (mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1)) ){
261                         puts (  "\n\t CPC0_SYSx DCRs corrupted. "
262                                 "Resetting chip ...\n");
263                         udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
264                         do_chip_reset ( mfdcr(cpc0_strp0),
265                                         mfdcr(cpc0_strp1) );
266                 }
267                 break;
268
269         case PVR_440GP_RC:
270                 puts("GP Rev. C");
271                 break;
272
273         case PVR_440GX_RA:
274                 puts("GX Rev. A");
275                 break;
276
277         case PVR_440GX_RB:
278                 puts("GX Rev. B");
279                 break;
280
281         case PVR_440GX_RC:
282                 puts("GX Rev. C");
283                 break;
284
285         case PVR_440GX_RF:
286                 puts("GX Rev. F");
287                 break;
288
289         case PVR_440EP_RA:
290                 puts("EP Rev. A");
291                 break;
292
293 #ifdef CONFIG_440EP
294         case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */
295                 puts("EP Rev. B");
296                 break;
297
298         case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */
299                 puts("EP Rev. C");
300                 break;
301 #endif /*  CONFIG_440EP */
302
303 #ifdef CONFIG_440GR
304         case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */
305                 puts("GR Rev. A");
306                 break;
307
308         case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */
309                 puts("GR Rev. B");
310                 break;
311 #endif /* CONFIG_440GR */
312 #endif /* CONFIG_440 */
313
314         case PVR_440EPX1_RA:
315                 puts("EPx Rev. A - Security/Kasumi support");
316                 break;
317
318         case PVR_440EPX2_RA:
319                 puts("EPx Rev. A - No Security/Kasumi support");
320                 break;
321
322         case PVR_440GRX1_RA:
323                 puts("GRx Rev. A - Security/Kasumi support");
324                 break;
325
326         case PVR_440GRX2_RA:
327                 puts("GRx Rev. A - No Security/Kasumi support");
328                 break;
329
330         case PVR_440SP_RA:
331                 puts("SP Rev. A");
332                 break;
333
334         case PVR_440SP_RB:
335                 puts("SP Rev. B");
336                 break;
337
338         case PVR_440SPe_RA:
339                 puts("SPe Rev. A");
340                 break;
341
342         case PVR_440SPe_RB:
343                 puts("SPe Rev. B");
344                 break;
345
346         default:
347                 printf (" UNKNOWN (PVR=%08x)", pvr);
348                 break;
349         }
350
351         printf (" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock),
352                sys_info.freqPLB / 1000000,
353                sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
354                FREQ_EBC / 1000000);
355
356 #if defined(I2C_BOOTROM)
357         printf ("       I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis");
358 #if defined(SDR0_PINSTP_SHIFT)
359         printf ("       Bootstrap Option %c - ", (char)bootstrap_option() + 'A');
360         printf ("Boot ROM Location %s\n", bootstrap_str[bootstrap_option()]);
361 #endif
362 #endif
363
364 #if defined(CONFIG_PCI)
365         printf ("       Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis");
366 #endif
367
368 #if defined(PCI_ASYNC)
369         if (pci_async_enabled()) {
370                 printf (", PCI async ext clock used");
371         } else {
372                 printf (", PCI sync clock at %lu MHz",
373                        sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
374         }
375 #endif
376
377 #if defined(CONFIG_PCI)
378         putc('\n');
379 #endif
380
381 #if defined(CONFIG_405EP)
382         printf ("       16 kB I-Cache 16 kB D-Cache");
383 #elif defined(CONFIG_440)
384         printf ("       32 kB I-Cache 32 kB D-Cache");
385 #else
386         printf ("       16 kB I-Cache %d kB D-Cache",
387                 ((pvr | 0x00000001) == PVR_405GPR_RB) ? 16 : 8);
388 #endif
389 #endif /* !defined(CONFIG_IOP480) */
390
391 #if defined(CONFIG_IOP480)
392         printf ("PLX IOP480 (PVR=%08x)", pvr);
393         printf (" at %s MHz:", strmhz(buf, clock));
394         printf (" %u kB I-Cache", 4);
395         printf (" %u kB D-Cache", 2);
396 #endif
397
398 #endif /* !defined(CONFIG_405) */
399
400         putc ('\n');
401
402         return 0;
403 }
404
405 #if defined (CONFIG_440SPE)
406 int ppc440spe_revB() {
407         unsigned int pvr;
408
409         pvr = get_pvr();
410         if (pvr == PVR_440SPe_RB)
411                 return 1;
412         else
413                 return 0;
414 }
415 #endif
416
417 /* ------------------------------------------------------------------------- */
418
419 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
420 {
421 #if defined(CONFIG_BOARD_RESET)
422         board_reset();
423 #else
424         /*
425          * Initiate system reset in debug control register DBCR
426          */
427         mtspr(dbcr0, 0x30000000);
428 #endif /* defined(CONFIG_BOARD_RESET) */
429
430         return 1;
431 }
432
433 #if defined(CONFIG_440)
434 static int do_chip_reset (unsigned long sys0, unsigned long sys1)
435 {
436         /* Changes to cpc0_sys0 and cpc0_sys1 require chip
437          * reset.
438          */
439         mtdcr (cntrl0, mfdcr (cntrl0) | 0x80000000);    /* Set SWE */
440         mtdcr (cpc0_sys0, sys0);
441         mtdcr (cpc0_sys1, sys1);
442         mtdcr (cntrl0, mfdcr (cntrl0) & ~0x80000000);   /* Clr SWE */
443         mtspr (dbcr0, 0x20000000);      /* Reset the chip */
444
445         return 1;
446 }
447 #endif
448
449
450 /*
451  * Get timebase clock frequency
452  */
453 unsigned long get_tbclk (void)
454 {
455 #if !defined(CONFIG_IOP480)
456         sys_info_t  sys_info;
457
458         get_sys_info(&sys_info);
459         return (sys_info.freqProcessor);
460 #else
461         return (66000000);
462 #endif
463
464 }
465
466
467 #if defined(CONFIG_WATCHDOG)
468 void
469 watchdog_reset(void)
470 {
471         int re_enable = disable_interrupts();
472         reset_4xx_watchdog();
473         if (re_enable) enable_interrupts();
474 }
475
476 void
477 reset_4xx_watchdog(void)
478 {
479         /*
480          * Clear TSR(WIS) bit
481          */
482         mtspr(tsr, 0x40000000);
483 }
484 #endif  /* CONFIG_WATCHDOG */