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