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/12/sys/arm/arm/identcpu-v4.c 337762 2018-08-14 16:01:25Z andrew $");
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
56 char machine[] = "arm";
57
58 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
59 machine, 0, "Machine class");
60
61 static 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
68 static 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
75 static 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
82 static 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
89 static 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 */
97 static 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 */
107 static 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 */
115 static 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
122 struct cpuidtab {
123 u_int32_t cpuid;
124 enum cpu_class cpu_class;
125 const char *cpu_name;
126 const char * const *cpu_steppings;
127 };
128
129 const struct cpuidtab cpuids[] = {
130 { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
131 generic_steppings },
132 { CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T",
133 generic_steppings },
134 { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
135 generic_steppings },
136 { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S",
137 generic_steppings },
138 { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
139 generic_steppings },
140 { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
141 generic_steppings },
142 { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
143 generic_steppings },
144 { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
145 generic_steppings },
146 { CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526",
147 generic_steppings },
148 { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
149 generic_steppings },
150
151 { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
152 generic_steppings },
153
154 { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E",
155 generic_steppings },
156 { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S",
157 generic_steppings },
158 { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
159 generic_steppings },
160
161 { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
162 xscale_steppings },
163
164 { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
165 i80321_steppings },
166 { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
167 i80321_steppings },
168 { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
169 i80321_steppings },
170 { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
171 i80321_steppings },
172
173 { CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
174 i81342_steppings },
175
176 { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
177 i80219_steppings },
178 { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
179 i80219_steppings },
180
181 { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
182 pxa27x_steppings },
183 { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
184 pxa2x0_steppings },
185 { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
186 pxa2x0_steppings },
187 { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
188 pxa2x0_steppings },
189 { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
190 pxa2x0_steppings },
191 { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
192 pxa255_steppings },
193 { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
194 pxa2x0_steppings },
195
196 { CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
197 generic_steppings },
198
199 { CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD",
200 generic_steppings },
201
202 { 0, CPU_CLASS_NONE, NULL, NULL }
203 };
204
205 struct cpu_classtab {
206 const char *class_name;
207 const char *class_option;
208 };
209
210 const struct cpu_classtab cpu_classes[] = {
211 { "unknown", NULL }, /* CPU_CLASS_NONE */
212 { "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */
213 { "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */
214 { "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */
215 { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */
216 { "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */
217 { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */
218 { "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */
219 };
220
221 /*
222 * Report the type of the specified arm processor. This uses the generic and
223 * arm specific information in the cpu structure to identify the processor.
224 * The remaining fields in the cpu structure are filled in appropriately.
225 */
226
227 static const char * const wtnames[] = {
228 "write-through",
229 "write-back",
230 "write-back",
231 "**unknown 3**",
232 "**unknown 4**",
233 "write-back-locking", /* XXX XScale-specific? */
234 "write-back-locking-A",
235 "write-back-locking-B",
236 "**unknown 8**",
237 "**unknown 9**",
238 "**unknown 10**",
239 "**unknown 11**",
240 "**unknown 12**",
241 "**unknown 13**",
242 "write-back-locking-C",
243 "**unknown 15**",
244 };
245
246 static void
print_enadis(int enadis,char * s)247 print_enadis(int enadis, char *s)
248 {
249
250 printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
251 }
252
253 enum cpu_class cpu_class = CPU_CLASS_NONE;
254
255 void
identify_arm_cpu(void)256 identify_arm_cpu(void)
257 {
258 u_int cpuid, ctrl;
259 int i;
260
261 ctrl = cp15_sctlr_get();
262 cpuid = cp15_midr_get();
263
264 if (cpuid == 0) {
265 printf("Processor failed probe - no CPU ID\n");
266 return;
267 }
268
269 for (i = 0; cpuids[i].cpuid != 0; i++)
270 if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
271 cpu_class = cpuids[i].cpu_class;
272 printf("CPU: %s %s (%s core)\n",
273 cpuids[i].cpu_name,
274 cpuids[i].cpu_steppings[cpuid &
275 CPU_ID_REVISION_MASK],
276 cpu_classes[cpu_class].class_name);
277 break;
278 }
279 if (cpuids[i].cpuid == 0)
280 printf("unknown CPU (ID = 0x%x)\n", cpuid);
281
282 printf(" ");
283
284 if (ctrl & CPU_CONTROL_BEND_ENABLE)
285 printf(" Big-endian");
286 else
287 printf(" Little-endian");
288
289 switch (cpu_class) {
290 case CPU_CLASS_ARM9TDMI:
291 case CPU_CLASS_ARM9ES:
292 case CPU_CLASS_ARM9EJS:
293 case CPU_CLASS_ARM10E:
294 case CPU_CLASS_ARM10EJ:
295 case CPU_CLASS_XSCALE:
296 case CPU_CLASS_MARVELL:
297 print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
298 print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
299 #if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
300 i = sheeva_control_ext(0, 0);
301 print_enadis(i & MV_WA_ENABLE, "WA");
302 print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
303 printf("\n ");
304 print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
305 print_enadis(i & MV_L2_ENABLE, "L2");
306 print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
307 "L2 prefetch");
308 printf("\n ");
309 #endif
310 break;
311 default:
312 break;
313 }
314
315 print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
316 if (ctrl & CPU_CONTROL_LABT_ENABLE)
317 printf(" LABT");
318 else
319 printf(" EABT");
320
321 print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
322 printf("\n");
323
324 /* Print cache info. */
325 if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
326 return;
327
328 if (arm_pcache_unified) {
329 printf(" %dKB/%dB %d-way %s unified cache\n",
330 arm_pdcache_size / 1024,
331 arm_pdcache_line_size, arm_pdcache_ways,
332 wtnames[arm_pcache_type]);
333 } else {
334 printf(" %dKB/%dB %d-way instruction cache\n",
335 arm_picache_size / 1024,
336 arm_picache_line_size, arm_picache_ways);
337 printf(" %dKB/%dB %d-way %s data cache\n",
338 arm_pdcache_size / 1024,
339 arm_pdcache_line_size, arm_pdcache_ways,
340 wtnames[arm_pcache_type]);
341 }
342 }
343