]>
Commit | Line | Data |
---|---|---|
1df49e27 WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. | |
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.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 | * more modifications by | |
36 | * Josh Huber <huber@mclx.com> | |
37 | * added support for the 74xx series of cpus | |
38 | * added support for the 7xx series of cpus | |
39 | * made the code a little less hard-coded, and more auto-detectish | |
40 | */ | |
41 | ||
42 | #include <common.h> | |
43 | #include <command.h> | |
44 | #include <74xx_7xx.h> | |
45 | #include <asm/cache.h> | |
46 | ||
4c52783b | 47 | #if defined(CONFIG_OF_FLAT_TREE) |
48 | #include <ft_build.h> | |
49 | #endif | |
50 | ||
c7de829c WD |
51 | #ifdef CONFIG_AMIGAONEG3SE |
52 | #include "../board/MAI/AmigaOneG3SE/via686.h" | |
53 | #include "../board/MAI/AmigaOneG3SE/memio.h" | |
54 | #endif | |
55 | ||
d87080b7 WD |
56 | DECLARE_GLOBAL_DATA_PTR; |
57 | ||
1df49e27 WD |
58 | cpu_t |
59 | get_cpu_type(void) | |
60 | { | |
61 | uint pvr = get_pvr(); | |
62 | cpu_t type; | |
63 | ||
64 | type = CPU_UNKNOWN; | |
65 | ||
66 | switch (PVR_VER(pvr)) { | |
67 | case 0x000c: | |
68 | type = CPU_7400; | |
69 | break; | |
70 | case 0x0008: | |
71 | type = CPU_750; | |
72 | ||
72755c71 | 73 | if (((pvr >> 8) & 0xff) == 0x01) { |
1df49e27 WD |
74 | type = CPU_750CX; /* old CX (80100 and 8010x?)*/ |
75 | } else if (((pvr >> 8) & 0xff) == 0x22) { | |
76 | type = CPU_750CX; /* CX (82201,82202) and CXe (82214) */ | |
77 | } else if (((pvr >> 8) & 0xff) == 0x33) { | |
78 | type = CPU_750CX; /* CXe (83311) */ | |
79 | } else if (((pvr >> 12) & 0xF) == 0x3) { | |
80 | type = CPU_755; | |
72755c71 WD |
81 | } |
82 | break; | |
83 | ||
84 | case 0x7000: | |
85 | type = CPU_750FX; | |
1df49e27 WD |
86 | break; |
87 | ||
3a473b2a WD |
88 | case 0x7002: |
89 | type = CPU_750GX; | |
90 | break; | |
91 | ||
1df49e27 WD |
92 | case 0x800C: |
93 | type = CPU_7410; | |
94 | break; | |
95 | ||
72755c71 | 96 | case 0x8000: |
1df49e27 WD |
97 | type = CPU_7450; |
98 | break; | |
99 | ||
3a473b2a WD |
100 | case 0x8001: |
101 | type = CPU_7455; | |
102 | break; | |
103 | ||
104 | case 0x8002: | |
105 | type = CPU_7457; | |
106 | break; | |
107 | ||
4c52783b | 108 | case 0x8003: |
109 | type = CPU_7447A; | |
110 | break; | |
c9c1eeed | 111 | |
4c52783b | 112 | case 0x8004: |
113 | type = CPU_7448; | |
114 | break; | |
c9c1eeed | 115 | |
1df49e27 WD |
116 | default: |
117 | break; | |
118 | } | |
119 | ||
120 | return type; | |
121 | } | |
122 | ||
123 | /* ------------------------------------------------------------------------- */ | |
124 | ||
125 | #if !defined(CONFIG_BAB7xx) | |
126 | int checkcpu (void) | |
127 | { | |
1df49e27 WD |
128 | uint type = get_cpu_type(); |
129 | uint pvr = get_pvr(); | |
130 | ulong clock = gd->cpu_clk; | |
131 | char buf[32]; | |
132 | char *str; | |
133 | ||
134 | puts ("CPU: "); | |
135 | ||
136 | switch (type) { | |
137 | case CPU_750CX: | |
138 | printf ("750CX%s v%d.%d", (pvr&0xf0)?"e":"", | |
139 | (pvr>>8) & 0xf, | |
140 | pvr & 0xf); | |
141 | goto PR_CLK; | |
142 | ||
143 | case CPU_750: | |
144 | str = "750"; | |
145 | break; | |
146 | ||
72755c71 WD |
147 | case CPU_750FX: |
148 | str = "750FX"; | |
149 | break; | |
150 | ||
3a473b2a WD |
151 | case CPU_750GX: |
152 | str = "750GX"; | |
153 | break; | |
154 | ||
1df49e27 WD |
155 | case CPU_755: |
156 | str = "755"; | |
157 | break; | |
158 | ||
159 | case CPU_7400: | |
160 | str = "MPC7400"; | |
161 | break; | |
162 | ||
72755c71 WD |
163 | case CPU_7410: |
164 | str = "MPC7410"; | |
1df49e27 WD |
165 | break; |
166 | ||
c9c1eeed | 167 | case CPU_7447A: |
168 | str = "MPC7447A"; | |
169 | break; | |
170 | ||
1eac2a71 SR |
171 | case CPU_7448: |
172 | str = "MPC7448"; | |
1df49e27 WD |
173 | break; |
174 | ||
72755c71 WD |
175 | case CPU_7450: |
176 | str = "MPC7450"; | |
1df49e27 WD |
177 | break; |
178 | ||
3a473b2a WD |
179 | case CPU_7455: |
180 | str = "MPC7455"; | |
181 | break; | |
182 | ||
183 | case CPU_7457: | |
184 | str = "MPC7457"; | |
185 | break; | |
186 | ||
1df49e27 | 187 | default: |
72755c71 | 188 | printf("Unknown CPU -- PVR: 0x%08x\n", pvr); |
1df49e27 WD |
189 | return -1; |
190 | } | |
191 | ||
192 | printf ("%s v%d.%d", str, (pvr >> 8) & 0xFF, pvr & 0xFF); | |
193 | PR_CLK: | |
194 | printf (" @ %s MHz\n", strmhz(buf, clock)); | |
195 | ||
196 | return (0); | |
197 | } | |
198 | #endif | |
199 | /* these two functions are unimplemented currently [josh] */ | |
200 | ||
72755c71 WD |
201 | /* -------------------------------------------------------------------- */ |
202 | /* L1 i-cache */ | |
1df49e27 WD |
203 | |
204 | int | |
205 | checkicache(void) | |
206 | { | |
207 | return 0; /* XXX */ | |
208 | } | |
209 | ||
72755c71 WD |
210 | /* -------------------------------------------------------------------- */ |
211 | /* L1 d-cache */ | |
1df49e27 WD |
212 | |
213 | int | |
214 | checkdcache(void) | |
215 | { | |
216 | return 0; /* XXX */ | |
217 | } | |
218 | ||
72755c71 | 219 | /* -------------------------------------------------------------------- */ |
1df49e27 WD |
220 | |
221 | static inline void | |
222 | soft_restart(unsigned long addr) | |
223 | { | |
224 | /* SRR0 has system reset vector, SRR1 has default MSR value */ | |
225 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | |
226 | ||
227 | __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); | |
228 | __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); | |
229 | __asm__ __volatile__ ("mtspr 27, 4"); | |
230 | __asm__ __volatile__ ("rfi"); | |
231 | ||
232 | while(1); /* not reached */ | |
233 | } | |
234 | ||
235 | ||
236 | #if !defined(CONFIG_PCIPPC2) && \ | |
237 | !defined(CONFIG_BAB7xx) && \ | |
f5e0d039 HS |
238 | !defined(CONFIG_ELPPC) && \ |
239 | !defined(CONFIG_PPMC7XX) | |
1df49e27 WD |
240 | /* no generic way to do board reset. simply call soft_reset. */ |
241 | void | |
8bde7f77 | 242 | do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
1df49e27 | 243 | { |
dd520bf3 | 244 | ulong addr; |
1df49e27 WD |
245 | /* flush and disable I/D cache */ |
246 | __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); | |
247 | __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); | |
248 | __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); | |
249 | __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); | |
250 | __asm__ __volatile__ ("sync"); | |
251 | __asm__ __volatile__ ("mtspr 1008, 4"); | |
252 | __asm__ __volatile__ ("isync"); | |
253 | __asm__ __volatile__ ("sync"); | |
254 | __asm__ __volatile__ ("mtspr 1008, 5"); | |
255 | __asm__ __volatile__ ("isync"); | |
256 | __asm__ __volatile__ ("sync"); | |
257 | ||
258 | #ifdef CFG_RESET_ADDRESS | |
259 | addr = CFG_RESET_ADDRESS; | |
260 | #else | |
261 | /* | |
262 | * note: when CFG_MONITOR_BASE points to a RAM address, | |
263 | * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid | |
264 | * address. Better pick an address known to be invalid on your | |
265 | * system and assign it to CFG_RESET_ADDRESS. | |
266 | */ | |
267 | addr = CFG_MONITOR_BASE - sizeof (ulong); | |
268 | #endif | |
269 | soft_restart(addr); | |
270 | while(1); /* not reached */ | |
271 | } | |
272 | #endif | |
273 | ||
274 | /* ------------------------------------------------------------------------- */ | |
275 | ||
276 | /* | |
277 | * For the 7400 the TB clock runs at 1/4 the cpu bus speed. | |
278 | */ | |
4c52783b | 279 | #if defined(CONFIG_AMIGAONEG3SE) || defined(CFG_CONFIG_BUS_CLK) |
c7de829c | 280 | unsigned long get_tbclk(void) |
1df49e27 | 281 | { |
c7de829c | 282 | return (gd->bus_clk / 4); |
1df49e27 | 283 | } |
4c52783b | 284 | #else /* ! CONFIG_AMIGAONEG3SE and !CFG_CONFIG_BUS_CLK*/ |
1df49e27 | 285 | |
c7de829c WD |
286 | unsigned long get_tbclk (void) |
287 | { | |
288 | return CFG_BUS_HZ / 4; | |
289 | } | |
4c52783b | 290 | #endif /* CONFIG_AMIGAONEG3SE or CFG_CONFIG_BUS_CLK*/ |
1df49e27 | 291 | /* ------------------------------------------------------------------------- */ |
1df49e27 WD |
292 | #if defined(CONFIG_WATCHDOG) |
293 | #if !defined(CONFIG_PCIPPC2) && !defined(CONFIG_BAB7xx) | |
294 | void | |
295 | watchdog_reset(void) | |
296 | { | |
297 | ||
298 | } | |
299 | #endif /* !CONFIG_PCIPPC2 && !CONFIG_BAB7xx */ | |
300 | #endif /* CONFIG_WATCHDOG */ | |
301 | ||
302 | /* ------------------------------------------------------------------------- */ | |
4c52783b | 303 | |
304 | #ifdef CONFIG_OF_FLAT_TREE | |
305 | void | |
ee311214 | 306 | ft_cpu_setup (void *blob, bd_t *bd) |
4c52783b | 307 | { |
308 | u32 *p; | |
309 | ulong clock; | |
310 | int len; | |
311 | ||
312 | clock = bd->bi_busfreq; | |
313 | ||
ee311214 | 314 | p = ft_get_prop (blob, "/cpus/" OF_CPU "/bus-frequency", &len); |
4c52783b | 315 | if (p != NULL) |
ee311214 | 316 | *p = cpu_to_be32 (clock); |
4c52783b | 317 | |
318 | #if defined(CONFIG_TSI108_ETH) | |
ee311214 | 319 | p = ft_get_prop (blob, "/" OF_TSI "/ethernet@6200/address", &len); |
320 | memcpy (p, bd->bi_enetaddr, 6); | |
4c52783b | 321 | #endif |
ee311214 | 322 | |
4c52783b | 323 | #if defined(CONFIG_HAS_ETH1) |
ee311214 | 324 | p = ft_get_prop (blob, "/" OF_TSI "/ethernet@6600/address", &len); |
325 | memcpy (p, bd->bi_enet1addr, 6); | |
4c52783b | 326 | #endif |
327 | } | |
328 | #endif | |
329 | /* ------------------------------------------------------------------------- */ |