cpu.c revision 1.20 1 1.20 bjh21 /* $NetBSD: cpu.c,v 1.20 2002/03/09 23:49:15 bjh21 Exp $ */
2 1.1 matt
3 1.1 matt /*
4 1.1 matt * Copyright (c) 1995 Mark Brinicombe.
5 1.1 matt * Copyright (c) 1995 Brini.
6 1.1 matt * All rights reserved.
7 1.1 matt *
8 1.1 matt * Redistribution and use in source and binary forms, with or without
9 1.1 matt * modification, are permitted provided that the following conditions
10 1.1 matt * are met:
11 1.1 matt * 1. Redistributions of source code must retain the above copyright
12 1.1 matt * notice, this list of conditions and the following disclaimer.
13 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 matt * notice, this list of conditions and the following disclaimer in the
15 1.1 matt * documentation and/or other materials provided with the distribution.
16 1.1 matt * 3. All advertising materials mentioning features or use of this software
17 1.1 matt * must display the following acknowledgement:
18 1.1 matt * This product includes software developed by Brini.
19 1.1 matt * 4. The name of the company nor the name of the author may be used to
20 1.1 matt * endorse or promote products derived from this software without specific
21 1.1 matt * prior written permission.
22 1.1 matt *
23 1.1 matt * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 1.1 matt * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 1.1 matt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.1 matt * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 1.1 matt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 1.1 matt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 1.1 matt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 matt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 matt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 matt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 matt * SUCH DAMAGE.
34 1.1 matt *
35 1.1 matt * RiscBSD kernel project
36 1.1 matt *
37 1.1 matt * cpu.c
38 1.1 matt *
39 1.1 matt * Probing and configuration for the master cpu
40 1.1 matt *
41 1.1 matt * Created : 10/10/95
42 1.1 matt */
43 1.1 matt
44 1.1 matt #include "opt_armfpe.h"
45 1.1 matt #include "opt_cputypes.h"
46 1.1 matt
47 1.1 matt #include <sys/param.h>
48 1.20 bjh21
49 1.20 bjh21 __RCSID("$NetBSD: cpu.c,v 1.20 2002/03/09 23:49:15 bjh21 Exp $");
50 1.20 bjh21
51 1.1 matt #include <sys/systm.h>
52 1.1 matt #include <sys/malloc.h>
53 1.1 matt #include <sys/device.h>
54 1.1 matt #include <sys/proc.h>
55 1.1 matt #include <uvm/uvm_extern.h>
56 1.1 matt #include <machine/conf.h>
57 1.1 matt #include <machine/cpu.h>
58 1.10 thorpej #include <arm/undefined.h>
59 1.10 thorpej
60 1.10 thorpej #include <arm/cpus.h>
61 1.1 matt
62 1.1 matt #ifdef ARMFPE
63 1.1 matt #include <machine/bootconfig.h> /* For boot args */
64 1.11 thorpej #include <arm/fpe-arm/armfpe.h>
65 1.11 thorpej #endif
66 1.1 matt
67 1.1 matt cpu_t cpus[MAX_CPUS];
68 1.1 matt
69 1.20 bjh21 char cpu_model[256];
70 1.1 matt volatile int undefined_test; /* Used for FPA test */
71 1.1 matt
72 1.1 matt /* Prototypes */
73 1.15 bjh21 void identify_master_cpu(struct device *dv, int cpu_number);
74 1.18 bjh21 void identify_arm_cpu(struct device *dv, int cpu_number, struct cpu_info *);
75 1.15 bjh21 void identify_arm_fpu(struct device *dv, int cpu_number);
76 1.15 bjh21 int fpa_test(u_int, u_int, trapframe_t *, int);
77 1.15 bjh21 int fpa_handler(u_int, u_int, trapframe_t *, int);
78 1.1 matt
79 1.1 matt /*
80 1.1 matt * void cpusattach(struct device *parent, struct device *dev, void *aux)
81 1.1 matt *
82 1.1 matt * Attach the main cpu
83 1.1 matt */
84 1.1 matt
85 1.1 matt void
86 1.15 bjh21 cpu_attach(struct device *dv)
87 1.1 matt {
88 1.15 bjh21
89 1.1 matt identify_master_cpu(dv, CPU_MASTER);
90 1.1 matt }
91 1.1 matt
92 1.1 matt /*
93 1.1 matt * Used to test for an FPA. The following function is installed as a coproc1
94 1.1 matt * handler on the undefined instruction vector and then we issue a FPA
95 1.1 matt * instruction. If undefined_test is non zero then the FPA did not handle
96 1.1 matt * the instruction so must be absent.
97 1.1 matt */
98 1.1 matt
99 1.1 matt int
100 1.15 bjh21 fpa_test(u_int address, u_int instruction, trapframe_t *frame, int fault_code)
101 1.1 matt {
102 1.1 matt
103 1.1 matt frame->tf_pc += INSN_SIZE;
104 1.1 matt ++undefined_test;
105 1.1 matt return(0);
106 1.1 matt }
107 1.1 matt
108 1.1 matt /*
109 1.1 matt * If an FPA was found then this function is installed as the coproc1 handler
110 1.1 matt * on the undefined instruction vector. Currently we don't support FPA's
111 1.1 matt * so this just triggers an exception.
112 1.1 matt */
113 1.1 matt
114 1.1 matt int
115 1.15 bjh21 fpa_handler(u_int address, u_int instruction, trapframe_t *frame,
116 1.15 bjh21 int fault_code)
117 1.1 matt {
118 1.1 matt u_int fpsr;
119 1.1 matt
120 1.15 bjh21 __asm __volatile("stmfd sp!, {r0};"
121 1.16 bjh21 "rfs r0;"
122 1.15 bjh21 "mov %0, r0;"
123 1.15 bjh21 "ldmfd sp!, {r0}" : "=r" (fpsr));
124 1.1 matt
125 1.1 matt printf("FPA exception: fpsr = %08x\n", fpsr);
126 1.1 matt
127 1.1 matt return(1);
128 1.1 matt }
129 1.1 matt
130 1.1 matt
131 1.1 matt /*
132 1.1 matt * Identify the master (boot) CPU
133 1.1 matt * This also probes for an FPU and will install an FPE if necessary
134 1.1 matt */
135 1.1 matt
136 1.1 matt void
137 1.15 bjh21 identify_master_cpu(struct device *dv, int cpu_number)
138 1.1 matt {
139 1.1 matt u_int fpsr;
140 1.1 matt void *uh;
141 1.1 matt
142 1.17 bjh21 evcnt_attach_dynamic(&curcpu()->ci_arm700bugcount, EVCNT_TYPE_MISC,
143 1.17 bjh21 NULL, dv->dv_xname, "arm700swibug");
144 1.17 bjh21
145 1.1 matt /* Get the cpu ID from coprocessor 15 */
146 1.1 matt
147 1.18 bjh21 curcpu()->ci_cpuid = cpu_id();
148 1.1 matt
149 1.18 bjh21 identify_arm_cpu(dv, cpu_number, curcpu());
150 1.1 matt
151 1.19 bjh21 if ((curcpu()->ci_cpuid & CPU_ID_CPU_MASK) == CPU_ID_SA110
152 1.18 bjh21 && (curcpu()->ci_cpuid & CPU_ID_REVISION_MASK) < 3) {
153 1.1 matt printf("%s: SA-110 with bugged STM^ instruction\n",
154 1.1 matt dv->dv_xname);
155 1.1 matt }
156 1.1 matt
157 1.1 matt #ifdef CPU_ARM8
158 1.18 bjh21 if ((curcpu()->ci_cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM810) {
159 1.1 matt int clock = arm8_clock_config(0, 0);
160 1.1 matt char *fclk;
161 1.1 matt printf("%s: ARM810 cp15=%02x", dv->dv_xname, clock);
162 1.1 matt printf(" clock:%s", (clock & 1) ? " dynamic" : "");
163 1.1 matt printf("%s", (clock & 2) ? " sync" : "");
164 1.1 matt switch ((clock >> 2) & 3) {
165 1.15 bjh21 case 0:
166 1.1 matt fclk = "bus clock";
167 1.1 matt break;
168 1.15 bjh21 case 1:
169 1.1 matt fclk = "ref clock";
170 1.1 matt break;
171 1.15 bjh21 case 3:
172 1.1 matt fclk = "pll";
173 1.1 matt break;
174 1.15 bjh21 default:
175 1.1 matt fclk = "illegal";
176 1.1 matt break;
177 1.1 matt }
178 1.1 matt printf(" fclk source=%s\n", fclk);
179 1.1 matt }
180 1.1 matt #endif
181 1.1 matt
182 1.1 matt /*
183 1.1 matt * Ok now we test for an FPA
184 1.1 matt * At this point no floating point emulator has been installed.
185 1.1 matt * This means any FP instruction will cause undefined exception.
186 1.1 matt * We install a temporay coproc 1 handler which will modify
187 1.1 matt * undefined_test if it is called.
188 1.1 matt * We then try to read the FP status register. If undefined_test
189 1.1 matt * has been decremented then the instruction was not handled by
190 1.1 matt * an FPA so we know the FPA is missing. If undefined_test is
191 1.1 matt * still 1 then we know the instruction was handled by an FPA.
192 1.1 matt * We then remove our test handler and look at the
193 1.1 matt * FP status register for identification.
194 1.1 matt */
195 1.1 matt
196 1.1 matt uh = install_coproc_handler(FP_COPROC, fpa_test);
197 1.1 matt
198 1.1 matt undefined_test = 0;
199 1.1 matt
200 1.15 bjh21 __asm __volatile("stmfd sp!, {r0};"
201 1.16 bjh21 "rfs r0;"
202 1.15 bjh21 "mov %0, r0;"
203 1.15 bjh21 "ldmfd sp!, {r0}" : "=r" (fpsr));
204 1.1 matt
205 1.1 matt remove_coproc_handler(uh);
206 1.1 matt
207 1.1 matt if (undefined_test == 0) {
208 1.1 matt cpus[cpu_number].fpu_type = (fpsr >> 24);
209 1.1 matt switch (fpsr >> 24) {
210 1.15 bjh21 case 0x81:
211 1.1 matt cpus[cpu_number].fpu_class = FPU_CLASS_FPA;
212 1.1 matt break;
213 1.1 matt
214 1.15 bjh21 default:
215 1.1 matt cpus[cpu_number].fpu_class = FPU_CLASS_FPU;
216 1.1 matt break;
217 1.1 matt }
218 1.1 matt cpus[cpu_number].fpu_flags = 0;
219 1.1 matt install_coproc_handler(FP_COPROC, fpa_handler);
220 1.1 matt } else {
221 1.1 matt cpus[cpu_number].fpu_class = FPU_CLASS_NONE;
222 1.1 matt cpus[cpu_number].fpu_flags = 0;
223 1.1 matt
224 1.1 matt /*
225 1.1 matt * Ok if ARMFPE is defined and the boot options request the
226 1.1 matt * ARM FPE then it will be installed as the FPE.
227 1.1 matt * This is just while I work on integrating the new FPE.
228 1.1 matt * It means the new FPE gets installed if compiled int (ARMFPE
229 1.1 matt * defined) and also gives me a on/off option when I boot in
230 1.1 matt * case the new FPE is causing panics.
231 1.1 matt */
232 1.1 matt
233 1.1 matt #ifdef ARMFPE
234 1.1 matt if (boot_args) {
235 1.2 bjh21 int usearmfpe = 1;
236 1.1 matt
237 1.2 bjh21 get_bootconf_option(boot_args, "armfpe",
238 1.2 bjh21 BOOTOPT_TYPE_BOOLEAN, &usearmfpe);
239 1.2 bjh21 if (usearmfpe) {
240 1.1 matt if (initialise_arm_fpe(&cpus[cpu_number]) != 0)
241 1.1 matt identify_arm_fpu(dv, cpu_number);
242 1.1 matt }
243 1.1 matt }
244 1.1 matt
245 1.1 matt #endif
246 1.1 matt }
247 1.1 matt
248 1.1 matt identify_arm_fpu(dv, cpu_number);
249 1.1 matt }
250 1.1 matt
251 1.19 bjh21 enum cpu_class {
252 1.19 bjh21 CPU_CLASS_NONE,
253 1.19 bjh21 CPU_CLASS_ARM2,
254 1.19 bjh21 CPU_CLASS_ARM2AS,
255 1.19 bjh21 CPU_CLASS_ARM3,
256 1.19 bjh21 CPU_CLASS_ARM6,
257 1.19 bjh21 CPU_CLASS_ARM7,
258 1.19 bjh21 CPU_CLASS_ARM7TDMI,
259 1.19 bjh21 CPU_CLASS_ARM8,
260 1.19 bjh21 CPU_CLASS_ARM9TDMI,
261 1.19 bjh21 CPU_CLASS_ARM9ES,
262 1.19 bjh21 CPU_CLASS_SA1,
263 1.19 bjh21 CPU_CLASS_XSCALE,
264 1.19 bjh21 };
265 1.19 bjh21
266 1.13 thorpej static const char *generic_steppings[16] = {
267 1.14 bjh21 "rev 0", "rev 1", "rev 2", "rev 3",
268 1.14 bjh21 "rev 4", "rev 5", "rev 6", "rev 7",
269 1.14 bjh21 "rev 8", "rev 9", "rev 10", "rev 11",
270 1.14 bjh21 "rev 12", "rev 13", "rev 14", "rev 15",
271 1.14 bjh21 };
272 1.14 bjh21
273 1.14 bjh21 static const char *sa110_steppings[16] = {
274 1.14 bjh21 "rev 0", "step J", "step K", "step S",
275 1.14 bjh21 "step T", "rev 5", "rev 6", "rev 7",
276 1.14 bjh21 "rev 8", "rev 9", "rev 10", "rev 11",
277 1.14 bjh21 "rev 12", "rev 13", "rev 14", "rev 15",
278 1.14 bjh21 };
279 1.14 bjh21
280 1.14 bjh21 static const char *sa1100_steppings[16] = {
281 1.14 bjh21 "rev 0", "step B", "step C", "rev 3",
282 1.14 bjh21 "rev 4", "rev 5", "rev 6", "rev 7",
283 1.14 bjh21 "step D", "step E", "rev 10" "step G",
284 1.14 bjh21 "rev 12", "rev 13", "rev 14", "rev 15",
285 1.14 bjh21 };
286 1.14 bjh21
287 1.14 bjh21 static const char *sa1110_steppings[16] = {
288 1.14 bjh21 "step A-0", "rev 1", "rev 2", "rev 3",
289 1.14 bjh21 "step B-0", "step B-1", "step B-2", "step B-3",
290 1.14 bjh21 "step B-4", "step B-5", "rev 10", "rev 11",
291 1.14 bjh21 "rev 12", "rev 13", "rev 14", "rev 15",
292 1.13 thorpej };
293 1.13 thorpej
294 1.13 thorpej static const char *i80200_steppings[16] = {
295 1.14 bjh21 "step A-0", "step A-1", "step B-0", "step C-0",
296 1.14 bjh21 "rev 4", "rev 5", "rev 6", "rev 7",
297 1.14 bjh21 "rev 8", "rev 9", "rev 10", "rev 11",
298 1.14 bjh21 "rev 12", "rev 13", "rev 14", "rev 15",
299 1.13 thorpej };
300 1.13 thorpej
301 1.1 matt struct cpuidtab {
302 1.1 matt u_int32_t cpuid;
303 1.1 matt enum cpu_class cpu_class;
304 1.9 thorpej const char *cpu_name;
305 1.13 thorpej const char **cpu_steppings;
306 1.1 matt };
307 1.1 matt
308 1.1 matt const struct cpuidtab cpuids[] = {
309 1.13 thorpej { CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2",
310 1.13 thorpej generic_steppings },
311 1.13 thorpej { CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250",
312 1.13 thorpej generic_steppings },
313 1.13 thorpej
314 1.13 thorpej { CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3",
315 1.13 thorpej generic_steppings },
316 1.13 thorpej
317 1.13 thorpej { CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600",
318 1.13 thorpej generic_steppings },
319 1.13 thorpej { CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610",
320 1.13 thorpej generic_steppings },
321 1.13 thorpej { CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620",
322 1.13 thorpej generic_steppings },
323 1.13 thorpej
324 1.13 thorpej { CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700",
325 1.13 thorpej generic_steppings },
326 1.13 thorpej { CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710",
327 1.13 thorpej generic_steppings },
328 1.13 thorpej { CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500",
329 1.13 thorpej generic_steppings },
330 1.13 thorpej { CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a",
331 1.13 thorpej generic_steppings },
332 1.13 thorpej { CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE",
333 1.13 thorpej generic_steppings },
334 1.13 thorpej { CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T",
335 1.13 thorpej generic_steppings },
336 1.13 thorpej { CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T",
337 1.13 thorpej generic_steppings },
338 1.13 thorpej { CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
339 1.13 thorpej generic_steppings },
340 1.13 thorpej { CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
341 1.13 thorpej generic_steppings },
342 1.13 thorpej
343 1.13 thorpej { CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810",
344 1.13 thorpej generic_steppings },
345 1.13 thorpej
346 1.13 thorpej { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
347 1.13 thorpej generic_steppings },
348 1.13 thorpej { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
349 1.13 thorpej generic_steppings },
350 1.13 thorpej { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
351 1.13 thorpej generic_steppings },
352 1.13 thorpej { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
353 1.13 thorpej generic_steppings },
354 1.13 thorpej { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
355 1.13 thorpej generic_steppings },
356 1.13 thorpej { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
357 1.13 thorpej generic_steppings },
358 1.13 thorpej
359 1.13 thorpej { CPU_ID_SA110, CPU_CLASS_SA1, "SA-110",
360 1.14 bjh21 sa110_steppings },
361 1.13 thorpej { CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100",
362 1.14 bjh21 sa1100_steppings },
363 1.13 thorpej { CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110",
364 1.14 bjh21 sa1110_steppings },
365 1.13 thorpej
366 1.13 thorpej { CPU_ID_I80200, CPU_CLASS_XSCALE, "i80200",
367 1.13 thorpej i80200_steppings },
368 1.13 thorpej
369 1.13 thorpej { 0, CPU_CLASS_NONE, NULL, NULL }
370 1.1 matt };
371 1.1 matt
372 1.1 matt struct cpu_classtab {
373 1.9 thorpej const char *class_name;
374 1.9 thorpej const char *class_option;
375 1.1 matt };
376 1.1 matt
377 1.1 matt const struct cpu_classtab cpu_classes[] = {
378 1.6 rearnsha { "unknown", NULL }, /* CPU_CLASS_NONE */
379 1.6 rearnsha { "ARM2", "CPU_ARM2" }, /* CPU_CLASS_ARM2 */
380 1.6 rearnsha { "ARM2as", "CPU_ARM250" }, /* CPU_CLASS_ARM2AS */
381 1.6 rearnsha { "ARM3", "CPU_ARM3" }, /* CPU_CLASS_ARM3 */
382 1.6 rearnsha { "ARM6", "CPU_ARM6" }, /* CPU_CLASS_ARM6 */
383 1.6 rearnsha { "ARM7", "CPU_ARM7" }, /* CPU_CLASS_ARM7 */
384 1.6 rearnsha { "ARM7TDMI", "CPU_ARM7TDMI" }, /* CPU_CLASS_ARM7TDMI */
385 1.6 rearnsha { "ARM8", "CPU_ARM8" }, /* CPU_CLASS_ARM8 */
386 1.6 rearnsha { "ARM9TDMI", NULL }, /* CPU_CLASS_ARM9TDMI */
387 1.6 rearnsha { "ARM9E-S", NULL }, /* CPU_CLASS_ARM9ES */
388 1.6 rearnsha { "SA-1", "CPU_SA110" }, /* CPU_CLASS_SA1 */
389 1.7 thorpej { "XScale", "CPU_XSCALE" }, /* CPU_CLASS_XSCALE */
390 1.1 matt };
391 1.1 matt
392 1.1 matt /*
393 1.1 matt * Report the type of the specifed arm processor. This uses the generic and
394 1.1 matt * arm specific information in the cpu structure to identify the processor.
395 1.1 matt * The remaining fields in the cpu structure are filled in appropriately.
396 1.1 matt */
397 1.1 matt
398 1.12 thorpej static const char *wtnames[] = {
399 1.12 thorpej "write-through",
400 1.12 thorpej "write-back",
401 1.12 thorpej "write-back",
402 1.12 thorpej "**unknown 3**",
403 1.12 thorpej "**unknown 4**",
404 1.12 thorpej "write-back-locking", /* XXX XScale-specific? */
405 1.12 thorpej "write-back-locking-A",
406 1.12 thorpej "write-back-locking-B",
407 1.12 thorpej "**unknown 8**",
408 1.12 thorpej "**unknown 9**",
409 1.12 thorpej "**unknown 10**",
410 1.12 thorpej "**unknown 11**",
411 1.12 thorpej "**unknown 12**",
412 1.12 thorpej "**unknown 13**",
413 1.12 thorpej "**unknown 14**",
414 1.12 thorpej "**unknown 15**",
415 1.12 thorpej };
416 1.12 thorpej
417 1.1 matt void
418 1.18 bjh21 identify_arm_cpu(struct device *dv, int cpu_number, struct cpu_info *ci)
419 1.1 matt {
420 1.1 matt cpu_t *cpu;
421 1.1 matt u_int cpuid;
422 1.19 bjh21 enum cpu_class cpu_class;
423 1.1 matt int i;
424 1.1 matt
425 1.1 matt cpu = &cpus[cpu_number];
426 1.18 bjh21 cpuid = ci->ci_cpuid;
427 1.1 matt
428 1.1 matt if (cpuid == 0) {
429 1.1 matt printf("Processor failed probe - no CPU ID\n");
430 1.1 matt return;
431 1.1 matt }
432 1.1 matt
433 1.1 matt for (i = 0; cpuids[i].cpuid != 0; i++)
434 1.1 matt if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
435 1.19 bjh21 cpu_class = cpuids[i].cpu_class;
436 1.20 bjh21 sprintf(cpu_model, "%s %s (%s core)",
437 1.13 thorpej cpuids[i].cpu_name,
438 1.13 thorpej cpuids[i].cpu_steppings[cpuid &
439 1.13 thorpej CPU_ID_REVISION_MASK],
440 1.19 bjh21 cpu_classes[cpu_class].class_name);
441 1.1 matt break;
442 1.1 matt }
443 1.1 matt
444 1.1 matt if (cpuids[i].cpuid == 0)
445 1.20 bjh21 sprintf(cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
446 1.1 matt
447 1.19 bjh21 switch (cpu_class) {
448 1.1 matt case CPU_CLASS_ARM6:
449 1.1 matt case CPU_CLASS_ARM7:
450 1.3 chris case CPU_CLASS_ARM7TDMI:
451 1.1 matt case CPU_CLASS_ARM8:
452 1.18 bjh21 if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
453 1.20 bjh21 strcat(cpu_model, " IDC disabled");
454 1.1 matt else
455 1.20 bjh21 strcat(cpu_model, " IDC enabled");
456 1.1 matt break;
457 1.6 rearnsha case CPU_CLASS_ARM9TDMI:
458 1.1 matt case CPU_CLASS_SA1:
459 1.4 matt case CPU_CLASS_XSCALE:
460 1.18 bjh21 if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
461 1.20 bjh21 strcat(cpu_model, " DC disabled");
462 1.1 matt else
463 1.20 bjh21 strcat(cpu_model, " DC enabled");
464 1.18 bjh21 if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
465 1.20 bjh21 strcat(cpu_model, " IC disabled");
466 1.1 matt else
467 1.20 bjh21 strcat(cpu_model, " IC enabled");
468 1.1 matt break;
469 1.19 bjh21 default:
470 1.19 bjh21 break;
471 1.1 matt }
472 1.18 bjh21 if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
473 1.20 bjh21 strcat(cpu_model, " WB disabled");
474 1.1 matt else
475 1.20 bjh21 strcat(cpu_model, " WB enabled");
476 1.1 matt
477 1.18 bjh21 if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
478 1.20 bjh21 strcat(cpu_model, " LABT");
479 1.1 matt else
480 1.20 bjh21 strcat(cpu_model, " EABT");
481 1.1 matt
482 1.18 bjh21 if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
483 1.20 bjh21 strcat(cpu_model, " branch prediction enabled");
484 1.1 matt
485 1.1 matt /* Print the info */
486 1.20 bjh21 printf(": %s\n", cpu_model);
487 1.1 matt
488 1.12 thorpej /* Print cache info. */
489 1.12 thorpej if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
490 1.12 thorpej goto skip_pcache;
491 1.12 thorpej
492 1.12 thorpej if (arm_pcache_unified) {
493 1.12 thorpej printf("%s: %dKB/%dB %d-way %s unified cache\n",
494 1.12 thorpej dv->dv_xname, arm_pdcache_size / 1024,
495 1.12 thorpej arm_pdcache_line_size, arm_pdcache_ways,
496 1.12 thorpej wtnames[arm_pcache_type]);
497 1.12 thorpej } else {
498 1.12 thorpej printf("%s: %dKB/%dB %d-way Instruction cache\n",
499 1.12 thorpej dv->dv_xname, arm_picache_size / 1024,
500 1.12 thorpej arm_picache_line_size, arm_picache_ways);
501 1.12 thorpej printf("%s: %dKB/%dB %d-way %s Data cache\n",
502 1.12 thorpej dv->dv_xname, arm_pdcache_size / 1024,
503 1.12 thorpej arm_pdcache_line_size, arm_pdcache_ways,
504 1.12 thorpej wtnames[arm_pcache_type]);
505 1.12 thorpej }
506 1.12 thorpej
507 1.12 thorpej skip_pcache:
508 1.1 matt
509 1.19 bjh21 switch (cpu_class) {
510 1.1 matt #ifdef CPU_ARM2
511 1.1 matt case CPU_CLASS_ARM2:
512 1.1 matt #endif
513 1.1 matt #ifdef CPU_ARM250
514 1.1 matt case CPU_CLASS_ARM2AS:
515 1.1 matt #endif
516 1.1 matt #ifdef CPU_ARM3
517 1.1 matt case CPU_CLASS_ARM3:
518 1.1 matt #endif
519 1.1 matt #ifdef CPU_ARM6
520 1.1 matt case CPU_CLASS_ARM6:
521 1.1 matt #endif
522 1.1 matt #ifdef CPU_ARM7
523 1.1 matt case CPU_CLASS_ARM7:
524 1.1 matt #endif
525 1.3 chris #ifdef CPU_ARM7TDMI
526 1.3 chris case CPU_CLASS_ARM7TDMI:
527 1.3 chris #endif
528 1.1 matt #ifdef CPU_ARM8
529 1.1 matt case CPU_CLASS_ARM8:
530 1.6 rearnsha #endif
531 1.6 rearnsha #ifdef CPU_ARM9
532 1.6 rearnsha case CPU_CLASS_ARM9TDMI:
533 1.1 matt #endif
534 1.1 matt #ifdef CPU_SA110
535 1.1 matt case CPU_CLASS_SA1:
536 1.4 matt #endif
537 1.4 matt #ifdef CPU_XSCALE
538 1.4 matt case CPU_CLASS_XSCALE:
539 1.1 matt #endif
540 1.1 matt break;
541 1.1 matt default:
542 1.19 bjh21 if (cpu_classes[cpu_class].class_option != NULL)
543 1.1 matt printf("%s: %s does not fully support this CPU."
544 1.1 matt "\n", dv->dv_xname, ostype);
545 1.1 matt else {
546 1.1 matt printf("%s: This kernel does not fully support "
547 1.1 matt "this CPU.\n", dv->dv_xname);
548 1.1 matt printf("%s: Recompile with \"options %s\" to "
549 1.1 matt "correct this.\n", dv->dv_xname,
550 1.19 bjh21 cpu_classes[cpu_class].class_option);
551 1.1 matt }
552 1.1 matt break;
553 1.1 matt }
554 1.1 matt
555 1.1 matt }
556 1.1 matt
557 1.1 matt
558 1.1 matt /*
559 1.1 matt * Report the type of the specifed arm fpu. This uses the generic and arm
560 1.1 matt * specific information in the cpu structure to identify the fpu. The
561 1.1 matt * remaining fields in the cpu structure are filled in appropriately.
562 1.1 matt */
563 1.1 matt
564 1.1 matt void
565 1.15 bjh21 identify_arm_fpu(struct device *dv, int cpu_number)
566 1.1 matt {
567 1.1 matt cpu_t *cpu;
568 1.1 matt
569 1.1 matt cpu = &cpus[cpu_number];
570 1.1 matt
571 1.1 matt /* Now for the FP info */
572 1.1 matt
573 1.1 matt switch (cpu->fpu_class) {
574 1.1 matt case FPU_CLASS_NONE :
575 1.1 matt strcpy(cpu->fpu_model, "None");
576 1.1 matt break;
577 1.1 matt case FPU_CLASS_FPE :
578 1.1 matt printf("%s: FPE: %s\n", dv->dv_xname, cpu->fpu_model);
579 1.1 matt printf("%s: no FP hardware found\n", dv->dv_xname);
580 1.1 matt break;
581 1.1 matt case FPU_CLASS_FPA :
582 1.1 matt printf("%s: FPE: %s\n", dv->dv_xname, cpu->fpu_model);
583 1.1 matt if (cpu->fpu_type == FPU_TYPE_FPA11) {
584 1.1 matt strcpy(cpu->fpu_model, "FPA11");
585 1.1 matt printf("%s: FPA11 found\n", dv->dv_xname);
586 1.1 matt } else {
587 1.1 matt strcpy(cpu->fpu_model, "FPA");
588 1.1 matt printf("%s: FPA10 found\n", dv->dv_xname);
589 1.1 matt }
590 1.1 matt if ((cpu->fpu_flags & 4) == 0)
591 1.1 matt strcat(cpu->fpu_model, "");
592 1.1 matt else
593 1.1 matt strcat(cpu->fpu_model, " clk/2");
594 1.1 matt break;
595 1.1 matt case FPU_CLASS_FPU :
596 1.1 matt sprintf(cpu->fpu_model, "Unknown FPU (ID=%02x)\n",
597 1.1 matt cpu->fpu_type);
598 1.1 matt printf("%s: %s\n", dv->dv_xname, cpu->fpu_model);
599 1.1 matt break;
600 1.1 matt }
601 1.1 matt }
602 1.1 matt
603 1.1 matt /* End of cpu.c */
604