]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/identcpu-v4.c
Upgrade Unbound to 1.6.2. More to follow.
[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 static 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
129 struct 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
136 const 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
223 struct cpu_classtab {
224         const char      *class_name;
225         const char      *class_option;
226 };
227
228 const 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
245 static 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
264 static void
265 print_enadis(int enadis, char *s)
266 {
267
268         printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
269 }
270
271 enum cpu_class cpu_class = CPU_CLASS_NONE;
272
273 u_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
294 void
295 identify_arm_cpu(void)
296 {
297         u_int cpuid, ctrl;
298         int i;
299
300         ctrl = cpu_get_control();
301         cpuid = cpu_ident();
302
303         if (cpuid == 0) {
304                 printf("Processor failed probe - no CPU ID\n");
305                 return;
306         }
307
308         for (i = 0; cpuids[i].cpuid != 0; i++)
309                 if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
310                         cpu_class = cpuids[i].cpu_class;
311                         printf("CPU: %s %s (%s core)\n",
312                             cpuids[i].cpu_name,
313                             cpuids[i].cpu_steppings[cpuid &
314                             CPU_ID_REVISION_MASK],
315                             cpu_classes[cpu_class].class_name);
316                         break;
317                 }
318         if (cpuids[i].cpuid == 0)
319                 printf("unknown CPU (ID = 0x%x)\n", cpuid);
320
321         printf(" ");
322
323         if (ctrl & CPU_CONTROL_BEND_ENABLE)
324                 printf(" Big-endian");
325         else
326                 printf(" Little-endian");
327
328         switch (cpu_class) {
329         case CPU_CLASS_ARM9TDMI:
330         case CPU_CLASS_ARM9ES:
331         case CPU_CLASS_ARM9EJS:
332         case CPU_CLASS_ARM10E:
333         case CPU_CLASS_ARM10EJ:
334         case CPU_CLASS_XSCALE:
335         case CPU_CLASS_MARVELL:
336                 print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
337                 print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
338 #ifdef CPU_XSCALE_81342
339                 print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
340 #endif
341 #if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
342                 i = sheeva_control_ext(0, 0);
343                 print_enadis(i & MV_WA_ENABLE, "WA");
344                 print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
345                 printf("\n ");
346                 print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
347                 print_enadis(i & MV_L2_ENABLE, "L2");
348                 print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
349                     "L2 prefetch");
350                 printf("\n ");
351 #endif
352                 break;
353         default:
354                 break;
355         }
356
357         print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
358         if (ctrl & CPU_CONTROL_LABT_ENABLE)
359                 printf(" LABT");
360         else
361                 printf(" EABT");
362
363         print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
364         printf("\n");
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 }