identcpu-v6.c revision 139735
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: head/sys/arm/arm/identcpu.c 139735 2005-01-05 21:58:49Z imp $");
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
56#include <machine/cpuconf.h>
57
58char machine[] = "arm";
59
60SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
61        machine, 0, "Machine class");
62enum cpu_class {
63	CPU_CLASS_NONE,
64	CPU_CLASS_ARM2,
65	CPU_CLASS_ARM2AS,
66	CPU_CLASS_ARM3,
67	CPU_CLASS_ARM6,
68	CPU_CLASS_ARM7,
69	CPU_CLASS_ARM7TDMI,
70	CPU_CLASS_ARM8,
71	CPU_CLASS_ARM9TDMI,
72	CPU_CLASS_ARM9ES,
73	CPU_CLASS_ARM10E,
74	CPU_CLASS_SA1,
75	CPU_CLASS_XSCALE
76};
77
78static const char * const generic_steppings[16] = {
79	"rev 0",	"rev 1",	"rev 2",	"rev 3",
80	"rev 4",	"rev 5",	"rev 6",	"rev 7",
81	"rev 8",	"rev 9",	"rev 10",	"rev 11",
82	"rev 12",	"rev 13",	"rev 14",	"rev 15",
83};
84
85static const char * const sa110_steppings[16] = {
86	"rev 0",	"step J",	"step K",	"step S",
87	"step T",	"rev 5",	"rev 6",	"rev 7",
88	"rev 8",	"rev 9",	"rev 10",	"rev 11",
89	"rev 12",	"rev 13",	"rev 14",	"rev 15",
90};
91
92static const char * const sa1100_steppings[16] = {
93	"rev 0",	"step B",	"step C",	"rev 3",
94	"rev 4",	"rev 5",	"rev 6",	"rev 7",
95	"step D",	"step E",	"rev 10"	"step G",
96	"rev 12",	"rev 13",	"rev 14",	"rev 15",
97};
98
99static const char * const sa1110_steppings[16] = {
100	"step A-0",	"rev 1",	"rev 2",	"rev 3",
101	"step B-0",	"step B-1",	"step B-2",	"step B-3",
102	"step B-4",	"step B-5",	"rev 10",	"rev 11",
103	"rev 12",	"rev 13",	"rev 14",	"rev 15",
104};
105
106static const char * const ixp12x0_steppings[16] = {
107	"(IXP1200 step A)",		"(IXP1200 step B)",
108	"rev 2",			"(IXP1200 step C)",
109	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
110	"(IXP1240 step B)",		"(IXP1250 step B)",
111	"rev 8",	"rev 9",	"rev 10",	"rev 11",
112	"rev 12",	"rev 13",	"rev 14",	"rev 15",
113};
114
115static const char * const xscale_steppings[16] = {
116	"step A-0",	"step A-1",	"step B-0",	"step C-0",
117	"step D-0",	"rev 5",	"rev 6",	"rev 7",
118	"rev 8",	"rev 9",	"rev 10",	"rev 11",
119	"rev 12",	"rev 13",	"rev 14",	"rev 15",
120};
121
122static const char * const i80321_steppings[16] = {
123	"step A-0",	"step B-0",	"rev 2",	"rev 3",
124	"rev 4",	"rev 5",	"rev 6",	"rev 7",
125	"rev 8",	"rev 9",	"rev 10",	"rev 11",
126	"rev 12",	"rev 13",	"rev 14",	"rev 15",
127};
128
129static const char * const pxa2x0_steppings[16] = {
130	"step A-0",	"step A-1",	"step B-0",	"step B-1",
131	"step B-2",	"step C-0",	"rev 6",	"rev 7",
132	"rev 8",	"rev 9",	"rev 10",	"rev 11",
133	"rev 12",	"rev 13",	"rev 14",	"rev 15",
134};
135
136static const char * const ixp425_steppings[16] = {
137	"step 0",	"rev 1",	"rev 2",	"rev 3",
138	"rev 4",	"rev 5",	"rev 6",	"rev 7",
139	"rev 8",	"rev 9",	"rev 10",	"rev 11",
140	"rev 12",	"rev 13",	"rev 14",	"rev 15",
141};
142
143struct cpuidtab {
144	u_int32_t	cpuid;
145	enum		cpu_class cpu_class;
146	const char	*cpu_name;
147	const char * const *cpu_steppings;
148};
149
150const struct cpuidtab cpuids[] = {
151	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
152	  generic_steppings },
153	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
154	  generic_steppings },
155
156	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
157	  generic_steppings },
158
159	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
160	  generic_steppings },
161	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
162	  generic_steppings },
163	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
164	  generic_steppings },
165
166	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
167	  generic_steppings },
168	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
169	  generic_steppings },
170	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
171	  generic_steppings },
172	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
173	  generic_steppings },
174	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
175	  generic_steppings },
176	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
177	  generic_steppings },
178	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
179	  generic_steppings },
180	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
181	  generic_steppings },
182	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
183	  generic_steppings },
184
185	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
186	  generic_steppings },
187
188	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
189	  generic_steppings },
190	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
191	  generic_steppings },
192	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
193	  generic_steppings },
194	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
195	  generic_steppings },
196	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
197	  generic_steppings },
198	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
199	  generic_steppings },
200	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
201	  generic_steppings },
202
203	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
204	  generic_steppings },
205	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
206	  generic_steppings },
207
208	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
209	  sa110_steppings },
210	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
211	  sa1100_steppings },
212	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
213	  sa1110_steppings },
214
215	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
216	  ixp12x0_steppings },
217
218	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
219	  xscale_steppings },
220
221	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
222	  i80321_steppings },
223	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
224	  i80321_steppings },
225	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
226	  i80321_steppings },
227	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
228	  i80321_steppings },
229
230	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
231	  pxa2x0_steppings },
232	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
233	  pxa2x0_steppings },
234	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
235	  pxa2x0_steppings },
236	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
237	  pxa2x0_steppings },
238	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA250",
239	  pxa2x0_steppings },
240	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
241	  pxa2x0_steppings },
242
243	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
244	  ixp425_steppings },
245	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
246	  ixp425_steppings },
247	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
248	  ixp425_steppings },
249
250	{ 0, CPU_CLASS_NONE, NULL, NULL }
251};
252
253struct cpu_classtab {
254	const char	*class_name;
255	const char	*class_option;
256};
257
258const struct cpu_classtab cpu_classes[] = {
259	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
260	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
261	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
262	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
263	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
264	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
265	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
266	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
267	{ "ARM9TDMI",	NULL },			/* CPU_CLASS_ARM9TDMI */
268	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
269	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
270	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
271	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
272};
273
274/*
275 * Report the type of the specified arm processor. This uses the generic and
276 * arm specific information in the cpu structure to identify the processor.
277 * The remaining fields in the cpu structure are filled in appropriately.
278 */
279
280static const char * const wtnames[] = {
281	"write-through",
282	"write-back",
283	"write-back",
284	"**unknown 3**",
285	"**unknown 4**",
286	"write-back-locking",		/* XXX XScale-specific? */
287	"write-back-locking-A",
288	"write-back-locking-B",
289	"**unknown 8**",
290	"**unknown 9**",
291	"**unknown 10**",
292	"**unknown 11**",
293	"**unknown 12**",
294	"**unknown 13**",
295	"**unknown 14**",
296	"**unknown 15**",
297};
298
299extern int ctrl;
300void
301identify_arm_cpu(void)
302{
303	u_int cpuid;
304	enum cpu_class cpu_class = CPU_CLASS_NONE;
305	int i;
306
307	cpuid = cpu_id();
308
309	if (cpuid == 0) {
310		printf("Processor failed probe - no CPU ID\n");
311		return;
312	}
313
314	for (i = 0; cpuids[i].cpuid != 0; i++)
315		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
316			cpu_class = cpuids[i].cpu_class;
317			printf("%s %s (%s core)\n",
318			    cpuids[i].cpu_name,
319			    cpuids[i].cpu_steppings[cpuid &
320			    CPU_ID_REVISION_MASK],
321			    cpu_classes[cpu_class].class_name);
322			break;
323		}
324	if (cpuids[i].cpuid == 0)
325		printf("unknown CPU (ID = 0x%x)\n", cpuid);
326
327	switch (cpu_class) {
328	case CPU_CLASS_ARM6:
329	case CPU_CLASS_ARM7:
330	case CPU_CLASS_ARM7TDMI:
331	case CPU_CLASS_ARM8:
332		if ((ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
333			printf(" IDC disabled");
334		else
335			printf(" IDC enabled");
336		break;
337	case CPU_CLASS_ARM9TDMI:
338	case CPU_CLASS_ARM10E:
339	case CPU_CLASS_SA1:
340	case CPU_CLASS_XSCALE:
341		if ((ctrl & CPU_CONTROL_DC_ENABLE) == 0)
342			printf(" DC disabled");
343		else
344			printf(" DC enabled");
345		if ((ctrl & CPU_CONTROL_IC_ENABLE) == 0)
346			printf(" IC disabled");
347		else
348			printf(" IC enabled");
349		break;
350	default:
351		break;
352	}
353	if ((ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
354		printf(" WB disabled");
355	else
356		printf(" WB enabled");
357
358	if (ctrl & CPU_CONTROL_LABT_ENABLE)
359		printf(" LABT");
360	else
361		printf(" EABT");
362
363	if (ctrl & CPU_CONTROL_BPRD_ENABLE)
364		printf(" branch prediction enabled");
365
366	/* Print cache info. */
367	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
368		return;
369
370	if (arm_pcache_unified) {
371 		printf("%dKB/%dB %d-way %s unified cache\n",
372		    arm_pdcache_size / 1024,
373		    arm_pdcache_line_size, arm_pdcache_ways,
374		    wtnames[arm_pcache_type]);
375	} else {
376		printf("%dKB/%dB %d-way Instruction cache\n",
377		    arm_picache_size / 1024,
378		    arm_picache_line_size, arm_picache_ways);
379		printf("%dKB/%dB %d-way %s Data cache\n",
380		    arm_pdcache_size / 1024,
381		    arm_pdcache_line_size, arm_pdcache_ways,
382		    wtnames[arm_pcache_type]);
383	}
384	printf("\n");
385}
386
387