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/11/sys/arm/arm/identcpu-v4.c 314530 2017-03-02 01:18:46Z ian $");
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/sysctl.h>
51#include <machine/cpu.h>
52#include <machine/endian.h>
53
54#include <machine/md_var.h>
55
56char machine[] = "arm";
57
58SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
59	machine, 0, "Machine class");
60
61static const char * const generic_steppings[16] = {
62	"rev 0",	"rev 1",	"rev 2",	"rev 3",
63	"rev 4",	"rev 5",	"rev 6",	"rev 7",
64	"rev 8",	"rev 9",	"rev 10",	"rev 11",
65	"rev 12",	"rev 13",	"rev 14",	"rev 15",
66};
67
68static const char * const xscale_steppings[16] = {
69	"step A-0",	"step A-1",	"step B-0",	"step C-0",
70	"step D-0",	"rev 5",	"rev 6",	"rev 7",
71	"rev 8",	"rev 9",	"rev 10",	"rev 11",
72	"rev 12",	"rev 13",	"rev 14",	"rev 15",
73};
74
75static const char * const i80219_steppings[16] = {
76	"step A-0",	"rev 1",	"rev 2",	"rev 3",
77	"rev 4",	"rev 5",	"rev 6",	"rev 7",
78	"rev 8",	"rev 9",	"rev 10",	"rev 11",
79	"rev 12",	"rev 13",	"rev 14",	"rev 15",
80};
81
82static const char * const i80321_steppings[16] = {
83	"step A-0",	"step B-0",	"rev 2",	"rev 3",
84	"rev 4",	"rev 5",	"rev 6",	"rev 7",
85	"rev 8",	"rev 9",	"rev 10",	"rev 11",
86	"rev 12",	"rev 13",	"rev 14",	"rev 15",
87};
88
89static const char * const i81342_steppings[16] = {
90	"step A-0",	"rev 1",	"rev 2",	"rev 3",
91	"rev 4",	"rev 5",	"rev 6",	"rev 7",
92	"rev 8",	"rev 9",	"rev 10",	"rev 11",
93	"rev 12",	"rev 13",	"rev 14",	"rev 15",
94};
95
96/* Steppings for PXA2[15]0 */
97static const char * const pxa2x0_steppings[16] = {
98	"step A-0",	"step A-1",	"step B-0",	"step B-1",
99	"step B-2",	"step C-0",	"rev 6",	"rev 7",
100	"rev 8",	"rev 9",	"rev 10",	"rev 11",
101	"rev 12",	"rev 13",	"rev 14",	"rev 15",
102};
103
104/* Steppings for PXA255/26x.
105 * rev 5: PXA26x B0, rev 6: PXA255 A0
106 */
107static const char * const pxa255_steppings[16] = {
108	"rev 0",	"rev 1",	"rev 2",	"step A-0",
109	"rev 4",	"step B-0",	"step A-0",	"rev 7",
110	"rev 8",	"rev 9",	"rev 10",	"rev 11",
111	"rev 12",	"rev 13",	"rev 14",	"rev 15",
112};
113
114/* Stepping for PXA27x */
115static const char * const pxa27x_steppings[16] = {
116	"step A-0",	"step A-1",	"step B-0",	"step B-1",
117	"step C-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 ixp425_steppings[16] = {
123	"step 0 (A0)",	"rev 1 (ARMv5TE)", "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
129struct cpuidtab {
130	u_int32_t	cpuid;
131	enum		cpu_class cpu_class;
132	const char	*cpu_name;
133	const char * const *cpu_steppings;
134};
135
136const struct cpuidtab cpuids[] = {
137	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
138	  generic_steppings },
139	{ CPU_ID_ARM920T_ALT,	CPU_CLASS_ARM9TDMI,	"ARM920T",
140	  generic_steppings },
141	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
142	  generic_steppings },
143	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
144	  generic_steppings },
145	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
146	  generic_steppings },
147	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
148	  generic_steppings },
149	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
150	  generic_steppings },
151	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
152	  generic_steppings },
153	{ CPU_ID_FA526,		CPU_CLASS_ARM9TDMI,	"FA526",
154	  generic_steppings },
155	{ CPU_ID_FA626TE,	CPU_CLASS_ARM9ES,	"FA626TE",
156	  generic_steppings },
157
158	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
159	  generic_steppings },
160
161	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
162	  generic_steppings },
163	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
164	  generic_steppings },
165	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
166	  generic_steppings },
167
168	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
169	  xscale_steppings },
170
171	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
172	  i80321_steppings },
173	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
174	  i80321_steppings },
175	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
176	  i80321_steppings },
177	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
178	  i80321_steppings },
179
180	{ CPU_ID_81342,		CPU_CLASS_XSCALE,	"i81342",
181	  i81342_steppings },
182
183	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
184	  i80219_steppings },
185	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
186	  i80219_steppings },
187
188	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
189	  pxa27x_steppings },
190	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
191	  pxa2x0_steppings },
192	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
193	  pxa2x0_steppings },
194	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
195	  pxa2x0_steppings },
196	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
197	  pxa2x0_steppings },
198	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255",
199	  pxa255_steppings },
200	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
201	  pxa2x0_steppings },
202
203	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
204	  ixp425_steppings },
205	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
206	  ixp425_steppings },
207	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
208	  ixp425_steppings },
209
210	/* XXX ixp435 steppings? */
211	{ CPU_ID_IXP435,	CPU_CLASS_XSCALE,	"IXP435",
212	  ixp425_steppings },
213
214	{ CPU_ID_MV88FR131,	CPU_CLASS_MARVELL,	"Feroceon 88FR131",
215	  generic_steppings },
216
217	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_MARVELL,	"Feroceon 88FR571-VD",
218	  generic_steppings },
219
220	{ 0, CPU_CLASS_NONE, NULL, NULL }
221};
222
223struct cpu_classtab {
224	const char	*class_name;
225	const char	*class_option;
226};
227
228const struct cpu_classtab cpu_classes[] = {
229	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
230	{ "ARM9TDMI",	"CPU_ARM9TDMI" },	/* CPU_CLASS_ARM9TDMI */
231	{ "ARM9E-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9ES */
232	{ "ARM9EJ-S",	"CPU_ARM9E" },		/* CPU_CLASS_ARM9EJS */
233	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
234	{ "ARM10EJ",	"CPU_ARM10" },		/* CPU_CLASS_ARM10EJ */
235	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
236	{ "Marvell",	"CPU_MARVELL" },	/* CPU_CLASS_MARVELL */
237};
238
239/*
240 * Report the type of the specified arm processor. This uses the generic and
241 * arm specific information in the cpu structure to identify the processor.
242 * The remaining fields in the cpu structure are filled in appropriately.
243 */
244
245static const char * const wtnames[] = {
246	"write-through",
247	"write-back",
248	"write-back",
249	"**unknown 3**",
250	"**unknown 4**",
251	"write-back-locking",		/* XXX XScale-specific? */
252	"write-back-locking-A",
253	"write-back-locking-B",
254	"**unknown 8**",
255	"**unknown 9**",
256	"**unknown 10**",
257	"**unknown 11**",
258	"**unknown 12**",
259	"**unknown 13**",
260	"write-back-locking-C",
261	"**unknown 15**",
262};
263
264static void
265print_enadis(int enadis, char *s)
266{
267
268	printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
269}
270
271enum cpu_class cpu_class = CPU_CLASS_NONE;
272
273u_int cpu_pfr(int num)
274{
275	u_int feat;
276
277	switch (num) {
278	case 0:
279		__asm __volatile("mrc p15, 0, %0, c0, c1, 0"
280		    : "=r" (feat));
281		break;
282	case 1:
283		__asm __volatile("mrc p15, 0, %0, c0, c1, 1"
284		    : "=r" (feat));
285		break;
286	default:
287		panic("Processor Feature Register %d not implemented", num);
288		break;
289	}
290
291	return (feat);
292}
293
294void
295identify_arm_cpu(void)
296{
297	u_int cpuid;
298	u_int8_t ctrl;
299	int i;
300
301	ctrl = cpu_get_control();
302	cpuid = cpu_ident();
303
304	if (cpuid == 0) {
305		printf("Processor failed probe - no CPU ID\n");
306		return;
307	}
308
309	for (i = 0; cpuids[i].cpuid != 0; i++)
310		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
311			cpu_class = cpuids[i].cpu_class;
312			printf("CPU: %s %s (%s core)\n",
313			    cpuids[i].cpu_name,
314			    cpuids[i].cpu_steppings[cpuid &
315			    CPU_ID_REVISION_MASK],
316			    cpu_classes[cpu_class].class_name);
317			break;
318		}
319	if (cpuids[i].cpuid == 0)
320		printf("unknown CPU (ID = 0x%x)\n", cpuid);
321
322	printf(" ");
323
324	if (ctrl & CPU_CONTROL_BEND_ENABLE)
325		printf(" Big-endian");
326	else
327		printf(" Little-endian");
328
329	switch (cpu_class) {
330	case CPU_CLASS_ARM9TDMI:
331	case CPU_CLASS_ARM9ES:
332	case CPU_CLASS_ARM9EJS:
333	case CPU_CLASS_ARM10E:
334	case CPU_CLASS_ARM10EJ:
335	case CPU_CLASS_XSCALE:
336	case CPU_CLASS_MARVELL:
337		print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
338		print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
339#ifdef CPU_XSCALE_81342
340		print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
341#endif
342#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
343		i = sheeva_control_ext(0, 0);
344		print_enadis(i & MV_WA_ENABLE, "WA");
345		print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
346		printf("\n ");
347		print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
348		print_enadis(i & MV_L2_ENABLE, "L2");
349		print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
350		    "L2 prefetch");
351		printf("\n ");
352#endif
353		break;
354	default:
355		break;
356	}
357
358	print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
359	if (ctrl & CPU_CONTROL_LABT_ENABLE)
360		printf(" LABT");
361	else
362		printf(" EABT");
363
364	print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
365	printf("\n");
366
367	/* Print cache info. */
368	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
369		return;
370
371	if (arm_pcache_unified) {
372		printf("  %dKB/%dB %d-way %s unified cache\n",
373		    arm_pdcache_size / 1024,
374		    arm_pdcache_line_size, arm_pdcache_ways,
375		    wtnames[arm_pcache_type]);
376	} else {
377		printf("  %dKB/%dB %d-way instruction cache\n",
378		    arm_picache_size / 1024,
379		    arm_picache_line_size, arm_picache_ways);
380		printf("  %dKB/%dB %d-way %s data cache\n",
381		    arm_pdcache_size / 1024,
382		    arm_pdcache_line_size, arm_pdcache_ways,
383		    wtnames[arm_pcache_type]);
384	}
385}
386