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