identcpu-v4.c revision 139735
1129198Scognet/* $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 1995 Mark Brinicombe. 5129198Scognet * Copyright (c) 1995 Brini. 6129198Scognet * All rights reserved. 7129198Scognet * 8129198Scognet * Redistribution and use in source and binary forms, with or without 9129198Scognet * modification, are permitted provided that the following conditions 10129198Scognet * are met: 11129198Scognet * 1. Redistributions of source code must retain the above copyright 12129198Scognet * notice, this list of conditions and the following disclaimer. 13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 14129198Scognet * notice, this list of conditions and the following disclaimer in the 15129198Scognet * documentation and/or other materials provided with the distribution. 16129198Scognet * 3. All advertising materials mentioning features or use of this software 17129198Scognet * must display the following acknowledgement: 18129198Scognet * This product includes software developed by Brini. 19129198Scognet * 4. The name of the company nor the name of the author may be used to 20129198Scognet * endorse or promote products derived from this software without specific 21129198Scognet * prior written permission. 22129198Scognet * 23129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 24129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26129198Scognet * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33129198Scognet * SUCH DAMAGE. 34129198Scognet * 35129198Scognet * RiscBSD kernel project 36129198Scognet * 37129198Scognet * cpu.c 38129198Scognet * 39129198Scognet * Probing and configuration for the master CPU 40129198Scognet * 41129198Scognet * Created : 10/10/95 42129198Scognet */ 43129198Scognet 44129198Scognet#include <sys/cdefs.h> 45129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/identcpu.c 139735 2005-01-05 21:58:49Z imp $"); 46129198Scognet#include <sys/systm.h> 47129198Scognet#include <sys/param.h> 48129198Scognet#include <sys/malloc.h> 49129198Scognet#include <sys/time.h> 50129198Scognet#include <sys/proc.h> 51129198Scognet#include <sys/conf.h> 52135652Scognet#include <sys/kernel.h> 53135652Scognet#include <sys/sysctl.h> 54129198Scognet#include <machine/cpu.h> 55129198Scognet 56129198Scognet#include <machine/cpuconf.h> 57129198Scognet 58129198Scognetchar machine[] = "arm"; 59129198Scognet 60135652ScognetSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, 61135652Scognet machine, 0, "Machine class"); 62129198Scognetenum cpu_class { 63129198Scognet CPU_CLASS_NONE, 64129198Scognet CPU_CLASS_ARM2, 65129198Scognet CPU_CLASS_ARM2AS, 66129198Scognet CPU_CLASS_ARM3, 67129198Scognet CPU_CLASS_ARM6, 68129198Scognet CPU_CLASS_ARM7, 69129198Scognet CPU_CLASS_ARM7TDMI, 70129198Scognet CPU_CLASS_ARM8, 71129198Scognet CPU_CLASS_ARM9TDMI, 72129198Scognet CPU_CLASS_ARM9ES, 73129198Scognet CPU_CLASS_ARM10E, 74129198Scognet CPU_CLASS_SA1, 75129198Scognet CPU_CLASS_XSCALE 76129198Scognet}; 77129198Scognet 78129198Scognetstatic const char * const generic_steppings[16] = { 79129198Scognet "rev 0", "rev 1", "rev 2", "rev 3", 80129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 81129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 82129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 83129198Scognet}; 84129198Scognet 85129198Scognetstatic const char * const sa110_steppings[16] = { 86129198Scognet "rev 0", "step J", "step K", "step S", 87129198Scognet "step T", "rev 5", "rev 6", "rev 7", 88129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 89129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 90129198Scognet}; 91129198Scognet 92129198Scognetstatic const char * const sa1100_steppings[16] = { 93129198Scognet "rev 0", "step B", "step C", "rev 3", 94129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 95129198Scognet "step D", "step E", "rev 10" "step G", 96129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 97129198Scognet}; 98129198Scognet 99129198Scognetstatic const char * const sa1110_steppings[16] = { 100129198Scognet "step A-0", "rev 1", "rev 2", "rev 3", 101129198Scognet "step B-0", "step B-1", "step B-2", "step B-3", 102129198Scognet "step B-4", "step B-5", "rev 10", "rev 11", 103129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 104129198Scognet}; 105129198Scognet 106129198Scognetstatic const char * const ixp12x0_steppings[16] = { 107129198Scognet "(IXP1200 step A)", "(IXP1200 step B)", 108129198Scognet "rev 2", "(IXP1200 step C)", 109129198Scognet "(IXP1200 step D)", "(IXP1240/1250 step A)", 110129198Scognet "(IXP1240 step B)", "(IXP1250 step B)", 111129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 112129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 113129198Scognet}; 114129198Scognet 115129198Scognetstatic const char * const xscale_steppings[16] = { 116129198Scognet "step A-0", "step A-1", "step B-0", "step C-0", 117129198Scognet "step D-0", "rev 5", "rev 6", "rev 7", 118129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 119129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 120129198Scognet}; 121129198Scognet 122129198Scognetstatic const char * const i80321_steppings[16] = { 123129198Scognet "step A-0", "step B-0", "rev 2", "rev 3", 124129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 125129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 126129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 127129198Scognet}; 128129198Scognet 129129198Scognetstatic const char * const pxa2x0_steppings[16] = { 130129198Scognet "step A-0", "step A-1", "step B-0", "step B-1", 131129198Scognet "step B-2", "step C-0", "rev 6", "rev 7", 132129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 133129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 134129198Scognet}; 135129198Scognet 136129198Scognetstatic const char * const ixp425_steppings[16] = { 137129198Scognet "step 0", "rev 1", "rev 2", "rev 3", 138129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 139129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 140129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 141129198Scognet}; 142129198Scognet 143129198Scognetstruct cpuidtab { 144129198Scognet u_int32_t cpuid; 145129198Scognet enum cpu_class cpu_class; 146129198Scognet const char *cpu_name; 147129198Scognet const char * const *cpu_steppings; 148129198Scognet}; 149129198Scognet 150129198Scognetconst struct cpuidtab cpuids[] = { 151129198Scognet { CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2", 152129198Scognet generic_steppings }, 153129198Scognet { CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250", 154129198Scognet generic_steppings }, 155129198Scognet 156129198Scognet { CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3", 157129198Scognet generic_steppings }, 158129198Scognet 159129198Scognet { CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600", 160129198Scognet generic_steppings }, 161129198Scognet { CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610", 162129198Scognet generic_steppings }, 163129198Scognet { CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620", 164129198Scognet generic_steppings }, 165129198Scognet 166129198Scognet { CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700", 167129198Scognet generic_steppings }, 168129198Scognet { CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710", 169129198Scognet generic_steppings }, 170129198Scognet { CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500", 171129198Scognet generic_steppings }, 172129198Scognet { CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a", 173129198Scognet generic_steppings }, 174129198Scognet { CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE", 175129198Scognet generic_steppings }, 176129198Scognet { CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T", 177129198Scognet generic_steppings }, 178129198Scognet { CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T", 179129198Scognet generic_steppings }, 180129198Scognet { CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)", 181129198Scognet generic_steppings }, 182129198Scognet { CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)", 183129198Scognet generic_steppings }, 184129198Scognet 185129198Scognet { CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810", 186129198Scognet generic_steppings }, 187129198Scognet 188129198Scognet { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T", 189129198Scognet generic_steppings }, 190129198Scognet { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T", 191129198Scognet generic_steppings }, 192129198Scognet { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T", 193129198Scognet generic_steppings }, 194129198Scognet { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S", 195129198Scognet generic_steppings }, 196129198Scognet { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S", 197129198Scognet generic_steppings }, 198129198Scognet { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", 199129198Scognet generic_steppings }, 200129198Scognet { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", 201129198Scognet generic_steppings }, 202129198Scognet 203129198Scognet { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E", 204129198Scognet generic_steppings }, 205129198Scognet { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S", 206129198Scognet generic_steppings }, 207129198Scognet 208129198Scognet { CPU_ID_SA110, CPU_CLASS_SA1, "SA-110", 209129198Scognet sa110_steppings }, 210129198Scognet { CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100", 211129198Scognet sa1100_steppings }, 212129198Scognet { CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110", 213129198Scognet sa1110_steppings }, 214129198Scognet 215129198Scognet { CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200", 216129198Scognet ixp12x0_steppings }, 217129198Scognet 218129198Scognet { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200", 219129198Scognet xscale_steppings }, 220129198Scognet 221129198Scognet { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz", 222129198Scognet i80321_steppings }, 223129198Scognet { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz", 224129198Scognet i80321_steppings }, 225129198Scognet { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz", 226129198Scognet i80321_steppings }, 227129198Scognet { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz", 228129198Scognet i80321_steppings }, 229129198Scognet 230129198Scognet { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250", 231129198Scognet pxa2x0_steppings }, 232129198Scognet { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210", 233129198Scognet pxa2x0_steppings }, 234129198Scognet { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250", 235129198Scognet pxa2x0_steppings }, 236129198Scognet { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210", 237129198Scognet pxa2x0_steppings }, 238129198Scognet { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA250", 239129198Scognet pxa2x0_steppings }, 240129198Scognet { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210", 241129198Scognet pxa2x0_steppings }, 242129198Scognet 243129198Scognet { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz", 244129198Scognet ixp425_steppings }, 245129198Scognet { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz", 246129198Scognet ixp425_steppings }, 247129198Scognet { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz", 248129198Scognet ixp425_steppings }, 249129198Scognet 250129198Scognet { 0, CPU_CLASS_NONE, NULL, NULL } 251129198Scognet}; 252129198Scognet 253129198Scognetstruct cpu_classtab { 254129198Scognet const char *class_name; 255129198Scognet const char *class_option; 256129198Scognet}; 257129198Scognet 258129198Scognetconst struct cpu_classtab cpu_classes[] = { 259129198Scognet { "unknown", NULL }, /* CPU_CLASS_NONE */ 260129198Scognet { "ARM2", "CPU_ARM2" }, /* CPU_CLASS_ARM2 */ 261129198Scognet { "ARM2as", "CPU_ARM250" }, /* CPU_CLASS_ARM2AS */ 262129198Scognet { "ARM3", "CPU_ARM3" }, /* CPU_CLASS_ARM3 */ 263129198Scognet { "ARM6", "CPU_ARM6" }, /* CPU_CLASS_ARM6 */ 264129198Scognet { "ARM7", "CPU_ARM7" }, /* CPU_CLASS_ARM7 */ 265129198Scognet { "ARM7TDMI", "CPU_ARM7TDMI" }, /* CPU_CLASS_ARM7TDMI */ 266129198Scognet { "ARM8", "CPU_ARM8" }, /* CPU_CLASS_ARM8 */ 267129198Scognet { "ARM9TDMI", NULL }, /* CPU_CLASS_ARM9TDMI */ 268129198Scognet { "ARM9E-S", NULL }, /* CPU_CLASS_ARM9ES */ 269129198Scognet { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */ 270129198Scognet { "SA-1", "CPU_SA110" }, /* CPU_CLASS_SA1 */ 271129198Scognet { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */ 272129198Scognet}; 273129198Scognet 274129198Scognet/* 275129198Scognet * Report the type of the specified arm processor. This uses the generic and 276129198Scognet * arm specific information in the cpu structure to identify the processor. 277129198Scognet * The remaining fields in the cpu structure are filled in appropriately. 278129198Scognet */ 279129198Scognet 280129198Scognetstatic const char * const wtnames[] = { 281129198Scognet "write-through", 282129198Scognet "write-back", 283129198Scognet "write-back", 284129198Scognet "**unknown 3**", 285129198Scognet "**unknown 4**", 286129198Scognet "write-back-locking", /* XXX XScale-specific? */ 287129198Scognet "write-back-locking-A", 288129198Scognet "write-back-locking-B", 289129198Scognet "**unknown 8**", 290129198Scognet "**unknown 9**", 291129198Scognet "**unknown 10**", 292129198Scognet "**unknown 11**", 293129198Scognet "**unknown 12**", 294129198Scognet "**unknown 13**", 295129198Scognet "**unknown 14**", 296129198Scognet "**unknown 15**", 297129198Scognet}; 298129198Scognet 299129198Scognetextern int ctrl; 300129198Scognetvoid 301129198Scognetidentify_arm_cpu(void) 302129198Scognet{ 303129198Scognet u_int cpuid; 304129198Scognet enum cpu_class cpu_class = CPU_CLASS_NONE; 305129198Scognet int i; 306129198Scognet 307129198Scognet cpuid = cpu_id(); 308129198Scognet 309129198Scognet if (cpuid == 0) { 310129198Scognet printf("Processor failed probe - no CPU ID\n"); 311129198Scognet return; 312129198Scognet } 313129198Scognet 314129198Scognet for (i = 0; cpuids[i].cpuid != 0; i++) 315129198Scognet if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) { 316129198Scognet cpu_class = cpuids[i].cpu_class; 317129198Scognet printf("%s %s (%s core)\n", 318129198Scognet cpuids[i].cpu_name, 319129198Scognet cpuids[i].cpu_steppings[cpuid & 320129198Scognet CPU_ID_REVISION_MASK], 321129198Scognet cpu_classes[cpu_class].class_name); 322129198Scognet break; 323129198Scognet } 324129198Scognet if (cpuids[i].cpuid == 0) 325129198Scognet printf("unknown CPU (ID = 0x%x)\n", cpuid); 326129198Scognet 327129198Scognet switch (cpu_class) { 328129198Scognet case CPU_CLASS_ARM6: 329129198Scognet case CPU_CLASS_ARM7: 330129198Scognet case CPU_CLASS_ARM7TDMI: 331129198Scognet case CPU_CLASS_ARM8: 332129198Scognet if ((ctrl & CPU_CONTROL_IDC_ENABLE) == 0) 333129198Scognet printf(" IDC disabled"); 334129198Scognet else 335129198Scognet printf(" IDC enabled"); 336129198Scognet break; 337129198Scognet case CPU_CLASS_ARM9TDMI: 338129198Scognet case CPU_CLASS_ARM10E: 339129198Scognet case CPU_CLASS_SA1: 340129198Scognet case CPU_CLASS_XSCALE: 341129198Scognet if ((ctrl & CPU_CONTROL_DC_ENABLE) == 0) 342129198Scognet printf(" DC disabled"); 343129198Scognet else 344129198Scognet printf(" DC enabled"); 345129198Scognet if ((ctrl & CPU_CONTROL_IC_ENABLE) == 0) 346129198Scognet printf(" IC disabled"); 347129198Scognet else 348129198Scognet printf(" IC enabled"); 349129198Scognet break; 350129198Scognet default: 351129198Scognet break; 352129198Scognet } 353129198Scognet if ((ctrl & CPU_CONTROL_WBUF_ENABLE) == 0) 354129198Scognet printf(" WB disabled"); 355129198Scognet else 356129198Scognet printf(" WB enabled"); 357129198Scognet 358129198Scognet if (ctrl & CPU_CONTROL_LABT_ENABLE) 359129198Scognet printf(" LABT"); 360129198Scognet else 361129198Scognet printf(" EABT"); 362129198Scognet 363129198Scognet if (ctrl & CPU_CONTROL_BPRD_ENABLE) 364129198Scognet printf(" branch prediction enabled"); 365129198Scognet 366137272Scognet /* Print cache info. */ 367137272Scognet if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) 368137272Scognet return; 369137272Scognet 370137272Scognet if (arm_pcache_unified) { 371137272Scognet printf("%dKB/%dB %d-way %s unified cache\n", 372137272Scognet arm_pdcache_size / 1024, 373137272Scognet arm_pdcache_line_size, arm_pdcache_ways, 374137272Scognet wtnames[arm_pcache_type]); 375137272Scognet } else { 376137272Scognet printf("%dKB/%dB %d-way Instruction cache\n", 377137272Scognet arm_picache_size / 1024, 378137272Scognet arm_picache_line_size, arm_picache_ways); 379137272Scognet printf("%dKB/%dB %d-way %s Data cache\n", 380137272Scognet arm_pdcache_size / 1024, 381137272Scognet arm_pdcache_line_size, arm_pdcache_ways, 382137272Scognet wtnames[arm_pcache_type]); 383137272Scognet } 384129198Scognet printf("\n"); 385129198Scognet} 386129198Scognet 387