identcpu-v6.c revision 139735
1129198Scognet/*	$NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * Copyright (c) 1995 Mark Brinicombe.
5129198Scognet * Copyright (c) 1995 Brini.
6129198Scognet * All rights reserved.
7129198Scognet *
8129198Scognet * Redistribution and use in source and binary forms, with or without
9129198Scognet * modification, are permitted provided that the following conditions
10129198Scognet * are met:
11129198Scognet * 1. Redistributions of source code must retain the above copyright
12129198Scognet *    notice, this list of conditions and the following disclaimer.
13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
14129198Scognet *    notice, this list of conditions and the following disclaimer in the
15129198Scognet *    documentation and/or other materials provided with the distribution.
16129198Scognet * 3. All advertising materials mentioning features or use of this software
17129198Scognet *    must display the following acknowledgement:
18129198Scognet *	This product includes software developed by Brini.
19129198Scognet * 4. The name of the company nor the name of the author may be used to
20129198Scognet *    endorse or promote products derived from this software without specific
21129198Scognet *    prior written permission.
22129198Scognet *
23129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
24129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26129198Scognet * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33129198Scognet * SUCH DAMAGE.
34129198Scognet *
35129198Scognet * RiscBSD kernel project
36129198Scognet *
37129198Scognet * cpu.c
38129198Scognet *
39129198Scognet * Probing and configuration for the master CPU
40129198Scognet *
41129198Scognet * Created      : 10/10/95
42129198Scognet */
43129198Scognet
44129198Scognet#include <sys/cdefs.h>
45129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/identcpu.c 139735 2005-01-05 21:58:49Z imp $");
46129198Scognet#include <sys/systm.h>
47129198Scognet#include <sys/param.h>
48129198Scognet#include <sys/malloc.h>
49129198Scognet#include <sys/time.h>
50129198Scognet#include <sys/proc.h>
51129198Scognet#include <sys/conf.h>
52135652Scognet#include <sys/kernel.h>
53135652Scognet#include <sys/sysctl.h>
54129198Scognet#include <machine/cpu.h>
55129198Scognet
56129198Scognet#include <machine/cpuconf.h>
57129198Scognet
58129198Scognetchar machine[] = "arm";
59129198Scognet
60135652ScognetSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
61135652Scognet        machine, 0, "Machine class");
62129198Scognetenum cpu_class {
63129198Scognet	CPU_CLASS_NONE,
64129198Scognet	CPU_CLASS_ARM2,
65129198Scognet	CPU_CLASS_ARM2AS,
66129198Scognet	CPU_CLASS_ARM3,
67129198Scognet	CPU_CLASS_ARM6,
68129198Scognet	CPU_CLASS_ARM7,
69129198Scognet	CPU_CLASS_ARM7TDMI,
70129198Scognet	CPU_CLASS_ARM8,
71129198Scognet	CPU_CLASS_ARM9TDMI,
72129198Scognet	CPU_CLASS_ARM9ES,
73129198Scognet	CPU_CLASS_ARM10E,
74129198Scognet	CPU_CLASS_SA1,
75129198Scognet	CPU_CLASS_XSCALE
76129198Scognet};
77129198Scognet
78129198Scognetstatic const char * const generic_steppings[16] = {
79129198Scognet	"rev 0",	"rev 1",	"rev 2",	"rev 3",
80129198Scognet	"rev 4",	"rev 5",	"rev 6",	"rev 7",
81129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
82129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
83129198Scognet};
84129198Scognet
85129198Scognetstatic const char * const sa110_steppings[16] = {
86129198Scognet	"rev 0",	"step J",	"step K",	"step S",
87129198Scognet	"step T",	"rev 5",	"rev 6",	"rev 7",
88129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
89129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
90129198Scognet};
91129198Scognet
92129198Scognetstatic const char * const sa1100_steppings[16] = {
93129198Scognet	"rev 0",	"step B",	"step C",	"rev 3",
94129198Scognet	"rev 4",	"rev 5",	"rev 6",	"rev 7",
95129198Scognet	"step D",	"step E",	"rev 10"	"step G",
96129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
97129198Scognet};
98129198Scognet
99129198Scognetstatic const char * const sa1110_steppings[16] = {
100129198Scognet	"step A-0",	"rev 1",	"rev 2",	"rev 3",
101129198Scognet	"step B-0",	"step B-1",	"step B-2",	"step B-3",
102129198Scognet	"step B-4",	"step B-5",	"rev 10",	"rev 11",
103129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
104129198Scognet};
105129198Scognet
106129198Scognetstatic const char * const ixp12x0_steppings[16] = {
107129198Scognet	"(IXP1200 step A)",		"(IXP1200 step B)",
108129198Scognet	"rev 2",			"(IXP1200 step C)",
109129198Scognet	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
110129198Scognet	"(IXP1240 step B)",		"(IXP1250 step B)",
111129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
112129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
113129198Scognet};
114129198Scognet
115129198Scognetstatic const char * const xscale_steppings[16] = {
116129198Scognet	"step A-0",	"step A-1",	"step B-0",	"step C-0",
117129198Scognet	"step D-0",	"rev 5",	"rev 6",	"rev 7",
118129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
119129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
120129198Scognet};
121129198Scognet
122129198Scognetstatic const char * const i80321_steppings[16] = {
123129198Scognet	"step A-0",	"step B-0",	"rev 2",	"rev 3",
124129198Scognet	"rev 4",	"rev 5",	"rev 6",	"rev 7",
125129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
126129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
127129198Scognet};
128129198Scognet
129129198Scognetstatic const char * const pxa2x0_steppings[16] = {
130129198Scognet	"step A-0",	"step A-1",	"step B-0",	"step B-1",
131129198Scognet	"step B-2",	"step C-0",	"rev 6",	"rev 7",
132129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
133129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
134129198Scognet};
135129198Scognet
136129198Scognetstatic const char * const ixp425_steppings[16] = {
137129198Scognet	"step 0",	"rev 1",	"rev 2",	"rev 3",
138129198Scognet	"rev 4",	"rev 5",	"rev 6",	"rev 7",
139129198Scognet	"rev 8",	"rev 9",	"rev 10",	"rev 11",
140129198Scognet	"rev 12",	"rev 13",	"rev 14",	"rev 15",
141129198Scognet};
142129198Scognet
143129198Scognetstruct cpuidtab {
144129198Scognet	u_int32_t	cpuid;
145129198Scognet	enum		cpu_class cpu_class;
146129198Scognet	const char	*cpu_name;
147129198Scognet	const char * const *cpu_steppings;
148129198Scognet};
149129198Scognet
150129198Scognetconst struct cpuidtab cpuids[] = {
151129198Scognet	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
152129198Scognet	  generic_steppings },
153129198Scognet	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
154129198Scognet	  generic_steppings },
155129198Scognet
156129198Scognet	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
157129198Scognet	  generic_steppings },
158129198Scognet
159129198Scognet	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
160129198Scognet	  generic_steppings },
161129198Scognet	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
162129198Scognet	  generic_steppings },
163129198Scognet	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
164129198Scognet	  generic_steppings },
165129198Scognet
166129198Scognet	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
167129198Scognet	  generic_steppings },
168129198Scognet	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
169129198Scognet	  generic_steppings },
170129198Scognet	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
171129198Scognet	  generic_steppings },
172129198Scognet	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
173129198Scognet	  generic_steppings },
174129198Scognet	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
175129198Scognet	  generic_steppings },
176129198Scognet	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
177129198Scognet	  generic_steppings },
178129198Scognet	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
179129198Scognet	  generic_steppings },
180129198Scognet	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
181129198Scognet	  generic_steppings },
182129198Scognet	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
183129198Scognet	  generic_steppings },
184129198Scognet
185129198Scognet	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
186129198Scognet	  generic_steppings },
187129198Scognet
188129198Scognet	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
189129198Scognet	  generic_steppings },
190129198Scognet	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
191129198Scognet	  generic_steppings },
192129198Scognet	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
193129198Scognet	  generic_steppings },
194129198Scognet	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
195129198Scognet	  generic_steppings },
196129198Scognet	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
197129198Scognet	  generic_steppings },
198129198Scognet	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
199129198Scognet	  generic_steppings },
200129198Scognet	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
201129198Scognet	  generic_steppings },
202129198Scognet
203129198Scognet	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
204129198Scognet	  generic_steppings },
205129198Scognet	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
206129198Scognet	  generic_steppings },
207129198Scognet
208129198Scognet	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
209129198Scognet	  sa110_steppings },
210129198Scognet	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
211129198Scognet	  sa1100_steppings },
212129198Scognet	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
213129198Scognet	  sa1110_steppings },
214129198Scognet
215129198Scognet	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
216129198Scognet	  ixp12x0_steppings },
217129198Scognet
218129198Scognet	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
219129198Scognet	  xscale_steppings },
220129198Scognet
221129198Scognet	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
222129198Scognet	  i80321_steppings },
223129198Scognet	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
224129198Scognet	  i80321_steppings },
225129198Scognet	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
226129198Scognet	  i80321_steppings },
227129198Scognet	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
228129198Scognet	  i80321_steppings },
229129198Scognet
230129198Scognet	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
231129198Scognet	  pxa2x0_steppings },
232129198Scognet	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
233129198Scognet	  pxa2x0_steppings },
234129198Scognet	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
235129198Scognet	  pxa2x0_steppings },
236129198Scognet	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
237129198Scognet	  pxa2x0_steppings },
238129198Scognet	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA250",
239129198Scognet	  pxa2x0_steppings },
240129198Scognet	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
241129198Scognet	  pxa2x0_steppings },
242129198Scognet
243129198Scognet	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
244129198Scognet	  ixp425_steppings },
245129198Scognet	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
246129198Scognet	  ixp425_steppings },
247129198Scognet	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
248129198Scognet	  ixp425_steppings },
249129198Scognet
250129198Scognet	{ 0, CPU_CLASS_NONE, NULL, NULL }
251129198Scognet};
252129198Scognet
253129198Scognetstruct cpu_classtab {
254129198Scognet	const char	*class_name;
255129198Scognet	const char	*class_option;
256129198Scognet};
257129198Scognet
258129198Scognetconst struct cpu_classtab cpu_classes[] = {
259129198Scognet	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
260129198Scognet	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
261129198Scognet	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
262129198Scognet	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
263129198Scognet	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
264129198Scognet	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
265129198Scognet	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
266129198Scognet	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
267129198Scognet	{ "ARM9TDMI",	NULL },			/* CPU_CLASS_ARM9TDMI */
268129198Scognet	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
269129198Scognet	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
270129198Scognet	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
271129198Scognet	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
272129198Scognet};
273129198Scognet
274129198Scognet/*
275129198Scognet * Report the type of the specified arm processor. This uses the generic and
276129198Scognet * arm specific information in the cpu structure to identify the processor.
277129198Scognet * The remaining fields in the cpu structure are filled in appropriately.
278129198Scognet */
279129198Scognet
280129198Scognetstatic const char * const wtnames[] = {
281129198Scognet	"write-through",
282129198Scognet	"write-back",
283129198Scognet	"write-back",
284129198Scognet	"**unknown 3**",
285129198Scognet	"**unknown 4**",
286129198Scognet	"write-back-locking",		/* XXX XScale-specific? */
287129198Scognet	"write-back-locking-A",
288129198Scognet	"write-back-locking-B",
289129198Scognet	"**unknown 8**",
290129198Scognet	"**unknown 9**",
291129198Scognet	"**unknown 10**",
292129198Scognet	"**unknown 11**",
293129198Scognet	"**unknown 12**",
294129198Scognet	"**unknown 13**",
295129198Scognet	"**unknown 14**",
296129198Scognet	"**unknown 15**",
297129198Scognet};
298129198Scognet
299129198Scognetextern int ctrl;
300129198Scognetvoid
301129198Scognetidentify_arm_cpu(void)
302129198Scognet{
303129198Scognet	u_int cpuid;
304129198Scognet	enum cpu_class cpu_class = CPU_CLASS_NONE;
305129198Scognet	int i;
306129198Scognet
307129198Scognet	cpuid = cpu_id();
308129198Scognet
309129198Scognet	if (cpuid == 0) {
310129198Scognet		printf("Processor failed probe - no CPU ID\n");
311129198Scognet		return;
312129198Scognet	}
313129198Scognet
314129198Scognet	for (i = 0; cpuids[i].cpuid != 0; i++)
315129198Scognet		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
316129198Scognet			cpu_class = cpuids[i].cpu_class;
317129198Scognet			printf("%s %s (%s core)\n",
318129198Scognet			    cpuids[i].cpu_name,
319129198Scognet			    cpuids[i].cpu_steppings[cpuid &
320129198Scognet			    CPU_ID_REVISION_MASK],
321129198Scognet			    cpu_classes[cpu_class].class_name);
322129198Scognet			break;
323129198Scognet		}
324129198Scognet	if (cpuids[i].cpuid == 0)
325129198Scognet		printf("unknown CPU (ID = 0x%x)\n", cpuid);
326129198Scognet
327129198Scognet	switch (cpu_class) {
328129198Scognet	case CPU_CLASS_ARM6:
329129198Scognet	case CPU_CLASS_ARM7:
330129198Scognet	case CPU_CLASS_ARM7TDMI:
331129198Scognet	case CPU_CLASS_ARM8:
332129198Scognet		if ((ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
333129198Scognet			printf(" IDC disabled");
334129198Scognet		else
335129198Scognet			printf(" IDC enabled");
336129198Scognet		break;
337129198Scognet	case CPU_CLASS_ARM9TDMI:
338129198Scognet	case CPU_CLASS_ARM10E:
339129198Scognet	case CPU_CLASS_SA1:
340129198Scognet	case CPU_CLASS_XSCALE:
341129198Scognet		if ((ctrl & CPU_CONTROL_DC_ENABLE) == 0)
342129198Scognet			printf(" DC disabled");
343129198Scognet		else
344129198Scognet			printf(" DC enabled");
345129198Scognet		if ((ctrl & CPU_CONTROL_IC_ENABLE) == 0)
346129198Scognet			printf(" IC disabled");
347129198Scognet		else
348129198Scognet			printf(" IC enabled");
349129198Scognet		break;
350129198Scognet	default:
351129198Scognet		break;
352129198Scognet	}
353129198Scognet	if ((ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
354129198Scognet		printf(" WB disabled");
355129198Scognet	else
356129198Scognet		printf(" WB enabled");
357129198Scognet
358129198Scognet	if (ctrl & CPU_CONTROL_LABT_ENABLE)
359129198Scognet		printf(" LABT");
360129198Scognet	else
361129198Scognet		printf(" EABT");
362129198Scognet
363129198Scognet	if (ctrl & CPU_CONTROL_BPRD_ENABLE)
364129198Scognet		printf(" branch prediction enabled");
365129198Scognet
366137272Scognet	/* Print cache info. */
367137272Scognet	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
368137272Scognet		return;
369137272Scognet
370137272Scognet	if (arm_pcache_unified) {
371137272Scognet 		printf("%dKB/%dB %d-way %s unified cache\n",
372137272Scognet		    arm_pdcache_size / 1024,
373137272Scognet		    arm_pdcache_line_size, arm_pdcache_ways,
374137272Scognet		    wtnames[arm_pcache_type]);
375137272Scognet	} else {
376137272Scognet		printf("%dKB/%dB %d-way Instruction cache\n",
377137272Scognet		    arm_picache_size / 1024,
378137272Scognet		    arm_picache_line_size, arm_picache_ways);
379137272Scognet		printf("%dKB/%dB %d-way %s Data cache\n",
380137272Scognet		    arm_pdcache_size / 1024,
381137272Scognet		    arm_pdcache_line_size, arm_pdcache_ways,
382137272Scognet		    wtnames[arm_pcache_type]);
383137272Scognet	}
384129198Scognet	printf("\n");
385129198Scognet}
386129198Scognet
387