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$");
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
60char machine[] = "arm";
61
62SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
63	machine, 0, "Machine class");
64
65static 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
72static const char * const sa110_steppings[16] = {
73	"rev 0",	"step J",	"step K",	"step S",
74	"step T",	"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
79static const char * const sa1100_steppings[16] = {
80	"rev 0",	"step B",	"step C",	"rev 3",
81	"rev 4",	"rev 5",	"rev 6",	"rev 7",
82	"step D",	"step E",	"rev 10"	"step G",
83	"rev 12",	"rev 13",	"rev 14",	"rev 15",
84};
85
86static const char * const sa1110_steppings[16] = {
87	"step A-0",	"rev 1",	"rev 2",	"rev 3",
88	"step B-0",	"step B-1",	"step B-2",	"step B-3",
89	"step B-4",	"step B-5",	"rev 10",	"rev 11",
90	"rev 12",	"rev 13",	"rev 14",	"rev 15",
91};
92
93static const char * const ixp12x0_steppings[16] = {
94	"(IXP1200 step A)",		"(IXP1200 step B)",
95	"rev 2",			"(IXP1200 step C)",
96	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
97	"(IXP1240 step B)",		"(IXP1250 step B)",
98	"rev 8",	"rev 9",	"rev 10",	"rev 11",
99	"rev 12",	"rev 13",	"rev 14",	"rev 15",
100};
101
102static const char * const xscale_steppings[16] = {
103	"step A-0",	"step A-1",	"step B-0",	"step C-0",
104	"step D-0",	"rev 5",	"rev 6",	"rev 7",
105	"rev 8",	"rev 9",	"rev 10",	"rev 11",
106	"rev 12",	"rev 13",	"rev 14",	"rev 15",
107};
108
109static const char * const i80219_steppings[16] = {
110	"step A-0",	"rev 1",	"rev 2",	"rev 3",
111	"rev 4",	"rev 5",	"rev 6",	"rev 7",
112	"rev 8",	"rev 9",	"rev 10",	"rev 11",
113	"rev 12",	"rev 13",	"rev 14",	"rev 15",
114};
115
116static const char * const i80321_steppings[16] = {
117	"step A-0",	"step B-0",	"rev 2",	"rev 3",
118	"rev 4",	"rev 5",	"rev 6",	"rev 7",
119	"rev 8",	"rev 9",	"rev 10",	"rev 11",
120	"rev 12",	"rev 13",	"rev 14",	"rev 15",
121};
122
123static const char * const i81342_steppings[16] = {
124	"step A-0",	"rev 1",	"rev 2",	"rev 3",
125	"rev 4",	"rev 5",	"rev 6",	"rev 7",
126	"rev 8",	"rev 9",	"rev 10",	"rev 11",
127	"rev 12",	"rev 13",	"rev 14",	"rev 15",
128};
129
130/* Steppings for PXA2[15]0 */
131static const char * const pxa2x0_steppings[16] = {
132	"step A-0",	"step A-1",	"step B-0",	"step B-1",
133	"step B-2",	"step C-0",	"rev 6",	"rev 7",
134	"rev 8",	"rev 9",	"rev 10",	"rev 11",
135	"rev 12",	"rev 13",	"rev 14",	"rev 15",
136};
137
138/* Steppings for PXA255/26x.
139 * rev 5: PXA26x B0, rev 6: PXA255 A0
140 */
141static const char * const pxa255_steppings[16] = {
142	"rev 0",	"rev 1",	"rev 2",	"step A-0",
143	"rev 4",	"step B-0",	"step A-0",	"rev 7",
144	"rev 8",	"rev 9",	"rev 10",	"rev 11",
145	"rev 12",	"rev 13",	"rev 14",	"rev 15",
146};
147
148/* Stepping for PXA27x */
149static const char * const pxa27x_steppings[16] = {
150	"step A-0",	"step A-1",	"step B-0",	"step B-1",
151	"step C-0",	"rev 5",	"rev 6",	"rev 7",
152	"rev 8",	"rev 9",	"rev 10",	"rev 11",
153	"rev 12",	"rev 13",	"rev 14",	"rev 15",
154};
155
156static const char * const ixp425_steppings[16] = {
157	"step 0 (A0)",	"rev 1 (ARMv5TE)", "rev 2",	"rev 3",
158	"rev 4",	"rev 5",	"rev 6",	"rev 7",
159	"rev 8",	"rev 9",	"rev 10",	"rev 11",
160	"rev 12",	"rev 13",	"rev 14",	"rev 15",
161};
162
163struct cpuidtab {
164	u_int32_t	cpuid;
165	enum		cpu_class cpu_class;
166	const char	*cpu_name;
167	const char * const *cpu_steppings;
168};
169
170const struct cpuidtab cpuids[] = {
171	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
172	  generic_steppings },
173	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
174	  generic_steppings },
175
176	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
177	  generic_steppings },
178
179	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
180	  generic_steppings },
181	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
182	  generic_steppings },
183	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
184	  generic_steppings },
185
186	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
187	  generic_steppings },
188	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
189	  generic_steppings },
190	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
191	  generic_steppings },
192	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
193	  generic_steppings },
194	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
195	  generic_steppings },
196	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
197	  generic_steppings },
198	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
199	  generic_steppings },
200	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
201	  generic_steppings },
202	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
203	  generic_steppings },
204
205	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
206	  generic_steppings },
207
208	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
209	  generic_steppings },
210	{ CPU_ID_ARM920T_ALT,	CPU_CLASS_ARM9TDMI,	"ARM920T",
211	  generic_steppings },
212	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
213	  generic_steppings },
214	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
215	  generic_steppings },
216	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
217	  generic_steppings },
218	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
219	  generic_steppings },
220	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
221	  generic_steppings },
222	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
223	  generic_steppings },
224	{ CPU_ID_FA526,		CPU_CLASS_ARM9TDMI,	"FA526",
225	  generic_steppings },
226	{ CPU_ID_FA626TE,	CPU_CLASS_ARM9ES,	"FA626TE",
227	  generic_steppings },
228
229	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
230	  generic_steppings },
231
232	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
233	  generic_steppings },
234	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
235	  generic_steppings },
236	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
237	  generic_steppings },
238
239	{ CPU_ID_CORTEXA7,	CPU_CLASS_CORTEXA,	"Cortex A7",
240	  generic_steppings },
241	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEXA,	"Cortex A8-r1",
242	  generic_steppings },
243	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEXA,	"Cortex A8-r2",
244	  generic_steppings },
245	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEXA,	"Cortex A8-r3",
246	  generic_steppings },
247	{ CPU_ID_CORTEXA9R1,	CPU_CLASS_CORTEXA,	"Cortex A9-r1",
248	  generic_steppings },
249	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEXA,	"Cortex A9-r2",
250	  generic_steppings },
251	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEXA,	"Cortex A9-r3",
252	  generic_steppings },
253	{ CPU_ID_CORTEXA15,     CPU_CLASS_CORTEXA,      "Cortex A15",
254	  generic_steppings },
255
256	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
257	  sa110_steppings },
258	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
259	  sa1100_steppings },
260	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
261	  sa1110_steppings },
262
263	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
264	  ixp12x0_steppings },
265
266	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
267	  xscale_steppings },
268
269	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
270	  i80321_steppings },
271	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
272	  i80321_steppings },
273	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
274	  i80321_steppings },
275	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
276	  i80321_steppings },
277
278	{ CPU_ID_81342,		CPU_CLASS_XSCALE,	"i81342",
279	  i81342_steppings },
280
281	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
282	  i80219_steppings },
283	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
284	  i80219_steppings },
285
286	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
287	  pxa27x_steppings },
288	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
289	  pxa2x0_steppings },
290	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
291	  pxa2x0_steppings },
292	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
293	  pxa2x0_steppings },
294	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
295	  pxa2x0_steppings },
296	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255",
297	  pxa255_steppings },
298	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
299	  pxa2x0_steppings },
300
301	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
302	  ixp425_steppings },
303	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
304	  ixp425_steppings },
305	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
306	  ixp425_steppings },
307
308	/* XXX ixp435 steppings? */
309	{ CPU_ID_IXP435,	CPU_CLASS_XSCALE,	"IXP435",
310	  ixp425_steppings },
311
312	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S",
313	  generic_steppings },
314	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S R1",
315	  generic_steppings },
316	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S",
317	  generic_steppings },
318
319	{ CPU_ID_MV88FR131,	CPU_CLASS_MARVELL,	"Feroceon 88FR131",
320	  generic_steppings },
321
322	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_MARVELL,	"Feroceon 88FR571-VD",
323	  generic_steppings },
324	{ CPU_ID_MV88SV581X_V6,	CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
325	  generic_steppings },
326	{ CPU_ID_ARM_88SV581X_V6, CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
327	  generic_steppings },
328	{ CPU_ID_MV88SV581X_V7,	CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
329	  generic_steppings },
330	{ CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL,	"Sheeva 88SV581x",
331	  generic_steppings },
332	{ CPU_ID_MV88SV584X_V6,	CPU_CLASS_MARVELL,	"Sheeva 88SV584x",
333	  generic_steppings },
334	{ CPU_ID_ARM_88SV584X_V6, CPU_CLASS_MARVELL,	"Sheeva 88SV584x",
335	  generic_steppings },
336	{ CPU_ID_MV88SV584X_V7,	CPU_CLASS_MARVELL,	"Sheeva 88SV584x",
337	  generic_steppings },
338
339	{ 0, CPU_CLASS_NONE, NULL, NULL }
340};
341
342struct cpu_classtab {
343	const char	*class_name;
344	const char	*class_option;
345};
346
347const struct cpu_classtab cpu_classes[] = {
348	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
349	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
350	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
351	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
352	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
353	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
354	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
355	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
356	{ "ARM9TDMI",	"CPU_ARM9TDMI" },	/* CPU_CLASS_ARM9TDMI */
357	{ "ARM9E-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9ES */
358	{ "ARM9EJ-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9EJS */
359	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
360	{ "ARM10EJ",	"CPU_ARM10" },		/* CPU_CLASS_ARM10EJ */
361	{ "Cortex-A",	"CPU_CORTEXA" },	/* CPU_CLASS_CORTEXA */
362	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
363	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
364	{ "ARM11J",	"CPU_ARM11" },		/* CPU_CLASS_ARM11J */
365	{ "Marvell",	"CPU_MARVELL" },	/* CPU_CLASS_MARVELL */
366};
367
368/*
369 * Report the type of the specified arm processor. This uses the generic and
370 * arm specific information in the cpu structure to identify the processor.
371 * The remaining fields in the cpu structure are filled in appropriately.
372 */
373
374static const char * const wtnames[] = {
375	"write-through",
376	"write-back",
377	"write-back",
378	"**unknown 3**",
379	"**unknown 4**",
380	"write-back-locking",		/* XXX XScale-specific? */
381	"write-back-locking-A",
382	"write-back-locking-B",
383	"**unknown 8**",
384	"**unknown 9**",
385	"**unknown 10**",
386	"**unknown 11**",
387	"**unknown 12**",
388	"**unknown 13**",
389	"write-back-locking-C",
390	"**unknown 15**",
391};
392
393static void
394print_enadis(int enadis, char *s)
395{
396
397	printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
398}
399
400extern int ctrl;
401enum cpu_class cpu_class = CPU_CLASS_NONE;
402
403u_int cpu_pfr(int num)
404{
405	u_int feat;
406
407	switch (num) {
408	case 0:
409		__asm __volatile("mrc p15, 0, %0, c0, c1, 0"
410		    : "=r" (feat));
411		break;
412	case 1:
413		__asm __volatile("mrc p15, 0, %0, c0, c1, 1"
414		    : "=r" (feat));
415		break;
416	default:
417		panic("Processor Feature Register %d not implemented", num);
418		break;
419	}
420
421	return (feat);
422}
423
424static
425void identify_armv7(void)
426{
427	u_int feature;
428
429	printf("Supported features:");
430	/* Get Processor Feature Register 0 */
431	feature = cpu_pfr(0);
432
433	if (feature & ARM_PFR0_ARM_ISA_MASK)
434		printf(" ARM_ISA");
435
436	if (feature & ARM_PFR0_THUMB2)
437		printf(" THUMB2");
438	else if (feature & ARM_PFR0_THUMB)
439		printf(" THUMB");
440
441	if (feature & ARM_PFR0_JAZELLE_MASK)
442		printf(" JAZELLE");
443
444	if (feature & ARM_PFR0_THUMBEE_MASK)
445		printf(" THUMBEE");
446
447
448	/* Get Processor Feature Register 1 */
449	feature = cpu_pfr(1);
450
451	if (feature & ARM_PFR1_ARMV4_MASK)
452		printf(" ARMv4");
453
454	if (feature & ARM_PFR1_SEC_EXT_MASK)
455		printf(" Security_Ext");
456
457	if (feature & ARM_PFR1_MICROCTRL_MASK)
458		printf(" M_profile");
459
460	printf("\n");
461}
462
463void
464identify_arm_cpu(void)
465{
466	u_int cpuid, reg, size, sets, ways;
467	u_int8_t type, linesize;
468	int i;
469
470	cpuid = cpu_id();
471
472	if (cpuid == 0) {
473		printf("Processor failed probe - no CPU ID\n");
474		return;
475	}
476
477	for (i = 0; cpuids[i].cpuid != 0; i++)
478		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
479			cpu_class = cpuids[i].cpu_class;
480			printf("CPU: %s %s (%s core)\n",
481			    cpuids[i].cpu_name,
482			    cpuids[i].cpu_steppings[cpuid &
483			    CPU_ID_REVISION_MASK],
484			    cpu_classes[cpu_class].class_name);
485			break;
486		}
487	if (cpuids[i].cpuid == 0)
488		printf("unknown CPU (ID = 0x%x)\n", cpuid);
489
490	printf(" ");
491
492	if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) {
493		identify_armv7();
494	} else {
495		if (ctrl & CPU_CONTROL_BEND_ENABLE)
496			printf(" Big-endian");
497		else
498			printf(" Little-endian");
499
500		switch (cpu_class) {
501		case CPU_CLASS_ARM6:
502		case CPU_CLASS_ARM7:
503		case CPU_CLASS_ARM7TDMI:
504		case CPU_CLASS_ARM8:
505			print_enadis(ctrl & CPU_CONTROL_IDC_ENABLE, "IDC");
506			break;
507		case CPU_CLASS_ARM9TDMI:
508		case CPU_CLASS_ARM9ES:
509		case CPU_CLASS_ARM9EJS:
510		case CPU_CLASS_ARM10E:
511		case CPU_CLASS_ARM10EJ:
512		case CPU_CLASS_SA1:
513		case CPU_CLASS_XSCALE:
514		case CPU_CLASS_ARM11J:
515		case CPU_CLASS_MARVELL:
516			print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
517			print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
518#ifdef CPU_XSCALE_81342
519			print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
520#endif
521#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
522			i = sheeva_control_ext(0, 0);
523			print_enadis(i & MV_WA_ENABLE, "WA");
524			print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
525			printf("\n ");
526			print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
527			print_enadis(i & MV_L2_ENABLE, "L2");
528			print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
529			    "L2 prefetch");
530			printf("\n ");
531#endif
532			break;
533		default:
534			break;
535		}
536	}
537
538	print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
539	if (ctrl & CPU_CONTROL_LABT_ENABLE)
540		printf(" LABT");
541	else
542		printf(" EABT");
543
544	print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
545	printf("\n");
546
547	if (arm_cache_level) {
548		printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
549		    arm_cache_loc, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
550		i = 0;
551		while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
552			printf("Cache level %d: \n", i + 1);
553			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
554			    type == CACHE_SEP_CACHE) {
555				reg = arm_cache_type[2 * i];
556				ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
557				sets = CPUV7_CT_xSIZE_SET(reg) + 1;
558				linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
559				size = (ways * sets * linesize) / 1024;
560
561				if (type == CACHE_UNI_CACHE)
562					printf(" %dKB/%dB %d-way unified cache", size, linesize,ways);
563				else
564					printf(" %dKB/%dB %d-way data cache", size, linesize, ways);
565				if (reg & CPUV7_CT_CTYPE_WT)
566					printf(" WT");
567				if (reg & CPUV7_CT_CTYPE_WB)
568					printf(" WB");
569				if (reg & CPUV7_CT_CTYPE_RA)
570					printf(" Read-Alloc");
571				if (reg & CPUV7_CT_CTYPE_WA)
572					printf(" Write-Alloc");
573				printf("\n");
574			}
575
576			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
577				reg = arm_cache_type[(2 * i) + 1];
578
579				ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
580				sets = CPUV7_CT_xSIZE_SET(reg) + 1;
581				linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
582				size = (ways * sets * linesize) / 1024;
583
584				printf(" %dKB/%dB %d-way instruction cache", size, linesize, ways);
585				if (reg & CPUV7_CT_CTYPE_WT)
586					printf(" WT");
587				if (reg & CPUV7_CT_CTYPE_WB)
588					printf(" WB");
589				if (reg & CPUV7_CT_CTYPE_RA)
590					printf(" Read-Alloc");
591				if (reg & CPUV7_CT_CTYPE_WA)
592					printf(" Write-Alloc");
593				printf("\n");
594			}
595			i++;
596		}
597	} else {
598		/* Print cache info. */
599		if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
600			return;
601
602		if (arm_pcache_unified) {
603			printf("  %dKB/%dB %d-way %s unified cache\n",
604			    arm_pdcache_size / 1024,
605			    arm_pdcache_line_size, arm_pdcache_ways,
606			    wtnames[arm_pcache_type]);
607		} else {
608			printf("  %dKB/%dB %d-way instruction cache\n",
609			    arm_picache_size / 1024,
610			    arm_picache_line_size, arm_picache_ways);
611			printf("  %dKB/%dB %d-way %s data cache\n",
612			    arm_pdcache_size / 1024,
613			    arm_pdcache_line_size, arm_pdcache_ways,
614			    wtnames[arm_pcache_type]);
615		}
616	}
617}
618