Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.85
      1 /*	$NetBSD: cpu.c,v 1.85 2012/08/29 17:44:25 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.85 2012/08/29 17:44:25 matt Exp $");
     50 
     51 #include <sys/systm.h>
     52 #include <sys/conf.h>
     53 #include <sys/cpu.h>
     54 #include <sys/device.h>
     55 #include <sys/kmem.h>
     56 #include <sys/proc.h>
     57 
     58 #include <uvm/uvm_extern.h>
     59 
     60 #include <arm/cpuconf.h>
     61 #include <arm/undefined.h>
     62 
     63 #ifdef ARMFPE
     64 #include <machine/bootconfig.h> /* For boot args */
     65 #include <arm/fpe-arm/armfpe.h>
     66 #endif
     67 
     68 char cpu_model[256];
     69 
     70 #ifdef MULTIPROCESSOR
     71 volatile u_int arm_cpu_hatched = 0;
     72 u_int arm_cpu_max = 0;
     73 uint32_t arm_cpu_mbox __cacheline_aligned = 0;
     74 uint32_t arm_cpu_marker __cacheline_aligned = 1;
     75 #endif
     76 
     77 /* Prototypes */
     78 void identify_arm_cpu(device_t dv, struct cpu_info *);
     79 void identify_cortex_caches(device_t dv);
     80 void identify_features(device_t dv);
     81 
     82 /*
     83  * Identify the master (boot) CPU
     84  */
     85 
     86 void
     87 cpu_attach(device_t dv, cpuid_t id)
     88 {
     89 	struct cpu_info *ci;
     90 
     91 	if (id == 0) {
     92 		ci = curcpu();
     93 
     94 		/* Get the CPU ID from coprocessor 15 */
     95 
     96 		ci->ci_arm_cpuid = cpu_id();
     97 		ci->ci_arm_cputype = ci->ci_arm_cpuid & CPU_ID_CPU_MASK;
     98 		ci->ci_arm_cpurev = ci->ci_arm_cpuid & CPU_ID_REVISION_MASK;
     99 	} else {
    100 #ifdef MULTIPROCESSOR
    101 		KASSERT(cpu_info[id] == NULL);
    102 		ci = kmem_zalloc(sizeof(*ci), KM_SLEEP);
    103 		KASSERT(ci != NULL);
    104 		ci->ci_cpl = IPL_HIGH;
    105 		ci->ci_cpuid = id;
    106 		ci->ci_data.cpu_core_id = id;
    107 		ci->ci_data.cpu_cc_freq = cpu_info_store.ci_data.cpu_cc_freq;
    108 		ci->ci_arm_cpuid = cpu_info_store.ci_arm_cpuid;
    109 		ci->ci_arm_cputype = cpu_info_store.ci_arm_cputype;
    110 		ci->ci_arm_cpurev = cpu_info_store.ci_arm_cpurev;
    111 		cpu_info[ci->ci_cpuid] = ci;
    112 		if ((arm_cpu_hatched & (1 << id)) == 0) {
    113 			ci->ci_dev = dv;
    114 			dv->dv_private = ci;
    115 			aprint_naive(": disabled\n");
    116 			aprint_normal(": disabled (unresponsive)\n");
    117 			return;
    118 		}
    119 #else
    120 		aprint_naive(": disabled\n");
    121 		aprint_normal(": disabled (uniprocessor kernel)\n");
    122 		return;
    123 #endif
    124 	}
    125 
    126 	ci->ci_dev = dv;
    127 	dv->dv_private = ci;
    128 
    129 	evcnt_attach_dynamic(&ci->ci_arm700bugcount, EVCNT_TYPE_MISC,
    130 	    NULL, device_xname(dv), "arm700swibug");
    131 
    132 #ifdef MULTIPROCESSOR
    133 	/*
    134 	 * and we are done if this is a secondary processor.
    135 	 */
    136 	if (!CPU_IS_PRIMARY(ci)) {
    137 		aprint_naive(": %s\n", cpu_model);
    138 		aprint_normal(": %s\n", cpu_model);
    139 		mi_cpu_attach(ci);
    140 		return;
    141 	}
    142 #endif
    143 
    144 	identify_arm_cpu(dv, ci);
    145 
    146 #ifdef CPU_STRONGARM
    147 	if (ci->ci_arm_cputype == CPU_ID_SA110 &&
    148 	    ci->ci_arm_cpurev < 3) {
    149 		aprint_normal_dev(dv, "SA-110 with bugged STM^ instruction\n");
    150 	}
    151 #endif
    152 
    153 #ifdef CPU_ARM8
    154 	if ((ci->ci_arm_cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM810) {
    155 		int clock = arm8_clock_config(0, 0);
    156 		char *fclk;
    157 		aprint_normal_dev(dv, "ARM810 cp15=%02x", clock);
    158 		aprint_normal(" clock:%s", (clock & 1) ? " dynamic" : "");
    159 		aprint_normal("%s", (clock & 2) ? " sync" : "");
    160 		switch ((clock >> 2) & 3) {
    161 		case 0:
    162 			fclk = "bus clock";
    163 			break;
    164 		case 1:
    165 			fclk = "ref clock";
    166 			break;
    167 		case 3:
    168 			fclk = "pll";
    169 			break;
    170 		default:
    171 			fclk = "illegal";
    172 			break;
    173 		}
    174 		aprint_normal(" fclk source=%s\n", fclk);
    175  	}
    176 #endif
    177 
    178 #ifdef ARMFPE
    179 	/*
    180 	 * Ok now we test for an FPA
    181 	 * At this point no floating point emulator has been installed.
    182 	 * This means any FP instruction will cause undefined exception.
    183 	 * We install a temporay coproc 1 handler which will modify
    184 	 * undefined_test if it is called.
    185 	 * We then try to read the FP status register. If undefined_test
    186 	 * has been decremented then the instruction was not handled by
    187 	 * an FPA so we know the FPA is missing. If undefined_test is
    188 	 * still 1 then we know the instruction was handled by an FPA.
    189 	 * We then remove our test handler and look at the
    190 	 * FP status register for identification.
    191 	 */
    192 
    193 	/*
    194 	 * Ok if ARMFPE is defined and the boot options request the
    195 	 * ARM FPE then it will be installed as the FPE.
    196 	 * This is just while I work on integrating the new FPE.
    197 	 * It means the new FPE gets installed if compiled int (ARMFPE
    198 	 * defined) and also gives me a on/off option when I boot in
    199 	 * case the new FPE is causing panics.
    200 	 */
    201 
    202 
    203 	int usearmfpe = 1;
    204 	if (boot_args)
    205 		get_bootconf_option(boot_args, "armfpe",
    206 		    BOOTOPT_TYPE_BOOLEAN, &usearmfpe);
    207 	if (usearmfpe)
    208 		initialise_arm_fpe();
    209 #endif
    210 
    211 	vfp_attach();		/* XXX SMP */
    212 }
    213 
    214 enum cpu_class {
    215 	CPU_CLASS_NONE,
    216 	CPU_CLASS_ARM2,
    217 	CPU_CLASS_ARM2AS,
    218 	CPU_CLASS_ARM3,
    219 	CPU_CLASS_ARM6,
    220 	CPU_CLASS_ARM7,
    221 	CPU_CLASS_ARM7TDMI,
    222 	CPU_CLASS_ARM8,
    223 	CPU_CLASS_ARM9TDMI,
    224 	CPU_CLASS_ARM9ES,
    225 	CPU_CLASS_ARM9EJS,
    226 	CPU_CLASS_ARM10E,
    227 	CPU_CLASS_ARM10EJ,
    228 	CPU_CLASS_SA1,
    229 	CPU_CLASS_XSCALE,
    230 	CPU_CLASS_ARM11J,
    231 	CPU_CLASS_ARMV4,
    232 	CPU_CLASS_CORTEX,
    233 };
    234 
    235 static const char * const generic_steppings[16] = {
    236 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
    237 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    238 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    239 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    240 };
    241 
    242 static const char * const pN_steppings[16] = {
    243 	"*p0",	"*p1",	"*p2",	"*p3",	"*p4",	"*p5",	"*p6",	"*p7",
    244 	"*p8",	"*p9",	"*p10",	"*p11",	"*p12",	"*p13",	"*p14",	"*p15",
    245 };
    246 
    247 static const char * const sa110_steppings[16] = {
    248 	"rev 0",	"step J",	"step K",	"step S",
    249 	"step T",	"rev 5",	"rev 6",	"rev 7",
    250 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    251 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    252 };
    253 
    254 static const char * const sa1100_steppings[16] = {
    255 	"rev 0",	"step B",	"step C",	"rev 3",
    256 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    257 	"step D",	"step E",	"rev 10"	"step G",
    258 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    259 };
    260 
    261 static const char * const sa1110_steppings[16] = {
    262 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    263 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
    264 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
    265 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    266 };
    267 
    268 static const char * const ixp12x0_steppings[16] = {
    269 	"(IXP1200 step A)",		"(IXP1200 step B)",
    270 	"rev 2",			"(IXP1200 step C)",
    271 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
    272 	"(IXP1240 step B)",		"(IXP1250 step B)",
    273 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    274 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    275 };
    276 
    277 static const char * const xscale_steppings[16] = {
    278 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
    279 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
    280 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    281 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    282 };
    283 
    284 static const char * const i80321_steppings[16] = {
    285 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
    286 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    287 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    288 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    289 };
    290 
    291 static const char * const i80219_steppings[16] = {
    292 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    293 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    294 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    295 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    296 };
    297 
    298 /* Steppings for PXA2[15]0 */
    299 static const char * const pxa2x0_steppings[16] = {
    300 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    301 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
    302 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    303 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    304 };
    305 
    306 /* Steppings for PXA255/26x.
    307  * rev 5: PXA26x B0, rev 6: PXA255 A0
    308  */
    309 static const char * const pxa255_steppings[16] = {
    310 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
    311 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
    312 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    313 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    314 };
    315 
    316 /* Stepping for PXA27x */
    317 static const char * const pxa27x_steppings[16] = {
    318 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    319 	"step C-0",	"rev 5",	"rev 6",	"rev 7",
    320 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    321 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    322 };
    323 
    324 static const char * const ixp425_steppings[16] = {
    325 	"step 0",	"rev 1",	"rev 2",	"rev 3",
    326 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    327 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    328 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    329 };
    330 
    331 struct cpuidtab {
    332 	u_int32_t	cpuid;
    333 	enum		cpu_class cpu_class;
    334 	const char	*cpu_classname;
    335 	const char * const *cpu_steppings;
    336 };
    337 
    338 const struct cpuidtab cpuids[] = {
    339 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
    340 	  generic_steppings },
    341 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
    342 	  generic_steppings },
    343 
    344 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
    345 	  generic_steppings },
    346 
    347 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
    348 	  generic_steppings },
    349 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
    350 	  generic_steppings },
    351 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
    352 	  generic_steppings },
    353 
    354 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
    355 	  generic_steppings },
    356 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
    357 	  generic_steppings },
    358 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
    359 	  generic_steppings },
    360 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
    361 	  generic_steppings },
    362 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
    363 	  generic_steppings },
    364 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
    365 	  generic_steppings },
    366 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
    367 	  generic_steppings },
    368 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
    369 	  generic_steppings },
    370 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
    371 	  generic_steppings },
    372 
    373 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
    374 	  generic_steppings },
    375 
    376 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
    377 	  generic_steppings },
    378 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
    379 	  generic_steppings },
    380 	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
    381 	  generic_steppings },
    382 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
    383 	  generic_steppings },
    384 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
    385 	  generic_steppings },
    386 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    387 	  generic_steppings },
    388 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    389 	  generic_steppings },
    390 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
    391 	  generic_steppings },
    392 	{ CPU_ID_MV88SV131,	CPU_CLASS_ARM9ES,	"Sheeva 88SV131",
    393 	  generic_steppings },
    394 	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_ARM9ES,	"Sheeva 88FR571-vd",
    395 	  generic_steppings },
    396 
    397 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
    398 	  generic_steppings },
    399 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
    400 	  generic_steppings },
    401 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
    402 	  generic_steppings },
    403 
    404 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
    405 	  sa110_steppings },
    406 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
    407 	  sa1100_steppings },
    408 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
    409 	  sa1110_steppings },
    410 
    411 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
    412 	  ixp12x0_steppings },
    413 
    414 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
    415 	  xscale_steppings },
    416 
    417 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    418 	  i80321_steppings },
    419 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    420 	  i80321_steppings },
    421 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    422 	  i80321_steppings },
    423 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    424 	  i80321_steppings },
    425 
    426 	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
    427 	  i80219_steppings },
    428 	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
    429 	  i80219_steppings },
    430 
    431 	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
    432 	  pxa27x_steppings },
    433 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
    434 	  pxa2x0_steppings },
    435 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
    436 	  pxa2x0_steppings },
    437 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
    438 	  pxa2x0_steppings },
    439 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
    440 	  pxa2x0_steppings },
    441 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
    442 	  pxa255_steppings },
    443 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
    444 	  pxa2x0_steppings },
    445 
    446 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
    447 	  ixp425_steppings },
    448 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
    449 	  ixp425_steppings },
    450 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
    451 	  ixp425_steppings },
    452 
    453 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S r0",
    454 	  pN_steppings },
    455 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S r1",
    456 	  pN_steppings },
    457 #if 0
    458 	/* The ARM1156T2-S only has a memory protection unit */
    459 	{ CPU_ID_ARM1156T2S,	CPU_CLASS_ARM11J,	"ARM1156T2-S r0",
    460 	  pN_steppings },
    461 #endif
    462 	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S r0",
    463 	  pN_steppings },
    464 
    465 	{ CPU_ID_ARM11MPCORE,	CPU_CLASS_ARM11J, 	"ARM11 MPCore",
    466 	  generic_steppings },
    467 
    468 	{ CPU_ID_CORTEXA5R0,	CPU_CLASS_CORTEX,	"Cortex-A5 r0",
    469 	  pN_steppings },
    470 	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEX,	"Cortex-A8 r1",
    471 	  pN_steppings },
    472 	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEX,	"Cortex-A8 r2",
    473 	  pN_steppings },
    474 	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEX,	"Cortex-A8 r3",
    475 	  pN_steppings },
    476 	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEX,	"Cortex-A9 r2",
    477 	  pN_steppings },
    478 	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEX,	"Cortex-A9 r3",
    479 	  pN_steppings },
    480 	{ CPU_ID_CORTEXA9R4,	CPU_CLASS_CORTEX,	"Cortex-A9 r4",
    481 	  pN_steppings },
    482 	{ CPU_ID_CORTEXA15R2,	CPU_CLASS_CORTEX,	"Cortex-A15 r2",
    483 	  pN_steppings },
    484 	{ CPU_ID_CORTEXA15R3,	CPU_CLASS_CORTEX,	"Cortex-A15 r3",
    485 	  pN_steppings },
    486 
    487 	{ CPU_ID_FA526,		CPU_CLASS_ARMV4,	"FA526",
    488 	  generic_steppings },
    489 
    490 	{ 0, CPU_CLASS_NONE, NULL, NULL }
    491 };
    492 
    493 struct cpu_classtab {
    494 	const char	*class_name;
    495 	const char	*class_option;
    496 };
    497 
    498 const struct cpu_classtab cpu_classes[] = {
    499 	[CPU_CLASS_NONE] =	{ "unknown",	NULL },
    500 	[CPU_CLASS_ARM2] =	{ "ARM2",	"CPU_ARM2" },
    501 	[CPU_CLASS_ARM2AS] =	{ "ARM2as",	"CPU_ARM250" },
    502 	[CPU_CLASS_ARM3] =	{ "ARM3",	"CPU_ARM3" },
    503 	[CPU_CLASS_ARM6] =	{ "ARM6",	"CPU_ARM6" },
    504 	[CPU_CLASS_ARM7] =	{ "ARM7",	"CPU_ARM7" },
    505 	[CPU_CLASS_ARM7TDMI] =	{ "ARM7TDMI",	"CPU_ARM7TDMI" },
    506 	[CPU_CLASS_ARM8] =	{ "ARM8",	"CPU_ARM8" },
    507 	[CPU_CLASS_ARM9TDMI] =	{ "ARM9TDMI",	NULL },
    508 	[CPU_CLASS_ARM9ES] =	{ "ARM9E-S",	"CPU_ARM9E" },
    509 	[CPU_CLASS_ARM9EJS] =	{ "ARM9EJ-S",	"CPU_ARM9E" },
    510 	[CPU_CLASS_ARM10E] =	{ "ARM10E",	"CPU_ARM10" },
    511 	[CPU_CLASS_ARM10EJ] =	{ "ARM10EJ",	"CPU_ARM10" },
    512 	[CPU_CLASS_SA1] =	{ "SA-1",	"CPU_SA110" },
    513 	[CPU_CLASS_XSCALE] =	{ "XScale",	"CPU_XSCALE_..." },
    514 	[CPU_CLASS_ARM11J] =	{ "ARM11J",	"CPU_ARM11" },
    515 	[CPU_CLASS_ARMV4] =	{ "ARMv4",	"CPU_ARMV4" },
    516 	[CPU_CLASS_CORTEX] =	{ "Cortex",	"CPU_CORTEX" },
    517 };
    518 
    519 /*
    520  * Report the type of the specified arm processor. This uses the generic and
    521  * arm specific information in the CPU structure to identify the processor.
    522  * The remaining fields in the CPU structure are filled in appropriately.
    523  */
    524 
    525 static const char * const wtnames[] = {
    526 	"write-through",
    527 	"write-back",
    528 	"write-back",
    529 	"**unknown 3**",
    530 	"**unknown 4**",
    531 	"write-back-locking",		/* XXX XScale-specific? */
    532 	"write-back-locking-A",
    533 	"write-back-locking-B",
    534 	"**unknown 8**",
    535 	"**unknown 9**",
    536 	"**unknown 10**",
    537 	"**unknown 11**",
    538 	"**unknown 12**",
    539 	"**unknown 13**",
    540 	"write-back-locking-C",
    541 	"**unknown 15**",
    542 };
    543 
    544 void
    545 identify_arm_cpu(device_t dv, struct cpu_info *ci)
    546 {
    547 	enum cpu_class cpu_class = CPU_CLASS_NONE;
    548 	const u_int cpuid = ci->ci_arm_cpuid;
    549 	const char * const xname = device_xname(dv);
    550 	const char *steppingstr;
    551 	int i;
    552 
    553 	if (cpuid == 0) {
    554 		aprint_error("Processor failed probe - no CPU ID\n");
    555 		return;
    556 	}
    557 
    558 	for (i = 0; cpuids[i].cpuid != 0; i++)
    559 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
    560 			cpu_class = cpuids[i].cpu_class;
    561 			steppingstr = cpuids[i].cpu_steppings[cpuid &
    562 			    CPU_ID_REVISION_MASK],
    563 			sprintf(cpu_model, "%s%s%s (%s core)",
    564 			    cpuids[i].cpu_classname,
    565 			    steppingstr[0] == '*' ? "" : " ",
    566 			    &steppingstr[steppingstr[0] == '*'],
    567 			    cpu_classes[cpu_class].class_name);
    568 			break;
    569 		}
    570 
    571 	if (cpuids[i].cpuid == 0)
    572 		sprintf(cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
    573 
    574 	if (ci->ci_data.cpu_cc_freq != 0) {
    575 		char freqbuf[8];
    576 		humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq,
    577 		    "Hz", 1000);
    578 
    579 		aprint_naive(": %s %s\n", freqbuf, cpu_model);
    580 		aprint_normal(": %s %s\n", freqbuf, cpu_model);
    581 	} else {
    582 		aprint_naive(": %s\n", cpu_model);
    583 		aprint_normal(": %s\n", cpu_model);
    584 	}
    585 
    586 	aprint_normal("%s:", xname);
    587 
    588 	switch (cpu_class) {
    589 	case CPU_CLASS_ARM6:
    590 	case CPU_CLASS_ARM7:
    591 	case CPU_CLASS_ARM7TDMI:
    592 	case CPU_CLASS_ARM8:
    593 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
    594 			aprint_normal(" IDC disabled");
    595 		else
    596 			aprint_normal(" IDC enabled");
    597 		break;
    598 	case CPU_CLASS_ARM9TDMI:
    599 	case CPU_CLASS_ARM9ES:
    600 	case CPU_CLASS_ARM9EJS:
    601 	case CPU_CLASS_ARM10E:
    602 	case CPU_CLASS_ARM10EJ:
    603 	case CPU_CLASS_SA1:
    604 	case CPU_CLASS_XSCALE:
    605 	case CPU_CLASS_ARM11J:
    606 	case CPU_CLASS_ARMV4:
    607 	case CPU_CLASS_CORTEX:
    608 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
    609 			aprint_normal(" DC disabled");
    610 		else
    611 			aprint_normal(" DC enabled");
    612 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
    613 			aprint_normal(" IC disabled");
    614 		else
    615 			aprint_normal(" IC enabled");
    616 		break;
    617 	default:
    618 		break;
    619 	}
    620 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
    621 		aprint_normal(" WB disabled");
    622 	else
    623 		aprint_normal(" WB enabled");
    624 
    625 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
    626 		aprint_normal(" LABT");
    627 	else
    628 		aprint_normal(" EABT");
    629 
    630 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
    631 		aprint_normal(" branch prediction enabled");
    632 
    633 	aprint_normal("\n");
    634 
    635 #ifdef CPU_CORTEX
    636 	if (CPU_ID_CORTEX_P(cpuid)) {
    637 		identify_cortex_caches(dv);
    638 		if (0)
    639 			identify_features(dv);
    640 	} else
    641 #endif
    642 	/* Print cache info. */
    643 	if (arm_picache_line_size != 0 || arm_pdcache_line_size != 0) {
    644 
    645 		if (arm_pcache_unified) {
    646 			aprint_normal_dev(dv, "%dKB/%dB %d-way %s unified cache\n",
    647 			    arm_pdcache_size / 1024,
    648 			    arm_pdcache_line_size, arm_pdcache_ways,
    649 			    wtnames[arm_pcache_type]);
    650 		} else {
    651 			aprint_normal_dev(dv, "%dKB/%dB %d-way Instruction cache\n",
    652 			    arm_picache_size / 1024,
    653 			    arm_picache_line_size, arm_picache_ways);
    654 			aprint_normal_dev(dv, "%dKB/%dB %d-way %s Data cache\n",
    655 			    arm_pdcache_size / 1024,
    656 			    arm_pdcache_line_size, arm_pdcache_ways,
    657 			    wtnames[arm_pcache_type]);
    658 		}
    659 
    660 	}
    661 
    662 
    663 	switch (cpu_class) {
    664 #ifdef CPU_ARM2
    665 	case CPU_CLASS_ARM2:
    666 #endif
    667 #ifdef CPU_ARM250
    668 	case CPU_CLASS_ARM2AS:
    669 #endif
    670 #ifdef CPU_ARM3
    671 	case CPU_CLASS_ARM3:
    672 #endif
    673 #ifdef CPU_ARM6
    674 	case CPU_CLASS_ARM6:
    675 #endif
    676 #ifdef CPU_ARM7
    677 	case CPU_CLASS_ARM7:
    678 #endif
    679 #ifdef CPU_ARM7TDMI
    680 	case CPU_CLASS_ARM7TDMI:
    681 #endif
    682 #ifdef CPU_ARM8
    683 	case CPU_CLASS_ARM8:
    684 #endif
    685 #ifdef CPU_ARM9
    686 	case CPU_CLASS_ARM9TDMI:
    687 #endif
    688 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
    689 	case CPU_CLASS_ARM9ES:
    690 	case CPU_CLASS_ARM9EJS:
    691 #endif
    692 #ifdef CPU_ARM10
    693 	case CPU_CLASS_ARM10E:
    694 	case CPU_CLASS_ARM10EJ:
    695 #endif
    696 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
    697     defined(CPU_SA1110) || defined(CPU_IXP12X0)
    698 	case CPU_CLASS_SA1:
    699 #endif
    700 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
    701     defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
    702 	case CPU_CLASS_XSCALE:
    703 #endif
    704 #if defined(CPU_ARM11)
    705 	case CPU_CLASS_ARM11J:
    706 #endif
    707 #if defined(CPU_CORTEX)
    708 	case CPU_CLASS_CORTEX:
    709 #endif
    710 #if defined(CPU_FA526)
    711 	case CPU_CLASS_ARMV4:
    712 #endif
    713 		break;
    714 	default:
    715 		if (cpu_classes[cpu_class].class_option == NULL) {
    716 			aprint_error_dev(dv, "%s does not fully support this CPU.\n",
    717 			     ostype);
    718 		} else {
    719 			aprint_error_dev(dv, "This kernel does not fully support "
    720 			       "this CPU.\n");
    721 			aprint_normal_dev(dv, "Recompile with \"options %s\" to "
    722 			       "correct this.\n", cpu_classes[cpu_class].class_option);
    723 		}
    724 		break;
    725 	}
    726 }
    727 
    728 #ifdef CPU_CORTEX
    729 static void
    730 print_cortex_cache(device_t dv, u_int level, const char *desc)
    731 {
    732 	uint32_t ccsidr = armreg_ccsidr_read();
    733 	u_int linesize = 1 << ((ccsidr & 7) + 4);
    734 	u_int nways = ((ccsidr >> 3) & 0x3ff) + 1;
    735 	u_int nsets = ((ccsidr >> 13) & 0x7fff) + 1;
    736 	u_int totalsize = linesize * nways * nsets;
    737 	static const char * const wstrings[] = {
    738 		"", " write-back", " write-through", ""
    739 	};
    740 	static const char * const astrings[] = {
    741 		"",
    742 		" with write allocate",
    743 		" with read allocate",
    744 		" with read and write allocate"
    745 	};
    746 
    747 	//aprint_debug_dev(dv, "ccsidr=%#x\n", ccsidr);
    748 
    749 	u_int wtype = (ccsidr >> 30) & 3;
    750 	u_int atype = (ccsidr >> 28) & 3;
    751 
    752 	aprint_normal_dev(dv, "%uKB/%uB %u-way%s L%u %s cache%s\n",
    753 	    totalsize / 1024, linesize, nways, wstrings[wtype], level + 1,
    754 	    desc, astrings[atype]);
    755 }
    756 
    757 void
    758 identify_cortex_caches(device_t dv)
    759 {
    760 	const uint32_t orig_csselr = armreg_csselr_read();
    761 	uint32_t clidr = armreg_clidr_read();
    762 	u_int level;
    763 
    764 	//aprint_debug_dev(dv, "clidr=%011o\n", clidr);
    765 
    766 	for (level = 0, clidr &= 077777777; clidr & 7; clidr >>= 3, level++) {
    767 		if (clidr & 1) {
    768 			armreg_csselr_write(2*level + 1);
    769 			print_cortex_cache(dv, level, "Instruction");
    770 		}
    771 		if (clidr & 6) {
    772 			armreg_csselr_write(2*level + 0);
    773 			print_cortex_cache(dv, level,
    774 			    (clidr & 4) ? "Unified" : "Data");
    775 		}
    776 	}
    777 
    778 	armreg_csselr_write(orig_csselr);
    779 
    780 
    781 }
    782 
    783 void
    784 identify_features(device_t dv)
    785 {
    786 	uint32_t isar0 = armreg_isar0_read();
    787 	uint32_t isar1 = armreg_isar1_read();
    788 	uint32_t isar2 = armreg_isar2_read();
    789 	uint32_t isar3 = armreg_isar3_read();
    790 	uint32_t isar4 = armreg_isar4_read();
    791 	uint32_t isar5 = armreg_isar5_read();
    792 
    793 	uint32_t mmfr0 = armreg_mmfr0_read();
    794 	uint32_t mmfr1 = armreg_mmfr1_read();
    795 	uint32_t mmfr2 = armreg_mmfr2_read();
    796 	uint32_t mmfr3 = armreg_mmfr3_read();
    797 
    798 	uint32_t pfr0 = armreg_pfr0_read();
    799 	uint32_t pfr1 = armreg_pfr1_read();
    800 
    801 	aprint_normal_dev(dv,
    802 	    "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n",
    803 	    isar0, isar1, isar2, isar3, isar4, isar5);
    804 	aprint_normal_dev(dv,
    805 	    "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n",
    806 	    mmfr0, mmfr1, mmfr2, mmfr3);
    807 	aprint_normal_dev(dv,
    808 	    "pfr: [0]=%#x [1]=%#x\n",
    809 	    pfr0, pfr1);
    810 }
    811 #endif /* CPU_CORTEX */
    812