]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/cpu.c
Initial revision
[karo-tx-uboot.git] / cpu / ppc4xx / cpu.c
1 /*
2  * (C) Copyright 2000
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  * m8xx.c
26  *
27  * CPU specific code
28  *
29  * written or collected and sometimes rewritten by
30  * Magnus Damm <damm@bitsmart.com>
31  *
32  * minor modifications by
33  * Wolfgang Denk <wd@denx.de>
34  */
35
36 #include <common.h>
37 #include <watchdog.h>
38 #include <command.h>
39 #include <asm/cache.h>
40 #include <ppc4xx.h>
41
42
43 #if defined(CONFIG_440)
44 static int do_chip_reset( unsigned long sys0, unsigned long sys1 );
45 #endif
46
47 /* ------------------------------------------------------------------------- */
48
49 int checkcpu (void)
50 {
51 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480) || defined(CONFIG_440)
52         uint pvr = get_pvr();
53 #endif
54 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480)
55         DECLARE_GLOBAL_DATA_PTR;
56
57         ulong clock = gd->cpu_clk;
58         char buf[32];
59 #endif
60
61 #if defined(CONFIG_405GP) || defined(CONFIG_405CR)
62         PPC405_SYS_INFO sys_info;
63
64         puts ("CPU:   ");
65
66         get_sys_info(&sys_info);
67
68 #if CONFIG_405GP
69         puts("IBM PowerPC 405GP");
70         if (pvr == PVR_405GPR_RA) {
71                 putc('r');
72         }
73         puts(" Rev. ");
74 #endif
75 #if CONFIG_405CR
76         puts("IBM PowerPC 405CR Rev. ");
77 #endif
78         switch (pvr) {
79         case PVR_405GP_RB:
80                 putc('B');
81                 break;
82         case PVR_405GP_RC:
83 #if CONFIG_405CR
84         case PVR_405CR_RC:
85 #endif
86                 putc('C');
87                 break;
88         case PVR_405GP_RD:
89                 putc('D');
90                 break;
91 #if CONFIG_405GP
92         case PVR_405GP_RE:
93                 putc('E');
94                 break;
95 #endif
96         case PVR_405CR_RA:
97         case PVR_405GPR_RA:
98                 putc('A');
99                 break;
100         case PVR_405CR_RB:
101                 putc('B');
102                 break;
103         default:
104                 printf("? (PVR=%08x)", pvr);
105                 break;
106         }
107
108         printf(" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock),
109                sys_info.freqPLB / 1000000,
110                sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
111                sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
112
113 #if CONFIG_405GP
114         if (mfdcr(strap) & PSR_PCI_ASYNC_EN)
115                 printf("           PCI async ext clock used, ");
116         else
117                 printf("           PCI sync clock at %lu MHz, ",
118                        sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
119         if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
120                 printf("internal PCI arbiter enabled\n");
121         else
122                 printf("external PCI arbiter enabled\n");
123 #endif
124
125         if ((pvr | 0x00000001) == PVR_405GPR_RA) {
126                 printf("           16 kB I-Cache 16 kB D-Cache");
127         } else {
128                 printf("           16 kB I-Cache 8 kB D-Cache");
129         }
130
131
132 #endif  /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
133
134 #ifdef CONFIG_IOP480
135         printf("PLX IOP480 (PVR=%08x)", pvr);
136         printf(" at %s MHz:", strmhz(buf, clock));
137         printf(" %u kB I-Cache", 4);
138         printf(" %u kB D-Cache", 2);
139 #endif
140
141 #if defined(CONFIG_440)
142         puts("IBM PowerPC 440 Rev. ");
143         switch(pvr)
144         {
145         case PVR_440GP_RB:
146                 putc('B');
147         /* See errata 1.12: CHIP_4 */
148         if(   ( mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0) )
149             ||( mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1) ) ){
150             puts("\n\t CPC0_SYSx DCRs corrupted. Resetting chip ...\n");
151             udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
152             do_chip_reset( mfdcr(cpc0_strp0), mfdcr(cpc0_strp1) );
153         }
154                 break;
155         case PVR_440GP_RC:
156                 putc('C');
157                 break;
158         default:
159                 printf("UNKNOWN (PVR=%08x)", pvr);
160                 break;
161         }
162 #endif
163
164         printf("\n");
165
166         return 0;
167 }
168
169
170 /* ------------------------------------------------------------------------- */
171
172 int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
173 {
174         /*
175          * Initiate system reset in debug control register DBCR
176          */
177         __asm__ __volatile__("lis   3, 0x3000" ::: "r3");
178 #if defined(CONFIG_440)
179         __asm__ __volatile__("mtspr 0x134, 3");
180 #else
181         __asm__ __volatile__("mtspr 0x3f2, 3");
182 #endif
183         return 1;
184 }
185
186 #if defined(CONFIG_440)
187 static
188 int do_chip_reset( unsigned long sys0, unsigned long sys1 )
189 {
190     /* Changes to cpc0_sys0 and cpc0_sys1 require chip
191      * reset.
192      */
193     mtdcr( cntrl0, mfdcr(cntrl0) | 0x80000000 ); /* Set SWE */
194     mtdcr( cpc0_sys0, sys0 );
195     mtdcr( cpc0_sys1, sys1 );
196     mtdcr( cntrl0, mfdcr(cntrl0) & ~0x80000000 ); /* Clr SWE */
197     mtspr( dbcr0, 0x20000000);  /* Reset the chip */
198
199     return 1;
200 }
201 #endif
202
203
204 /*
205  * Get timebase clock frequency
206  */
207 unsigned long get_tbclk (void)
208 {
209 #if defined(CONFIG_440)
210
211         sys_info_t  sys_info;
212
213         get_sys_info(&sys_info);
214         return (sys_info.freqProcessor);
215
216 #elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405)
217
218         PPC405_SYS_INFO sys_info;
219
220         get_sys_info(&sys_info);
221         return (sys_info.freqProcessor);
222
223 #elif defined(CONFIG_IOP480)
224
225         return (66000000);
226
227 #else
228
229 # error get_tbclk() not implemented
230
231 #endif
232
233 }
234
235
236 #if defined(CONFIG_WATCHDOG)
237 void
238 watchdog_reset(void)
239 {
240         int re_enable = disable_interrupts();
241         reset_4xx_watchdog();
242         if (re_enable) enable_interrupts();
243 }
244
245 void
246 reset_4xx_watchdog(void)
247 {
248         /*
249          * Clear TSR(WIS) bit
250          */
251         mtspr(tsr, 0x40000000);
252 }
253 #endif  /* CONFIG_WATCHDOG */