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