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