1 /*	$NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz 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 <sys/cdefs.h>
45 __FBSDID("$FreeBSD: stable/10/sys/arm/arm/identcpu.c 278626 2015-02-12 17:01:54Z ian $");
46 #include <sys/systm.h>
47 #include <sys/param.h>
48 #include <sys/malloc.h>
49 #include <sys/time.h>
50 #include <sys/proc.h>
51 #include <sys/conf.h>
52 #include <sys/kernel.h>
53 #include <sys/sysctl.h>
54 #include <machine/cpu.h>
55 #include <machine/endian.h>
56 
57 #include <machine/cpuconf.h>
58 #include <machine/md_var.h>
59 
60 char machine[] = "arm";
61 
62 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
63 	machine, 0, "Machine class");
64 
65 static const char * const generic_steppings[16] = {
66 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
67 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
68 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
69 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
70 };
71 
72 static const char * const xscale_steppings[16] = {
73 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
74 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
75 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
76 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
77 };
78 
79 static const char * const i80219_steppings[16] = {
80 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
81 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
82 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
83 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
84 };
85 
86 static const char * const i80321_steppings[16] = {
87 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
88 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
89 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
90 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
91 };
92 
93 static const char * const i81342_steppings[16] = {
94 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
95 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
96 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
97 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
98 };
99 
100 /* Steppings for PXA2[15]0 */
101 static const char * const pxa2x0_steppings[16] = {
102 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
103 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
104 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
105 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
106 };
107 
108 /* Steppings for PXA255/26x.
109  * rev 5: PXA26x B0, rev 6: PXA255 A0
110  */
111 static const char * const pxa255_steppings[16] = {
112 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
113 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
114 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
115 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
116 };
117 
118 /* Stepping for PXA27x */
119 static const char * const pxa27x_steppings[16] = {
120 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
121 	"step C-0",	"rev 5",	"rev 6",	"rev 7",
122 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
123 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
124 };
125 
126 static const char * const ixp425_steppings[16] = {
127 	"step 0 (A0)",	"rev 1 (ARMv5TE)", "rev 2",	"rev 3",
128 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
129 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
130 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
131 };
132 
133 struct cpuidtab {
134 	u_int32_t	cpuid;
135 	enum		cpu_class cpu_class;
136 	const char	*cpu_name;
137 	const char * const *cpu_steppings;
138 };
139 
140 const struct cpuidtab cpuids[] = {
141 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
142 	  generic_steppings },
143 	{ CPU_ID_ARM920T_ALT,	CPU_CLASS_ARM9TDMI,	"ARM920T",
144 	  generic_steppings },
145 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
146 	  generic_steppings },
147 	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
148 	  generic_steppings },
149 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
150 	  generic_steppings },
151 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
152 	  generic_steppings },
153 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
154 	  generic_steppings },
155 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
156 	  generic_steppings },
157 	{ CPU_ID_FA526,		CPU_CLASS_ARM9TDMI,	"FA526",
158 	  generic_steppings },
159 	{ CPU_ID_FA626TE,	CPU_CLASS_ARM9ES,	"FA626TE",
160 	  generic_steppings },
161 
162 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
163 	  generic_steppings },
164 
165 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
166 	  generic_steppings },
167 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
168 	  generic_steppings },
169 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
170 	  generic_steppings },
171 
172 	{ CPU_ID_CORTEXA7,	CPU_CLASS_CORTEXA,	"Cortex A7",
173 	  generic_steppings },
174 	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEXA,	"Cortex A8-r1",
175 	  generic_steppings },
176 	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEXA,	"Cortex A8-r2",
177 	  generic_steppings },
178 	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEXA,	"Cortex A8-r3",
179 	  generic_steppings },
180 	{ CPU_ID_CORTEXA9R1,	CPU_CLASS_CORTEXA,	"Cortex A9-r1",
181 	  generic_steppings },
182 	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEXA,	"Cortex A9-r2",
183 	  generic_steppings },
184 	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEXA,	"Cortex A9-r3",
185 	  generic_steppings },
186 	{ CPU_ID_CORTEXA15R0,	CPU_CLASS_CORTEXA,	"Cortex A15-r0",
187 	  generic_steppings },
188 	{ CPU_ID_CORTEXA15R1,	CPU_CLASS_CORTEXA,	"Cortex A15-r1",
189 	  generic_steppings },
190 	{ CPU_ID_CORTEXA15R2,	CPU_CLASS_CORTEXA,	"Cortex A15-r2",
191 	  generic_steppings },
192 	{ CPU_ID_CORTEXA15R3,	CPU_CLASS_CORTEXA,	"Cortex A15-r3",
193 	  generic_steppings },
194 	{ CPU_ID_KRAIT,		CPU_CLASS_KRAIT,	"Krait",
195 	  generic_steppings },
196 
197 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
198 	  xscale_steppings },
199 
200 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
201 	  i80321_steppings },
202 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
203 	  i80321_steppings },
204 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
205 	  i80321_steppings },
206 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
207 	  i80321_steppings },
208 
209 	{ CPU_ID_81342,		CPU_CLASS_XSCALE,	"i81342",
210 	  i81342_steppings },
211 
212 	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
213 	  i80219_steppings },
214 	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
215 	  i80219_steppings },
216 
217 	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
218 	  pxa27x_steppings },
219 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
220 	  pxa2x0_steppings },
221 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
222 	  pxa2x0_steppings },
223 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
224 	  pxa2x0_steppings },
225 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
226 	  pxa2x0_steppings },
227 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255",
228 	  pxa255_steppings },
229 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
230 	  pxa2x0_steppings },
231 
232 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
233 	  ixp425_steppings },
234 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
235 	  ixp425_steppings },
236 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
237 	  ixp425_steppings },
238 
239 	/* XXX ixp435 steppings? */
240 	{ CPU_ID_IXP435,	CPU_CLASS_XSCALE,	"IXP435",
241 	  ixp425_steppings },
242 
243 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S",
244 	  generic_steppings },
245 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S R1",
246 	  generic_steppings },
247 	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S",
248 	  generic_steppings },
249 
250 	{ CPU_ID_MV88FR131,	CPU_CLASS_MARVELL,	"Feroceon 88FR131",
251 	  generic_steppings },
252 
253 	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_MARVELL,	"Feroceon 88FR571-VD",
254 	  generic_steppings },
255 	{ CPU_ID_MV88SV581X_V7,	CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
256 	  generic_steppings },
257 	{ CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
258 	  generic_steppings },
259 	{ CPU_ID_MV88SV584X_V7,	CPU_CLASS_MARVELL,	"Sheeva 88SV584x",
260 	  generic_steppings },
261 
262 	{ 0, CPU_CLASS_NONE, NULL, NULL }
263 };
264 
265 struct cpu_classtab {
266 	const char	*class_name;
267 	const char	*class_option;
268 };
269 
270 const struct cpu_classtab cpu_classes[] = {
271 	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
272 	{ "ARM9TDMI",	"CPU_ARM9TDMI" },	/* CPU_CLASS_ARM9TDMI */
273 	{ "ARM9E-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9ES */
274 	{ "ARM9EJ-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9EJS */
275 	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
276 	{ "ARM10EJ",	"CPU_ARM10" },		/* CPU_CLASS_ARM10EJ */
277 	{ "Cortex-A",	"CPU_CORTEXA" },	/* CPU_CLASS_CORTEXA */
278 	{ "Krait",	"CPU_KRAIT" },		/* CPU_CLASS_KRAIT */
279 	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
280 	{ "ARM11J",	"CPU_ARM11" },		/* CPU_CLASS_ARM11J */
281 	{ "Marvell",	"CPU_MARVELL" },	/* CPU_CLASS_MARVELL */
282 };
283 
284 /*
285  * Report the type of the specified arm processor. This uses the generic and
286  * arm specific information in the cpu structure to identify the processor.
287  * The remaining fields in the cpu structure are filled in appropriately.
288  */
289 
290 static const char * const wtnames[] = {
291 	"write-through",
292 	"write-back",
293 	"write-back",
294 	"**unknown 3**",
295 	"**unknown 4**",
296 	"write-back-locking",		/* XXX XScale-specific? */
297 	"write-back-locking-A",
298 	"write-back-locking-B",
299 	"**unknown 8**",
300 	"**unknown 9**",
301 	"**unknown 10**",
302 	"**unknown 11**",
303 	"**unknown 12**",
304 	"**unknown 13**",
305 	"write-back-locking-C",
306 	"**unknown 15**",
307 };
308 
309 static void
print_enadis(int enadis,char * s)310 print_enadis(int enadis, char *s)
311 {
312 
313 	printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
314 }
315 
316 extern int ctrl;
317 enum cpu_class cpu_class = CPU_CLASS_NONE;
318 
cpu_pfr(int num)319 u_int cpu_pfr(int num)
320 {
321 	u_int feat;
322 
323 	switch (num) {
324 	case 0:
325 		__asm __volatile("mrc p15, 0, %0, c0, c1, 0"
326 		    : "=r" (feat));
327 		break;
328 	case 1:
329 		__asm __volatile("mrc p15, 0, %0, c0, c1, 1"
330 		    : "=r" (feat));
331 		break;
332 	default:
333 		panic("Processor Feature Register %d not implemented", num);
334 		break;
335 	}
336 
337 	return (feat);
338 }
339 
340 static
identify_armv7(void)341 void identify_armv7(void)
342 {
343 	u_int feature;
344 
345 	printf("Supported features:");
346 	/* Get Processor Feature Register 0 */
347 	feature = cpu_pfr(0);
348 
349 	if (feature & ARM_PFR0_ARM_ISA_MASK)
350 		printf(" ARM_ISA");
351 
352 	if (feature & ARM_PFR0_THUMB2)
353 		printf(" THUMB2");
354 	else if (feature & ARM_PFR0_THUMB)
355 		printf(" THUMB");
356 
357 	if (feature & ARM_PFR0_JAZELLE_MASK)
358 		printf(" JAZELLE");
359 
360 	if (feature & ARM_PFR0_THUMBEE_MASK)
361 		printf(" THUMBEE");
362 
363 
364 	/* Get Processor Feature Register 1 */
365 	feature = cpu_pfr(1);
366 
367 	if (feature & ARM_PFR1_ARMV4_MASK)
368 		printf(" ARMv4");
369 
370 	if (feature & ARM_PFR1_SEC_EXT_MASK)
371 		printf(" Security_Ext");
372 
373 	if (feature & ARM_PFR1_MICROCTRL_MASK)
374 		printf(" M_profile");
375 
376 	printf("\n");
377 }
378 
379 void
identify_arm_cpu(void)380 identify_arm_cpu(void)
381 {
382 	u_int cpuid, reg, size, sets, ways;
383 	u_int8_t type, linesize;
384 	int i;
385 
386 	cpuid = cpu_id();
387 
388 	if (cpuid == 0) {
389 		printf("Processor failed probe - no CPU ID\n");
390 		return;
391 	}
392 
393 	for (i = 0; cpuids[i].cpuid != 0; i++)
394 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
395 			cpu_class = cpuids[i].cpu_class;
396 			printf("CPU: %s %s (%s core)\n",
397 			    cpuids[i].cpu_name,
398 			    cpuids[i].cpu_steppings[cpuid &
399 			    CPU_ID_REVISION_MASK],
400 			    cpu_classes[cpu_class].class_name);
401 			break;
402 		}
403 	if (cpuids[i].cpuid == 0)
404 		printf("unknown CPU (ID = 0x%x)\n", cpuid);
405 
406 	printf(" ");
407 
408 	if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) {
409 		identify_armv7();
410 	} else {
411 		if (ctrl & CPU_CONTROL_BEND_ENABLE)
412 			printf(" Big-endian");
413 		else
414 			printf(" Little-endian");
415 
416 		switch (cpu_class) {
417 		case CPU_CLASS_ARM9TDMI:
418 		case CPU_CLASS_ARM9ES:
419 		case CPU_CLASS_ARM9EJS:
420 		case CPU_CLASS_ARM10E:
421 		case CPU_CLASS_ARM10EJ:
422 		case CPU_CLASS_XSCALE:
423 		case CPU_CLASS_ARM11J:
424 		case CPU_CLASS_MARVELL:
425 			print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
426 			print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
427 #ifdef CPU_XSCALE_81342
428 			print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
429 #endif
430 #if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
431 			i = sheeva_control_ext(0, 0);
432 			print_enadis(i & MV_WA_ENABLE, "WA");
433 			print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
434 			printf("\n ");
435 			print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
436 			print_enadis(i & MV_L2_ENABLE, "L2");
437 			print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
438 			    "L2 prefetch");
439 			printf("\n ");
440 #endif
441 			break;
442 		default:
443 			break;
444 		}
445 	}
446 
447 	print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
448 	if (ctrl & CPU_CONTROL_LABT_ENABLE)
449 		printf(" LABT");
450 	else
451 		printf(" EABT");
452 
453 	print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
454 	printf("\n");
455 
456 	if (arm_cache_level) {
457 		printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
458 		    arm_cache_loc + 1, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
459 		i = 0;
460 		while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
461 			printf("Cache level %d: \n", i + 1);
462 			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
463 			    type == CACHE_SEP_CACHE) {
464 				reg = arm_cache_type[2 * i];
465 				ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
466 				sets = CPUV7_CT_xSIZE_SET(reg) + 1;
467 				linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
468 				size = (ways * sets * linesize) / 1024;
469 
470 				if (type == CACHE_UNI_CACHE)
471 					printf(" %dKB/%dB %d-way unified cache", size, linesize,ways);
472 				else
473 					printf(" %dKB/%dB %d-way data cache", size, linesize, ways);
474 				if (reg & CPUV7_CT_CTYPE_WT)
475 					printf(" WT");
476 				if (reg & CPUV7_CT_CTYPE_WB)
477 					printf(" WB");
478 				if (reg & CPUV7_CT_CTYPE_RA)
479 					printf(" Read-Alloc");
480 				if (reg & CPUV7_CT_CTYPE_WA)
481 					printf(" Write-Alloc");
482 				printf("\n");
483 			}
484 
485 			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
486 				reg = arm_cache_type[(2 * i) + 1];
487 
488 				ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
489 				sets = CPUV7_CT_xSIZE_SET(reg) + 1;
490 				linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
491 				size = (ways * sets * linesize) / 1024;
492 
493 				printf(" %dKB/%dB %d-way instruction cache", size, linesize, ways);
494 				if (reg & CPUV7_CT_CTYPE_WT)
495 					printf(" WT");
496 				if (reg & CPUV7_CT_CTYPE_WB)
497 					printf(" WB");
498 				if (reg & CPUV7_CT_CTYPE_RA)
499 					printf(" Read-Alloc");
500 				if (reg & CPUV7_CT_CTYPE_WA)
501 					printf(" Write-Alloc");
502 				printf("\n");
503 			}
504 			i++;
505 		}
506 	} else {
507 		/* Print cache info. */
508 		if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
509 			return;
510 
511 		if (arm_pcache_unified) {
512 			printf("  %dKB/%dB %d-way %s unified cache\n",
513 			    arm_pdcache_size / 1024,
514 			    arm_pdcache_line_size, arm_pdcache_ways,
515 			    wtnames[arm_pcache_type]);
516 		} else {
517 			printf("  %dKB/%dB %d-way instruction cache\n",
518 			    arm_picache_size / 1024,
519 			    arm_picache_line_size, arm_picache_ways);
520 			printf("  %dKB/%dB %d-way %s data cache\n",
521 			    arm_pdcache_size / 1024,
522 			    arm_pdcache_line_size, arm_pdcache_ways,
523 			    wtnames[arm_pcache_type]);
524 		}
525 	}
526 }
527