]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/identcpu-v4.c
Merge libc++ trunk r338150, and resolve conflicts.
[FreeBSD/FreeBSD.git] / sys / arm / arm / identcpu-v4.c
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$");
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
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 u_int cpu_pfr(int num)
256 {
257         u_int feat;
258
259         switch (num) {
260         case 0:
261                 __asm __volatile("mrc p15, 0, %0, c0, c1, 0"
262                     : "=r" (feat));
263                 break;
264         case 1:
265                 __asm __volatile("mrc p15, 0, %0, c0, c1, 1"
266                     : "=r" (feat));
267                 break;
268         default:
269                 panic("Processor Feature Register %d not implemented", num);
270                 break;
271         }
272
273         return (feat);
274 }
275
276 void
277 identify_arm_cpu(void)
278 {
279         u_int cpuid, ctrl;
280         int i;
281
282         ctrl = cp15_sctlr_get();
283         cpuid = cp15_midr_get();
284
285         if (cpuid == 0) {
286                 printf("Processor failed probe - no CPU ID\n");
287                 return;
288         }
289
290         for (i = 0; cpuids[i].cpuid != 0; i++)
291                 if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
292                         cpu_class = cpuids[i].cpu_class;
293                         printf("CPU: %s %s (%s core)\n",
294                             cpuids[i].cpu_name,
295                             cpuids[i].cpu_steppings[cpuid &
296                             CPU_ID_REVISION_MASK],
297                             cpu_classes[cpu_class].class_name);
298                         break;
299                 }
300         if (cpuids[i].cpuid == 0)
301                 printf("unknown CPU (ID = 0x%x)\n", cpuid);
302
303         printf(" ");
304
305         if (ctrl & CPU_CONTROL_BEND_ENABLE)
306                 printf(" Big-endian");
307         else
308                 printf(" Little-endian");
309
310         switch (cpu_class) {
311         case CPU_CLASS_ARM9TDMI:
312         case CPU_CLASS_ARM9ES:
313         case CPU_CLASS_ARM9EJS:
314         case CPU_CLASS_ARM10E:
315         case CPU_CLASS_ARM10EJ:
316         case CPU_CLASS_XSCALE:
317         case CPU_CLASS_MARVELL:
318                 print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
319                 print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
320 #if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
321                 i = sheeva_control_ext(0, 0);
322                 print_enadis(i & MV_WA_ENABLE, "WA");
323                 print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
324                 printf("\n ");
325                 print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
326                 print_enadis(i & MV_L2_ENABLE, "L2");
327                 print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
328                     "L2 prefetch");
329                 printf("\n ");
330 #endif
331                 break;
332         default:
333                 break;
334         }
335
336         print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
337         if (ctrl & CPU_CONTROL_LABT_ENABLE)
338                 printf(" LABT");
339         else
340                 printf(" EABT");
341
342         print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
343         printf("\n");
344
345         /* Print cache info. */
346         if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
347                 return;
348
349         if (arm_pcache_unified) {
350                 printf("  %dKB/%dB %d-way %s unified cache\n",
351                     arm_pdcache_size / 1024,
352                     arm_pdcache_line_size, arm_pdcache_ways,
353                     wtnames[arm_pcache_type]);
354         } else {
355                 printf("  %dKB/%dB %d-way instruction cache\n",
356                     arm_picache_size / 1024,
357                     arm_picache_line_size, arm_picache_ways);
358                 printf("  %dKB/%dB %d-way %s data cache\n",
359                     arm_pdcache_size / 1024,
360                     arm_pdcache_line_size, arm_pdcache_ways,
361                     wtnames[arm_pcache_type]);
362         }
363 }