]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/cpu.c
[PATCH] Update Prodrive ALPR board support (440GX)
[karo-tx-uboot.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         char addstr[64] = "";
200         sys_info_t sys_info;
201
202         puts ("CPU:   ");
203
204         get_sys_info(&sys_info);
205
206         puts("AMCC PowerPC 4");
207
208 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP)
209         puts("05");
210 #endif
211 #if defined(CONFIG_440)
212         puts("40");
213 #endif
214
215         switch (pvr) {
216         case PVR_405GP_RB:
217                 puts("GP Rev. B");
218                 break;
219
220         case PVR_405GP_RC:
221                 puts("GP Rev. C");
222                 break;
223
224         case PVR_405GP_RD:
225                 puts("GP Rev. D");
226                 break;
227
228 #ifdef CONFIG_405GP
229         case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */
230                 puts("GP Rev. E");
231                 break;
232 #endif
233
234         case PVR_405CR_RA:
235                 puts("CR Rev. A");
236                 break;
237
238         case PVR_405CR_RB:
239                 puts("CR Rev. B");
240                 break;
241
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;
246 #endif
247
248         case PVR_405GPR_RB:
249                 puts("GPr Rev. B");
250                 break;
251
252         case PVR_405EP_RB:
253                 puts("EP Rev. B");
254                 break;
255
256 #if defined(CONFIG_440)
257         case PVR_440GP_RB:
258                 puts("GP Rev. B");
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                 }
268                 break;
269
270         case PVR_440GP_RC:
271                 puts("GP Rev. C");
272                 break;
273
274         case PVR_440GX_RA:
275                 puts("GX Rev. A");
276                 break;
277
278         case PVR_440GX_RB:
279                 puts("GX Rev. B");
280                 break;
281
282         case PVR_440GX_RC:
283                 puts("GX Rev. C");
284                 break;
285
286         case PVR_440GX_RF:
287                 puts("GX Rev. F");
288                 break;
289
290         case PVR_440EP_RA:
291                 puts("EP Rev. A");
292                 break;
293
294 #ifdef CONFIG_440EP
295         case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */
296                 puts("EP Rev. B");
297                 break;
298
299         case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */
300                 puts("EP Rev. C");
301                 break;
302 #endif /*  CONFIG_440EP */
303
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;
308
309         case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */
310                 puts("GR Rev. B");
311                 break;
312 #endif /* CONFIG_440GR */
313 #endif /* CONFIG_440 */
314
315         case PVR_440EPX1_RA:
316                 puts("EPx Rev. A");
317                 strcpy(addstr, "Security/Kasumi support");
318                 break;
319
320         case PVR_440EPX2_RA:
321                 puts("EPx Rev. A");
322                 strcpy(addstr, "No Security/Kasumi support");
323                 break;
324
325         case PVR_440GRX1_RA:
326                 puts("GRx Rev. A");
327                 strcpy(addstr, "Security/Kasumi support");
328                 break;
329
330         case PVR_440GRX2_RA:
331                 puts("GRx Rev. A");
332                 strcpy(addstr, "No Security/Kasumi support");
333                 break;
334
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
343         case PVR_440SPe_RA:
344                 puts("SPe Rev. A");
345                 break;
346
347         case PVR_440SPe_RB:
348                 puts("SPe Rev. B");
349                 break;
350
351         default:
352                 printf (" UNKNOWN (PVR=%08x)", pvr);
353                 break;
354         }
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
361         if (addstr[0] != 0)
362                 printf("       %s\n", addstr);
363
364 #if defined(I2C_BOOTROM)
365         printf ("       I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis");
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()]);
369 #endif  /* SDR0_PINSTP_SHIFT */
370 #endif  /* I2C_BOOTROM */
371
372 #if defined(CONFIG_PCI)
373         printf ("       Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis");
374 #endif
375
376 #if defined(PCI_ASYNC)
377         if (pci_async_enabled()) {
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         }
383 #endif
384
385 #if defined(CONFIG_PCI)
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');
409
410         return 0;
411 }
412
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
424
425 /* ------------------------------------------------------------------------- */
426
427 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
428 {
429 #if defined(CFG_4xx_RESET_TYPE)
430         mtspr(dbcr0, CFG_4xx_RESET_TYPE << 28);
431 #else
432         /*
433          * Initiate system reset in debug control register DBCR
434          */
435         mtspr(dbcr0, 0x30000000);
436 #endif /* defined(CONFIG_BOARD_RESET) */
437
438         return 1;
439 }
440
441 #if defined(CONFIG_440)
442 static int do_chip_reset (unsigned long sys0, unsigned long sys1)
443 {
444         /* Changes to cpc0_sys0 and cpc0_sys1 require chip
445          * reset.
446          */
447         mtdcr (cntrl0, mfdcr (cntrl0) | 0x80000000);    /* Set SWE */
448         mtdcr (cpc0_sys0, sys0);
449         mtdcr (cpc0_sys1, sys1);
450         mtdcr (cntrl0, mfdcr (cntrl0) & ~0x80000000);   /* Clr SWE */
451         mtspr (dbcr0, 0x20000000);      /* Reset the chip */
452
453         return 1;
454 }
455 #endif
456
457
458 /*
459  * Get timebase clock frequency
460  */
461 unsigned long get_tbclk (void)
462 {
463 #if !defined(CONFIG_IOP480)
464         sys_info_t  sys_info;
465
466         get_sys_info(&sys_info);
467         return (sys_info.freqProcessor);
468 #else
469         return (66000000);
470 #endif
471
472 }
473
474
475 #if defined(CONFIG_WATCHDOG)
476 void
477 watchdog_reset(void)
478 {
479         int re_enable = disable_interrupts();
480         reset_4xx_watchdog();
481         if (re_enable) enable_interrupts();
482 }
483
484 void
485 reset_4xx_watchdog(void)
486 {
487         /*
488          * Clear TSR(WIS) bit
489          */
490         mtspr(tsr, 0x40000000);
491 }
492 #endif  /* CONFIG_WATCHDOG */