Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.103
      1 /*	$NetBSD: cpu.c,v 1.103 2014/03/24 20:06:31 christos 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.103 2014/03/24 20:06:31 christos 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/locore.h>
     61 #include <arm/undefined.h>
     62 
     63 extern const char *cpu_arch;
     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[2]  __cacheline_aligned = { 0, 0 };
     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_getmodel());
    167 		aprint_normal(": %s\n", cpu_getmodel());
    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 	CPU_CLASS_PJ4B,
    230 };
    231 
    232 static const char * const generic_steppings[16] = {
    233 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
    234 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    235 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    236 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    237 };
    238 
    239 static const char * const pN_steppings[16] = {
    240 	"*p0",	"*p1",	"*p2",	"*p3",	"*p4",	"*p5",	"*p6",	"*p7",
    241 	"*p8",	"*p9",	"*p10",	"*p11",	"*p12",	"*p13",	"*p14",	"*p15",
    242 };
    243 
    244 static const char * const sa110_steppings[16] = {
    245 	"rev 0",	"step J",	"step K",	"step S",
    246 	"step T",	"rev 5",	"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 static const char * const sa1100_steppings[16] = {
    252 	"rev 0",	"step B",	"step C",	"rev 3",
    253 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    254 	"step D",	"step E",	"rev 10"	"step G",
    255 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    256 };
    257 
    258 static const char * const sa1110_steppings[16] = {
    259 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    260 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
    261 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
    262 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    263 };
    264 
    265 static const char * const ixp12x0_steppings[16] = {
    266 	"(IXP1200 step A)",		"(IXP1200 step B)",
    267 	"rev 2",			"(IXP1200 step C)",
    268 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
    269 	"(IXP1240 step B)",		"(IXP1250 step B)",
    270 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    271 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    272 };
    273 
    274 static const char * const xscale_steppings[16] = {
    275 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
    276 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
    277 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    278 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    279 };
    280 
    281 static const char * const i80321_steppings[16] = {
    282 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
    283 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    284 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    285 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    286 };
    287 
    288 static const char * const i80219_steppings[16] = {
    289 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    290 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    291 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    292 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    293 };
    294 
    295 /* Steppings for PXA2[15]0 */
    296 static const char * const pxa2x0_steppings[16] = {
    297 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    298 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
    299 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    300 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    301 };
    302 
    303 /* Steppings for PXA255/26x.
    304  * rev 5: PXA26x B0, rev 6: PXA255 A0
    305  */
    306 static const char * const pxa255_steppings[16] = {
    307 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
    308 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
    309 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    310 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    311 };
    312 
    313 /* Stepping for PXA27x */
    314 static const char * const pxa27x_steppings[16] = {
    315 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    316 	"step C-0",	"rev 5",	"rev 6",	"rev 7",
    317 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    318 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    319 };
    320 
    321 static const char * const ixp425_steppings[16] = {
    322 	"step 0",	"rev 1",	"rev 2",	"rev 3",
    323 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    324 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    325 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    326 };
    327 
    328 struct cpuidtab {
    329 	uint32_t	cpuid;
    330 	enum		cpu_class cpu_class;
    331 	const char	*cpu_classname;
    332 	const char * const *cpu_steppings;
    333 	char		cpu_arch[8];
    334 };
    335 
    336 const struct cpuidtab cpuids[] = {
    337 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
    338 	  generic_steppings, "2" },
    339 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
    340 	  generic_steppings, "2" },
    341 
    342 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
    343 	  generic_steppings, "2A" },
    344 
    345 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
    346 	  generic_steppings, "3" },
    347 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
    348 	  generic_steppings, "3" },
    349 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
    350 	  generic_steppings, "3" },
    351 
    352 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
    353 	  generic_steppings, "3" },
    354 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
    355 	  generic_steppings, "3" },
    356 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
    357 	  generic_steppings, "3" },
    358 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
    359 	  generic_steppings, "3" },
    360 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
    361 	  generic_steppings, "3" },
    362 
    363 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
    364 	  generic_steppings, "4" },
    365 
    366 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
    367 	  sa110_steppings, "4" },
    368 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
    369 	  sa1100_steppings, "4" },
    370 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
    371 	  sa1110_steppings, "4" },
    372 
    373 	{ CPU_ID_FA526,		CPU_CLASS_ARMV4,	"FA526",
    374 	  generic_steppings, "4" },
    375 
    376 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
    377 	  ixp12x0_steppings, "4" },
    378 
    379 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
    380 	  generic_steppings, "4T" },
    381 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
    382 	  generic_steppings, "4T" },
    383 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
    384 	  generic_steppings, "4T" },
    385 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
    386 	  generic_steppings, "4T" },
    387 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
    388 	  generic_steppings, "4T" },
    389 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
    390 	  generic_steppings, "4T" },
    391 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
    392 	  generic_steppings, "4T" },
    393 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
    394 	  generic_steppings, "4T" },
    395 
    396 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
    397 	  generic_steppings, "5TE" },
    398 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    399 	  generic_steppings, "5TE" },
    400 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    401 	  generic_steppings, "5TE" },
    402 	{ CPU_ID_MV88SV131,	CPU_CLASS_ARM9ES,	"Sheeva 88SV131",
    403 	  generic_steppings, "5TE" },
    404 	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_ARM9ES,	"Sheeva 88FR571-vd",
    405 	  generic_steppings, "5TE" },
    406 
    407 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
    408 	  xscale_steppings, "5TE" },
    409 
    410 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    411 	  i80321_steppings, "5TE" },
    412 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    413 	  i80321_steppings, "5TE" },
    414 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    415 	  i80321_steppings, "5TE" },
    416 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    417 	  i80321_steppings, "5TE" },
    418 
    419 	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
    420 	  i80219_steppings, "5TE" },
    421 	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
    422 	  i80219_steppings, "5TE" },
    423 
    424 	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
    425 	  pxa27x_steppings, "5TE" },
    426 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
    427 	  pxa2x0_steppings, "5TE" },
    428 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
    429 	  pxa2x0_steppings, "5TE" },
    430 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
    431 	  pxa2x0_steppings, "5TE" },
    432 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
    433 	  pxa2x0_steppings, "5TE" },
    434 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
    435 	  pxa255_steppings, "5TE" },
    436 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
    437 	  pxa2x0_steppings, "5TE" },
    438 
    439 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
    440 	  ixp425_steppings, "5TE" },
    441 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
    442 	  ixp425_steppings, "5TE" },
    443 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
    444 	  ixp425_steppings, "5TE" },
    445 
    446 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
    447 	  generic_steppings, "5TE" },
    448 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
    449 	  generic_steppings, "5TE" },
    450 
    451 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
    452 	  generic_steppings, "5TEJ" },
    453 	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
    454 	  generic_steppings, "5TEJ" },
    455 
    456 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S r0",
    457 	  pN_steppings, "6J" },
    458 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S r1",
    459 	  pN_steppings, "6J" },
    460 #if 0
    461 	/* The ARM1156T2-S only has a memory protection unit */
    462 	{ CPU_ID_ARM1156T2S,	CPU_CLASS_ARM11J,	"ARM1156T2-S r0",
    463 	  pN_steppings, "6T2" },
    464 #endif
    465 	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S r0",
    466 	  pN_steppings, "6ZK" },
    467 
    468 	{ CPU_ID_ARM11MPCORE,	CPU_CLASS_ARM11J, 	"ARM11 MPCore",
    469 	  generic_steppings, "6K" },
    470 
    471 	{ CPU_ID_CORTEXA5R0,	CPU_CLASS_CORTEX,	"Cortex-A5 r0",
    472 	  pN_steppings, "7A" },
    473 	{ CPU_ID_CORTEXA7R0,	CPU_CLASS_CORTEX,	"Cortex-A7 r0",
    474 	  pN_steppings, "7A" },
    475 	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEX,	"Cortex-A8 r1",
    476 	  pN_steppings, "7A" },
    477 	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEX,	"Cortex-A8 r2",
    478 	  pN_steppings, "7A" },
    479 	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEX,	"Cortex-A8 r3",
    480 	  pN_steppings, "7A" },
    481 	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEX,	"Cortex-A9 r2",
    482 	  pN_steppings, "7A" },
    483 	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEX,	"Cortex-A9 r3",
    484 	  pN_steppings, "7A" },
    485 	{ CPU_ID_CORTEXA9R4,	CPU_CLASS_CORTEX,	"Cortex-A9 r4",
    486 	  pN_steppings, "7A" },
    487 	{ CPU_ID_CORTEXA15R2,	CPU_CLASS_CORTEX,	"Cortex-A15 r2",
    488 	  pN_steppings, "7A" },
    489 	{ CPU_ID_CORTEXA15R3,	CPU_CLASS_CORTEX,	"Cortex-A15 r3",
    490 	  pN_steppings, "7A" },
    491 
    492 	{ CPU_ID_MV88SV581X_V6, CPU_CLASS_PJ4B,      "Sheeva 88SV581x",
    493 	  generic_steppings },
    494 	{ CPU_ID_ARM_88SV581X_V6, CPU_CLASS_PJ4B,    "Sheeva 88SV581x",
    495 	  generic_steppings },
    496 	{ CPU_ID_MV88SV581X_V7, CPU_CLASS_PJ4B,      "Sheeva 88SV581x",
    497 	  generic_steppings },
    498 	{ CPU_ID_ARM_88SV581X_V7, CPU_CLASS_PJ4B,    "Sheeva 88SV581x",
    499 	  generic_steppings },
    500 	{ CPU_ID_MV88SV584X_V6, CPU_CLASS_PJ4B,      "Sheeva 88SV584x",
    501 	  generic_steppings },
    502 	{ CPU_ID_ARM_88SV584X_V6, CPU_CLASS_PJ4B,    "Sheeva 88SV584x",
    503 	  generic_steppings },
    504 	{ CPU_ID_MV88SV584X_V7, CPU_CLASS_PJ4B,      "Sheeva 88SV584x",
    505 	  generic_steppings },
    506 
    507 
    508 	{ 0, CPU_CLASS_NONE, NULL, NULL, "" }
    509 };
    510 
    511 struct cpu_classtab {
    512 	const char	*class_name;
    513 	const char	*class_option;
    514 };
    515 
    516 const struct cpu_classtab cpu_classes[] = {
    517 	[CPU_CLASS_NONE] =	{ "unknown",	NULL },
    518 	[CPU_CLASS_ARM2] =	{ "ARM2",	"CPU_ARM2" },
    519 	[CPU_CLASS_ARM2AS] =	{ "ARM2as",	"CPU_ARM250" },
    520 	[CPU_CLASS_ARM3] =	{ "ARM3",	"CPU_ARM3" },
    521 	[CPU_CLASS_ARM6] =	{ "ARM6",	"CPU_ARM6" },
    522 	[CPU_CLASS_ARM7] =	{ "ARM7",	"CPU_ARM7" },
    523 	[CPU_CLASS_ARM7TDMI] =	{ "ARM7TDMI",	"CPU_ARM7TDMI" },
    524 	[CPU_CLASS_ARM8] =	{ "ARM8",	"CPU_ARM8" },
    525 	[CPU_CLASS_ARM9TDMI] =	{ "ARM9TDMI",	NULL },
    526 	[CPU_CLASS_ARM9ES] =	{ "ARM9E-S",	"CPU_ARM9E" },
    527 	[CPU_CLASS_ARM9EJS] =	{ "ARM9EJ-S",	"CPU_ARM9E" },
    528 	[CPU_CLASS_ARM10E] =	{ "ARM10E",	"CPU_ARM10" },
    529 	[CPU_CLASS_ARM10EJ] =	{ "ARM10EJ",	"CPU_ARM10" },
    530 	[CPU_CLASS_SA1] =	{ "SA-1",	"CPU_SA110" },
    531 	[CPU_CLASS_XSCALE] =	{ "XScale",	"CPU_XSCALE_..." },
    532 	[CPU_CLASS_ARM11J] =	{ "ARM11J",	"CPU_ARM11" },
    533 	[CPU_CLASS_ARMV4] =	{ "ARMv4",	"CPU_ARMV4" },
    534 	[CPU_CLASS_CORTEX] =	{ "Cortex",	"CPU_CORTEX" },
    535 	[CPU_CLASS_PJ4B] =	{ "Marvell",	"CPU_PJ4B" },
    536 };
    537 
    538 /*
    539  * Report the type of the specified arm processor. This uses the generic and
    540  * arm specific information in the CPU structure to identify the processor.
    541  * The remaining fields in the CPU structure are filled in appropriately.
    542  */
    543 
    544 static const char * const wtnames[] = {
    545 	"write-through",
    546 	"write-back",
    547 	"write-back",
    548 	"**unknown 3**",
    549 	"**unknown 4**",
    550 	"write-back-locking",		/* XXX XScale-specific? */
    551 	"write-back-locking-A",
    552 	"write-back-locking-B",
    553 	"**unknown 8**",
    554 	"**unknown 9**",
    555 	"**unknown 10**",
    556 	"**unknown 11**",
    557 	"**unknown 12**",
    558 	"write-back-locking-line",
    559 	"write-back-locking-C",
    560 	"write-back-locking-D",
    561 };
    562 
    563 static void
    564 print_cache_info(device_t dv, struct arm_cache_info *info, u_int level)
    565 {
    566 	if (info->cache_unified) {
    567 		aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Unified cache\n",
    568 		    info->dcache_size / 1024,
    569 		    info->dcache_line_size, info->dcache_ways,
    570 		    wtnames[info->cache_type], level + 1,
    571 		    info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    572 		    info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    573 	} else {
    574 		aprint_normal_dev(dv, "%dKB/%dB %d-way L%u %cI%cT Instruction cache\n",
    575 		    info->icache_size / 1024,
    576 		    info->icache_line_size, info->icache_ways, level + 1,
    577 		    info->icache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    578 		    info->icache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    579 		aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Data cache\n",
    580 		    info->dcache_size / 1024,
    581 		    info->dcache_line_size, info->dcache_ways,
    582 		    wtnames[info->cache_type], level + 1,
    583 		    info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    584 		    info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    585 	}
    586 }
    587 
    588 void
    589 identify_arm_cpu(device_t dv, struct cpu_info *ci)
    590 {
    591 	enum cpu_class cpu_class = CPU_CLASS_NONE;
    592 	const u_int cpuid = ci->ci_arm_cpuid;
    593 	const char * const xname = device_xname(dv);
    594 	const char *steppingstr;
    595 	int i;
    596 
    597 	if (cpuid == 0) {
    598 		aprint_error("Processor failed probe - no CPU ID\n");
    599 		return;
    600 	}
    601 
    602 	for (i = 0; cpuids[i].cpuid != 0; i++)
    603 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
    604 			cpu_class = cpuids[i].cpu_class;
    605 			cpu_arch = cpuids[i].cpu_arch;
    606 			steppingstr = cpuids[i].cpu_steppings[cpuid &
    607 			    CPU_ID_REVISION_MASK];
    608 			cpu_setmodel("%s%s%s (%s V%s core)",
    609 			    cpuids[i].cpu_classname,
    610 			    steppingstr[0] == '*' ? "" : " ",
    611 			    &steppingstr[steppingstr[0] == '*'],
    612 			    cpu_classes[cpu_class].class_name,
    613 			    cpu_arch);
    614 			break;
    615 		}
    616 
    617 	if (cpuids[i].cpuid == 0)
    618 		cpu_setmodel("unknown CPU (ID = 0x%x)", cpuid);
    619 
    620 	if (ci->ci_data.cpu_cc_freq != 0) {
    621 		char freqbuf[8];
    622 		humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq,
    623 		    "Hz", 1000);
    624 
    625 		aprint_naive(": %s %s\n", freqbuf, cpu_getmodel());
    626 		aprint_normal(": %s %s\n", freqbuf, cpu_getmodel());
    627 	} else {
    628 		aprint_naive(": %s\n", cpu_getmodel());
    629 		aprint_normal(": %s\n", cpu_getmodel());
    630 	}
    631 
    632 	aprint_normal("%s:", xname);
    633 
    634 	switch (cpu_class) {
    635 	case CPU_CLASS_ARM6:
    636 	case CPU_CLASS_ARM7:
    637 	case CPU_CLASS_ARM7TDMI:
    638 	case CPU_CLASS_ARM8:
    639 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
    640 			aprint_normal(" IDC disabled");
    641 		else
    642 			aprint_normal(" IDC enabled");
    643 		break;
    644 	case CPU_CLASS_ARM9TDMI:
    645 	case CPU_CLASS_ARM9ES:
    646 	case CPU_CLASS_ARM9EJS:
    647 	case CPU_CLASS_ARM10E:
    648 	case CPU_CLASS_ARM10EJ:
    649 	case CPU_CLASS_SA1:
    650 	case CPU_CLASS_XSCALE:
    651 	case CPU_CLASS_ARM11J:
    652 	case CPU_CLASS_ARMV4:
    653 	case CPU_CLASS_CORTEX:
    654 	case CPU_CLASS_PJ4B:
    655 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
    656 			aprint_normal(" DC disabled");
    657 		else
    658 			aprint_normal(" DC enabled");
    659 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
    660 			aprint_normal(" IC disabled");
    661 		else
    662 			aprint_normal(" IC enabled");
    663 		break;
    664 	default:
    665 		break;
    666 	}
    667 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
    668 		aprint_normal(" WB disabled");
    669 	else
    670 		aprint_normal(" WB enabled");
    671 
    672 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
    673 		aprint_normal(" LABT");
    674 	else
    675 		aprint_normal(" EABT");
    676 
    677 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
    678 		aprint_normal(" branch prediction enabled");
    679 
    680 	aprint_normal("\n");
    681 
    682 	if (CPU_ID_CORTEX_P(cpuid) || CPU_ID_ARM11_P(cpuid) || CPU_ID_MV88SV58XX_P(cpuid)) {
    683 		identify_features(dv);
    684 	}
    685 
    686 	/* Print cache info. */
    687 	if (arm_pcache.icache_line_size != 0 || arm_pcache.dcache_line_size != 0) {
    688 		print_cache_info(dv, &arm_pcache, 0);
    689 	}
    690 	if (arm_scache.icache_line_size != 0 || arm_scache.dcache_line_size != 0) {
    691 		print_cache_info(dv, &arm_scache, 1);
    692 	}
    693 
    694 
    695 	switch (cpu_class) {
    696 #ifdef CPU_ARM2
    697 	case CPU_CLASS_ARM2:
    698 #endif
    699 #ifdef CPU_ARM250
    700 	case CPU_CLASS_ARM2AS:
    701 #endif
    702 #ifdef CPU_ARM3
    703 	case CPU_CLASS_ARM3:
    704 #endif
    705 #ifdef CPU_ARM6
    706 	case CPU_CLASS_ARM6:
    707 #endif
    708 #ifdef CPU_ARM7
    709 	case CPU_CLASS_ARM7:
    710 #endif
    711 #ifdef CPU_ARM7TDMI
    712 	case CPU_CLASS_ARM7TDMI:
    713 #endif
    714 #ifdef CPU_ARM8
    715 	case CPU_CLASS_ARM8:
    716 #endif
    717 #ifdef CPU_ARM9
    718 	case CPU_CLASS_ARM9TDMI:
    719 #endif
    720 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
    721 	case CPU_CLASS_ARM9ES:
    722 	case CPU_CLASS_ARM9EJS:
    723 #endif
    724 #ifdef CPU_ARM10
    725 	case CPU_CLASS_ARM10E:
    726 	case CPU_CLASS_ARM10EJ:
    727 #endif
    728 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
    729     defined(CPU_SA1110) || defined(CPU_IXP12X0)
    730 	case CPU_CLASS_SA1:
    731 #endif
    732 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
    733     defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
    734 	case CPU_CLASS_XSCALE:
    735 #endif
    736 #if defined(CPU_ARM11)
    737 	case CPU_CLASS_ARM11J:
    738 #endif
    739 #if defined(CPU_CORTEX)
    740 	case CPU_CLASS_CORTEX:
    741 #endif
    742 #if defined(CPU_PJ4B)
    743 	case CPU_CLASS_PJ4B:
    744 #endif
    745 #if defined(CPU_FA526)
    746 	case CPU_CLASS_ARMV4:
    747 #endif
    748 		break;
    749 	default:
    750 		if (cpu_classes[cpu_class].class_option == NULL) {
    751 			aprint_error_dev(dv, "%s does not fully support this CPU.\n",
    752 			     ostype);
    753 		} else {
    754 			aprint_error_dev(dv, "This kernel does not fully support "
    755 			       "this CPU.\n");
    756 			aprint_normal_dev(dv, "Recompile with \"options %s\" to "
    757 			       "correct this.\n", cpu_classes[cpu_class].class_option);
    758 		}
    759 		break;
    760 	}
    761 }
    762 
    763 extern int cpu_instruction_set_attributes[6];
    764 extern int cpu_memory_model_features[4];
    765 extern int cpu_processor_features[2];
    766 extern int cpu_simd_present;
    767 extern int cpu_simdex_present;
    768 
    769 void
    770 identify_features(device_t dv)
    771 {
    772 	cpu_instruction_set_attributes[0] = armreg_isar0_read();
    773 	cpu_instruction_set_attributes[1] = armreg_isar1_read();
    774 	cpu_instruction_set_attributes[2] = armreg_isar2_read();
    775 	cpu_instruction_set_attributes[3] = armreg_isar3_read();
    776 	cpu_instruction_set_attributes[4] = armreg_isar4_read();
    777 	cpu_instruction_set_attributes[5] = armreg_isar5_read();
    778 
    779 	cpu_hwdiv_present =
    780 	    ((cpu_instruction_set_attributes[0] >> 24) & 0x0f) >= 2;
    781 	cpu_simd_present =
    782 	    ((cpu_instruction_set_attributes[3] >> 4) & 0x0f) >= 3;
    783 	cpu_simdex_present = cpu_simd_present
    784 	    && ((cpu_instruction_set_attributes[1] >> 12) & 0x0f) >= 2;
    785 	cpu_synchprim_present =
    786 	    ((cpu_instruction_set_attributes[3] >> 8) & 0xf0)
    787 	    | ((cpu_instruction_set_attributes[4] >> 20) & 0x0f);
    788 
    789 	cpu_memory_model_features[0] = armreg_mmfr0_read();
    790 	cpu_memory_model_features[1] = armreg_mmfr1_read();
    791 	cpu_memory_model_features[2] = armreg_mmfr2_read();
    792 	cpu_memory_model_features[3] = armreg_mmfr3_read();
    793 
    794 	if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) {
    795 		/*
    796 		 * Updates to the translation tables do not require a clean
    797 		 * to the point of unification to ensure visibility by
    798 		 * subsequent translation table walks.
    799 		 */
    800 		pmap_needs_pte_sync = 0;
    801 	}
    802 
    803 	cpu_processor_features[0] = armreg_pfr0_read();
    804 	cpu_processor_features[1] = armreg_pfr1_read();
    805 
    806 	aprint_verbose_dev(dv,
    807 	    "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n",
    808 	    cpu_instruction_set_attributes[0],
    809 	    cpu_instruction_set_attributes[1],
    810 	    cpu_instruction_set_attributes[2],
    811 	    cpu_instruction_set_attributes[3],
    812 	    cpu_instruction_set_attributes[4],
    813 	    cpu_instruction_set_attributes[5]);
    814 	aprint_verbose_dev(dv,
    815 	    "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n",
    816 	    cpu_memory_model_features[0], cpu_memory_model_features[1],
    817 	    cpu_memory_model_features[2], cpu_memory_model_features[3]);
    818 	aprint_verbose_dev(dv,
    819 	    "pfr: [0]=%#x [1]=%#x\n",
    820 	    cpu_processor_features[0], cpu_processor_features[1]);
    821 }
    822