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