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