Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.84
      1 /*	$NetBSD: cpu.c,v 1.84 2012/08/14 20:39:49 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.84 2012/08/14 20:39:49 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(device_t dv, struct cpu_info *);
     71 
     72 /*
     73  * Identify the master (boot) CPU
     74  */
     75 
     76 void
     77 cpu_attach(device_t 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 	vfp_attach();		/* XXX SMP */
    161 }
    162 
    163 enum cpu_class {
    164 	CPU_CLASS_NONE,
    165 	CPU_CLASS_ARM2,
    166 	CPU_CLASS_ARM2AS,
    167 	CPU_CLASS_ARM3,
    168 	CPU_CLASS_ARM6,
    169 	CPU_CLASS_ARM7,
    170 	CPU_CLASS_ARM7TDMI,
    171 	CPU_CLASS_ARM8,
    172 	CPU_CLASS_ARM9TDMI,
    173 	CPU_CLASS_ARM9ES,
    174 	CPU_CLASS_ARM9EJS,
    175 	CPU_CLASS_ARM10E,
    176 	CPU_CLASS_ARM10EJ,
    177 	CPU_CLASS_SA1,
    178 	CPU_CLASS_XSCALE,
    179 	CPU_CLASS_ARM11J,
    180 	CPU_CLASS_ARMV4,
    181 	CPU_CLASS_CORTEX,
    182 };
    183 
    184 static const char * const generic_steppings[16] = {
    185 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
    186 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    187 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    188 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    189 };
    190 
    191 static const char * const pN_steppings[16] = {
    192 	"*p0",	"*p1",	"*p2",	"*p3",	"*p4",	"*p5",	"*p6",	"*p7",
    193 	"*p8",	"*p9",	"*p10",	"*p11",	"*p12",	"*p13",	"*p14",	"*p15",
    194 };
    195 
    196 static const char * const sa110_steppings[16] = {
    197 	"rev 0",	"step J",	"step K",	"step S",
    198 	"step T",	"rev 5",	"rev 6",	"rev 7",
    199 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    200 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    201 };
    202 
    203 static const char * const sa1100_steppings[16] = {
    204 	"rev 0",	"step B",	"step C",	"rev 3",
    205 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    206 	"step D",	"step E",	"rev 10"	"step G",
    207 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    208 };
    209 
    210 static const char * const sa1110_steppings[16] = {
    211 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    212 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
    213 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
    214 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    215 };
    216 
    217 static const char * const ixp12x0_steppings[16] = {
    218 	"(IXP1200 step A)",		"(IXP1200 step B)",
    219 	"rev 2",			"(IXP1200 step C)",
    220 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
    221 	"(IXP1240 step B)",		"(IXP1250 step B)",
    222 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    223 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    224 };
    225 
    226 static const char * const xscale_steppings[16] = {
    227 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
    228 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
    229 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    230 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    231 };
    232 
    233 static const char * const i80321_steppings[16] = {
    234 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
    235 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    236 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    237 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    238 };
    239 
    240 static const char * const i80219_steppings[16] = {
    241 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    242 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    243 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    244 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    245 };
    246 
    247 /* Steppings for PXA2[15]0 */
    248 static const char * const pxa2x0_steppings[16] = {
    249 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    250 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
    251 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    252 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    253 };
    254 
    255 /* Steppings for PXA255/26x.
    256  * rev 5: PXA26x B0, rev 6: PXA255 A0
    257  */
    258 static const char * const pxa255_steppings[16] = {
    259 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
    260 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
    261 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    262 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    263 };
    264 
    265 /* Stepping for PXA27x */
    266 static const char * const pxa27x_steppings[16] = {
    267 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    268 	"step C-0",	"rev 5",	"rev 6",	"rev 7",
    269 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    270 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    271 };
    272 
    273 static const char * const ixp425_steppings[16] = {
    274 	"step 0",	"rev 1",	"rev 2",	"rev 3",
    275 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    276 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    277 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    278 };
    279 
    280 struct cpuidtab {
    281 	u_int32_t	cpuid;
    282 	enum		cpu_class cpu_class;
    283 	const char	*cpu_classname;
    284 	const char * const *cpu_steppings;
    285 };
    286 
    287 const struct cpuidtab cpuids[] = {
    288 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
    289 	  generic_steppings },
    290 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
    291 	  generic_steppings },
    292 
    293 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
    294 	  generic_steppings },
    295 
    296 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
    297 	  generic_steppings },
    298 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
    299 	  generic_steppings },
    300 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
    301 	  generic_steppings },
    302 
    303 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
    304 	  generic_steppings },
    305 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
    306 	  generic_steppings },
    307 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
    308 	  generic_steppings },
    309 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
    310 	  generic_steppings },
    311 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
    312 	  generic_steppings },
    313 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
    314 	  generic_steppings },
    315 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
    316 	  generic_steppings },
    317 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
    318 	  generic_steppings },
    319 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
    320 	  generic_steppings },
    321 
    322 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
    323 	  generic_steppings },
    324 
    325 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
    326 	  generic_steppings },
    327 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
    328 	  generic_steppings },
    329 	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
    330 	  generic_steppings },
    331 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
    332 	  generic_steppings },
    333 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
    334 	  generic_steppings },
    335 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    336 	  generic_steppings },
    337 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    338 	  generic_steppings },
    339 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
    340 	  generic_steppings },
    341 	{ CPU_ID_MV88SV131,	CPU_CLASS_ARM9ES,	"Sheeva 88SV131",
    342 	  generic_steppings },
    343 	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_ARM9ES,	"Sheeva 88FR571-vd",
    344 	  generic_steppings },
    345 
    346 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
    347 	  generic_steppings },
    348 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
    349 	  generic_steppings },
    350 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
    351 	  generic_steppings },
    352 
    353 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
    354 	  sa110_steppings },
    355 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
    356 	  sa1100_steppings },
    357 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
    358 	  sa1110_steppings },
    359 
    360 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
    361 	  ixp12x0_steppings },
    362 
    363 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
    364 	  xscale_steppings },
    365 
    366 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    367 	  i80321_steppings },
    368 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    369 	  i80321_steppings },
    370 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    371 	  i80321_steppings },
    372 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    373 	  i80321_steppings },
    374 
    375 	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
    376 	  i80219_steppings },
    377 	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
    378 	  i80219_steppings },
    379 
    380 	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
    381 	  pxa27x_steppings },
    382 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
    383 	  pxa2x0_steppings },
    384 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
    385 	  pxa2x0_steppings },
    386 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
    387 	  pxa2x0_steppings },
    388 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
    389 	  pxa2x0_steppings },
    390 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
    391 	  pxa255_steppings },
    392 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
    393 	  pxa2x0_steppings },
    394 
    395 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
    396 	  ixp425_steppings },
    397 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
    398 	  ixp425_steppings },
    399 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
    400 	  ixp425_steppings },
    401 
    402 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S r0",
    403 	  pN_steppings },
    404 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S r1",
    405 	  pN_steppings },
    406 #if 0
    407 	/* The ARM1156T2-S only has a memory protection unit */
    408 	{ CPU_ID_ARM1156T2S,	CPU_CLASS_ARM11J,	"ARM1156T2-S r0",
    409 	  pN_steppings },
    410 #endif
    411 	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S r0",
    412 	  pN_steppings },
    413 
    414 	{ CPU_ID_ARM11MPCORE,	CPU_CLASS_ARM11J, 	"ARM11 MPCore",
    415 	  generic_steppings },
    416 
    417 	{ CPU_ID_CORTEXA5R0,	CPU_CLASS_CORTEX,	"Cortex-A5 r0",
    418 	  pN_steppings },
    419 	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEX,	"Cortex-A8 r1",
    420 	  pN_steppings },
    421 	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEX,	"Cortex-A8 r2",
    422 	  pN_steppings },
    423 	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEX,	"Cortex-A8 r3",
    424 	  pN_steppings },
    425 	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEX,	"Cortex-A9 r2",
    426 	  pN_steppings },
    427 	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEX,	"Cortex-A9 r3",
    428 	  pN_steppings },
    429 	{ CPU_ID_CORTEXA9R4,	CPU_CLASS_CORTEX,	"Cortex-A9 r4",
    430 	  pN_steppings },
    431 	{ CPU_ID_CORTEXA15R2,	CPU_CLASS_CORTEX,	"Cortex-A15 r2",
    432 	  pN_steppings },
    433 	{ CPU_ID_CORTEXA15R3,	CPU_CLASS_CORTEX,	"Cortex-A15 r3",
    434 	  pN_steppings },
    435 
    436 	{ CPU_ID_FA526,		CPU_CLASS_ARMV4,	"FA526",
    437 	  generic_steppings },
    438 
    439 	{ 0, CPU_CLASS_NONE, NULL, NULL }
    440 };
    441 
    442 struct cpu_classtab {
    443 	const char	*class_name;
    444 	const char	*class_option;
    445 };
    446 
    447 const struct cpu_classtab cpu_classes[] = {
    448 	[CPU_CLASS_NONE] =	{ "unknown",	NULL },
    449 	[CPU_CLASS_ARM2] =	{ "ARM2",	"CPU_ARM2" },
    450 	[CPU_CLASS_ARM2AS] =	{ "ARM2as",	"CPU_ARM250" },
    451 	[CPU_CLASS_ARM3] =	{ "ARM3",	"CPU_ARM3" },
    452 	[CPU_CLASS_ARM6] =	{ "ARM6",	"CPU_ARM6" },
    453 	[CPU_CLASS_ARM7] =	{ "ARM7",	"CPU_ARM7" },
    454 	[CPU_CLASS_ARM7TDMI] =	{ "ARM7TDMI",	"CPU_ARM7TDMI" },
    455 	[CPU_CLASS_ARM8] =	{ "ARM8",	"CPU_ARM8" },
    456 	[CPU_CLASS_ARM9TDMI] =	{ "ARM9TDMI",	NULL },
    457 	[CPU_CLASS_ARM9ES] =	{ "ARM9E-S",	"CPU_ARM9E" },
    458 	[CPU_CLASS_ARM9EJS] =	{ "ARM9EJ-S",	"CPU_ARM9E" },
    459 	[CPU_CLASS_ARM10E] =	{ "ARM10E",	"CPU_ARM10" },
    460 	[CPU_CLASS_ARM10EJ] =	{ "ARM10EJ",	"CPU_ARM10" },
    461 	[CPU_CLASS_SA1] =	{ "SA-1",	"CPU_SA110" },
    462 	[CPU_CLASS_XSCALE] =	{ "XScale",	"CPU_XSCALE_..." },
    463 	[CPU_CLASS_ARM11J] =	{ "ARM11J",	"CPU_ARM11" },
    464 	[CPU_CLASS_ARMV4] =	{ "ARMv4",	"CPU_ARMV4" },
    465 	[CPU_CLASS_CORTEX] =	{ "Cortex",	"CPU_CORTEX" },
    466 };
    467 
    468 /*
    469  * Report the type of the specified arm processor. This uses the generic and
    470  * arm specific information in the CPU structure to identify the processor.
    471  * The remaining fields in the CPU structure are filled in appropriately.
    472  */
    473 
    474 static const char * const wtnames[] = {
    475 	"write-through",
    476 	"write-back",
    477 	"write-back",
    478 	"**unknown 3**",
    479 	"**unknown 4**",
    480 	"write-back-locking",		/* XXX XScale-specific? */
    481 	"write-back-locking-A",
    482 	"write-back-locking-B",
    483 	"**unknown 8**",
    484 	"**unknown 9**",
    485 	"**unknown 10**",
    486 	"**unknown 11**",
    487 	"**unknown 12**",
    488 	"**unknown 13**",
    489 	"write-back-locking-C",
    490 	"**unknown 15**",
    491 };
    492 
    493 void
    494 identify_arm_cpu(device_t dv, struct cpu_info *ci)
    495 {
    496 	u_int cpuid;
    497 	enum cpu_class cpu_class = CPU_CLASS_NONE;
    498 	int i;
    499 	const char *steppingstr;
    500 
    501 	cpuid = ci->ci_arm_cpuid;
    502 
    503 	if (cpuid == 0) {
    504 		aprint_error("Processor failed probe - no CPU ID\n");
    505 		return;
    506 	}
    507 
    508 	for (i = 0; cpuids[i].cpuid != 0; i++)
    509 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
    510 			cpu_class = cpuids[i].cpu_class;
    511 			steppingstr = cpuids[i].cpu_steppings[cpuid &
    512 			    CPU_ID_REVISION_MASK],
    513 			sprintf(cpu_model, "%s%s%s (%s core)",
    514 			    cpuids[i].cpu_classname,
    515 			    steppingstr[0] == '*' ? "" : " ",
    516 			    &steppingstr[steppingstr[0] == '*'],
    517 			    cpu_classes[cpu_class].class_name);
    518 			break;
    519 		}
    520 
    521 	if (cpuids[i].cpuid == 0)
    522 		sprintf(cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
    523 
    524 	aprint_naive(": %s\n", cpu_model);
    525 	aprint_normal(": %s\n", cpu_model);
    526 
    527 	aprint_normal("%s:", dv->dv_xname);
    528 
    529 	switch (cpu_class) {
    530 	case CPU_CLASS_ARM6:
    531 	case CPU_CLASS_ARM7:
    532 	case CPU_CLASS_ARM7TDMI:
    533 	case CPU_CLASS_ARM8:
    534 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
    535 			aprint_normal(" IDC disabled");
    536 		else
    537 			aprint_normal(" IDC enabled");
    538 		break;
    539 	case CPU_CLASS_ARM9TDMI:
    540 	case CPU_CLASS_ARM9ES:
    541 	case CPU_CLASS_ARM9EJS:
    542 	case CPU_CLASS_ARM10E:
    543 	case CPU_CLASS_ARM10EJ:
    544 	case CPU_CLASS_SA1:
    545 	case CPU_CLASS_XSCALE:
    546 	case CPU_CLASS_ARM11J:
    547 	case CPU_CLASS_ARMV4:
    548 	case CPU_CLASS_CORTEX:
    549 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
    550 			aprint_normal(" DC disabled");
    551 		else
    552 			aprint_normal(" DC enabled");
    553 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
    554 			aprint_normal(" IC disabled");
    555 		else
    556 			aprint_normal(" IC enabled");
    557 		break;
    558 	default:
    559 		break;
    560 	}
    561 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
    562 		aprint_normal(" WB disabled");
    563 	else
    564 		aprint_normal(" WB enabled");
    565 
    566 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
    567 		aprint_normal(" LABT");
    568 	else
    569 		aprint_normal(" EABT");
    570 
    571 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
    572 		aprint_normal(" branch prediction enabled");
    573 
    574 	aprint_normal("\n");
    575 
    576 	/* Print cache info. */
    577 	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
    578 		goto skip_pcache;
    579 
    580 	if (arm_pcache_unified) {
    581 		aprint_normal("%s: %dKB/%dB %d-way %s unified cache\n",
    582 		    dv->dv_xname, arm_pdcache_size / 1024,
    583 		    arm_pdcache_line_size, arm_pdcache_ways,
    584 		    wtnames[arm_pcache_type]);
    585 	} else {
    586 		aprint_normal("%s: %dKB/%dB %d-way Instruction cache\n",
    587 		    dv->dv_xname, arm_picache_size / 1024,
    588 		    arm_picache_line_size, arm_picache_ways);
    589 		aprint_normal("%s: %dKB/%dB %d-way %s Data cache\n",
    590 		    dv->dv_xname, arm_pdcache_size / 1024,
    591 		    arm_pdcache_line_size, arm_pdcache_ways,
    592 		    wtnames[arm_pcache_type]);
    593 	}
    594 
    595  skip_pcache:
    596 
    597 	switch (cpu_class) {
    598 #ifdef CPU_ARM2
    599 	case CPU_CLASS_ARM2:
    600 #endif
    601 #ifdef CPU_ARM250
    602 	case CPU_CLASS_ARM2AS:
    603 #endif
    604 #ifdef CPU_ARM3
    605 	case CPU_CLASS_ARM3:
    606 #endif
    607 #ifdef CPU_ARM6
    608 	case CPU_CLASS_ARM6:
    609 #endif
    610 #ifdef CPU_ARM7
    611 	case CPU_CLASS_ARM7:
    612 #endif
    613 #ifdef CPU_ARM7TDMI
    614 	case CPU_CLASS_ARM7TDMI:
    615 #endif
    616 #ifdef CPU_ARM8
    617 	case CPU_CLASS_ARM8:
    618 #endif
    619 #ifdef CPU_ARM9
    620 	case CPU_CLASS_ARM9TDMI:
    621 #endif
    622 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
    623 	case CPU_CLASS_ARM9ES:
    624 	case CPU_CLASS_ARM9EJS:
    625 #endif
    626 #ifdef CPU_ARM10
    627 	case CPU_CLASS_ARM10E:
    628 	case CPU_CLASS_ARM10EJ:
    629 #endif
    630 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
    631     defined(CPU_SA1110) || defined(CPU_IXP12X0)
    632 	case CPU_CLASS_SA1:
    633 #endif
    634 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
    635     defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
    636 	case CPU_CLASS_XSCALE:
    637 #endif
    638 #if defined(CPU_ARM11)
    639 	case CPU_CLASS_ARM11J:
    640 #endif
    641 #if defined(CPU_CORTEX)
    642 	case CPU_CLASS_CORTEX:
    643 #endif
    644 #if defined(CPU_FA526)
    645 	case CPU_CLASS_ARMV4:
    646 #endif
    647 		break;
    648 	default:
    649 		if (cpu_classes[cpu_class].class_option == NULL)
    650 			aprint_error("%s: %s does not fully support this CPU."
    651 			       "\n", dv->dv_xname, ostype);
    652 		else {
    653 			aprint_error("%s: This kernel does not fully support "
    654 			       "this CPU.\n", dv->dv_xname);
    655 			aprint_normal("%s: Recompile with \"options %s\" to "
    656 			       "correct this.\n", dv->dv_xname,
    657 			       cpu_classes[cpu_class].class_option);
    658 		}
    659 		break;
    660 	}
    661 
    662 }
    663 
    664 /* End of cpu.c */
    665