identcpu-v4.c revision 155242
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 155242 2006-02-03 06:39:57Z 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 },
190152653Scognet	{ CPU_ID_ARM920T_ALT,	CPU_CLASS_ARM9TDMI,	"ARM920T",
191152653Scognet	  generic_steppings },
192129198Scognet	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
193129198Scognet	  generic_steppings },
194129198Scognet	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
195129198Scognet	  generic_steppings },
196129198Scognet	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
197129198Scognet	  generic_steppings },
198129198Scognet	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
199129198Scognet	  generic_steppings },
200129198Scognet	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
201129198Scognet	  generic_steppings },
202129198Scognet	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
203129198Scognet	  generic_steppings },
204129198Scognet
205129198Scognet	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
206129198Scognet	  generic_steppings },
207129198Scognet	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
208129198Scognet	  generic_steppings },
209129198Scognet
210129198Scognet	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
211129198Scognet	  sa110_steppings },
212129198Scognet	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
213129198Scognet	  sa1100_steppings },
214129198Scognet	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
215129198Scognet	  sa1110_steppings },
216129198Scognet
217129198Scognet	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
218129198Scognet	  ixp12x0_steppings },
219129198Scognet
220129198Scognet	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
221129198Scognet	  xscale_steppings },
222129198Scognet
223129198Scognet	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
224129198Scognet	  i80321_steppings },
225129198Scognet	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
226129198Scognet	  i80321_steppings },
227129198Scognet	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
228129198Scognet	  i80321_steppings },
229129198Scognet	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
230129198Scognet	  i80321_steppings },
231129198Scognet
232129198Scognet	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
233129198Scognet	  pxa2x0_steppings },
234129198Scognet	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
235129198Scognet	  pxa2x0_steppings },
236129198Scognet	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
237129198Scognet	  pxa2x0_steppings },
238129198Scognet	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
239129198Scognet	  pxa2x0_steppings },
240129198Scognet	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA250",
241129198Scognet	  pxa2x0_steppings },
242129198Scognet	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
243129198Scognet	  pxa2x0_steppings },
244129198Scognet
245129198Scognet	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
246129198Scognet	  ixp425_steppings },
247129198Scognet	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
248129198Scognet	  ixp425_steppings },
249129198Scognet	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
250129198Scognet	  ixp425_steppings },
251129198Scognet
252129198Scognet	{ 0, CPU_CLASS_NONE, NULL, NULL }
253129198Scognet};
254129198Scognet
255129198Scognetstruct cpu_classtab {
256129198Scognet	const char	*class_name;
257129198Scognet	const char	*class_option;
258129198Scognet};
259129198Scognet
260129198Scognetconst struct cpu_classtab cpu_classes[] = {
261129198Scognet	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
262129198Scognet	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
263129198Scognet	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
264129198Scognet	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
265129198Scognet	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
266129198Scognet	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
267129198Scognet	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
268129198Scognet	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
269155242Simp	{ "ARM9TDMI",	"CPU_ARM9TDMI" },	/* CPU_CLASS_ARM9TDMI */
270129198Scognet	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
271129198Scognet	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
272129198Scognet	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
273129198Scognet	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
274129198Scognet};
275129198Scognet
276129198Scognet/*
277129198Scognet * Report the type of the specified arm processor. This uses the generic and
278129198Scognet * arm specific information in the cpu structure to identify the processor.
279129198Scognet * The remaining fields in the cpu structure are filled in appropriately.
280129198Scognet */
281129198Scognet
282129198Scognetstatic const char * const wtnames[] = {
283129198Scognet	"write-through",
284129198Scognet	"write-back",
285129198Scognet	"write-back",
286129198Scognet	"**unknown 3**",
287129198Scognet	"**unknown 4**",
288129198Scognet	"write-back-locking",		/* XXX XScale-specific? */
289129198Scognet	"write-back-locking-A",
290129198Scognet	"write-back-locking-B",
291129198Scognet	"**unknown 8**",
292129198Scognet	"**unknown 9**",
293129198Scognet	"**unknown 10**",
294129198Scognet	"**unknown 11**",
295129198Scognet	"**unknown 12**",
296129198Scognet	"**unknown 13**",
297129198Scognet	"**unknown 14**",
298129198Scognet	"**unknown 15**",
299129198Scognet};
300129198Scognet
301153940Snetchildvoid setPQL2(int *const size, int *const ways);
302153940Snetchild
303153940Snetchildvoid
304153940SnetchildsetPQL2(int *const size, int *const ways)
305153940Snetchild{
306153940Snetchild	return;
307153940Snetchild}
308153940Snetchild
309153940Snetchild
310129198Scognetextern int ctrl;
311129198Scognetvoid
312129198Scognetidentify_arm_cpu(void)
313129198Scognet{
314129198Scognet	u_int cpuid;
315129198Scognet	enum cpu_class cpu_class = CPU_CLASS_NONE;
316129198Scognet	int i;
317129198Scognet
318129198Scognet	cpuid = cpu_id();
319129198Scognet
320129198Scognet	if (cpuid == 0) {
321129198Scognet		printf("Processor failed probe - no CPU ID\n");
322129198Scognet		return;
323129198Scognet	}
324129198Scognet
325129198Scognet	for (i = 0; cpuids[i].cpuid != 0; i++)
326129198Scognet		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
327129198Scognet			cpu_class = cpuids[i].cpu_class;
328155242Simp			printf("CPU: %s %s (%s core)\n",
329129198Scognet			    cpuids[i].cpu_name,
330129198Scognet			    cpuids[i].cpu_steppings[cpuid &
331129198Scognet			    CPU_ID_REVISION_MASK],
332129198Scognet			    cpu_classes[cpu_class].class_name);
333129198Scognet			break;
334129198Scognet		}
335129198Scognet	if (cpuids[i].cpuid == 0)
336129198Scognet		printf("unknown CPU (ID = 0x%x)\n", cpuid);
337129198Scognet
338155242Simp	printf(" ");
339129198Scognet	switch (cpu_class) {
340129198Scognet	case CPU_CLASS_ARM6:
341129198Scognet	case CPU_CLASS_ARM7:
342129198Scognet	case CPU_CLASS_ARM7TDMI:
343129198Scognet	case CPU_CLASS_ARM8:
344129198Scognet		if ((ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
345129198Scognet			printf(" IDC disabled");
346129198Scognet		else
347129198Scognet			printf(" IDC enabled");
348129198Scognet		break;
349129198Scognet	case CPU_CLASS_ARM9TDMI:
350129198Scognet	case CPU_CLASS_ARM10E:
351129198Scognet	case CPU_CLASS_SA1:
352129198Scognet	case CPU_CLASS_XSCALE:
353129198Scognet		if ((ctrl & CPU_CONTROL_DC_ENABLE) == 0)
354129198Scognet			printf(" DC disabled");
355129198Scognet		else
356129198Scognet			printf(" DC enabled");
357129198Scognet		if ((ctrl & CPU_CONTROL_IC_ENABLE) == 0)
358129198Scognet			printf(" IC disabled");
359129198Scognet		else
360129198Scognet			printf(" IC enabled");
361129198Scognet		break;
362129198Scognet	default:
363129198Scognet		break;
364129198Scognet	}
365129198Scognet	if ((ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
366129198Scognet		printf(" WB disabled");
367129198Scognet	else
368129198Scognet		printf(" WB enabled");
369129198Scognet
370129198Scognet	if (ctrl & CPU_CONTROL_LABT_ENABLE)
371129198Scognet		printf(" LABT");
372129198Scognet	else
373129198Scognet		printf(" EABT");
374129198Scognet
375129198Scognet	if (ctrl & CPU_CONTROL_BPRD_ENABLE)
376129198Scognet		printf(" branch prediction enabled");
377129198Scognet
378155242Simp	printf("\n");
379137272Scognet	/* Print cache info. */
380137272Scognet	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
381137272Scognet		return;
382137272Scognet
383137272Scognet	if (arm_pcache_unified) {
384155242Simp 		printf("  %dKB/%dB %d-way %s unified cache\n",
385137272Scognet		    arm_pdcache_size / 1024,
386137272Scognet		    arm_pdcache_line_size, arm_pdcache_ways,
387137272Scognet		    wtnames[arm_pcache_type]);
388137272Scognet	} else {
389155242Simp		printf("  %dKB/%dB %d-way Instruction cache\n",
390137272Scognet		    arm_picache_size / 1024,
391137272Scognet		    arm_picache_line_size, arm_picache_ways);
392155242Simp		printf("  %dKB/%dB %d-way %s Data cache\n",
393137272Scognet		    arm_pdcache_size / 1024,
394137272Scognet		    arm_pdcache_line_size, arm_pdcache_ways,
395137272Scognet		    wtnames[arm_pcache_type]);
396137272Scognet	}
397129198Scognet}
398129198Scognet
399