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$"); 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> 55235050Simp#include <machine/endian.h> 56129198Scognet 57129198Scognet#include <machine/cpuconf.h> 58197523Srpaulo#include <machine/md_var.h> 59129198Scognet 60129198Scognetchar machine[] = "arm"; 61129198Scognet 62135652ScognetSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, 63235062Simp machine, 0, "Machine class"); 64129198Scognet 65129198Scognetstatic const char * const generic_steppings[16] = { 66129198Scognet "rev 0", "rev 1", "rev 2", "rev 3", 67129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 68129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 69129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 70129198Scognet}; 71129198Scognet 72129198Scognetstatic const char * const sa110_steppings[16] = { 73129198Scognet "rev 0", "step J", "step K", "step S", 74129198Scognet "step T", "rev 5", "rev 6", "rev 7", 75129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 76129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 77129198Scognet}; 78129198Scognet 79129198Scognetstatic const char * const sa1100_steppings[16] = { 80129198Scognet "rev 0", "step B", "step C", "rev 3", 81129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 82129198Scognet "step D", "step E", "rev 10" "step G", 83129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 84129198Scognet}; 85129198Scognet 86129198Scognetstatic const char * const sa1110_steppings[16] = { 87129198Scognet "step A-0", "rev 1", "rev 2", "rev 3", 88129198Scognet "step B-0", "step B-1", "step B-2", "step B-3", 89129198Scognet "step B-4", "step B-5", "rev 10", "rev 11", 90129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 91129198Scognet}; 92129198Scognet 93129198Scognetstatic const char * const ixp12x0_steppings[16] = { 94129198Scognet "(IXP1200 step A)", "(IXP1200 step B)", 95129198Scognet "rev 2", "(IXP1200 step C)", 96129198Scognet "(IXP1200 step D)", "(IXP1240/1250 step A)", 97129198Scognet "(IXP1240 step B)", "(IXP1250 step B)", 98129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 99129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 100129198Scognet}; 101129198Scognet 102129198Scognetstatic const char * const xscale_steppings[16] = { 103129198Scognet "step A-0", "step A-1", "step B-0", "step C-0", 104129198Scognet "step D-0", "rev 5", "rev 6", "rev 7", 105129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 106129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 107129198Scognet}; 108129198Scognet 109172738Simpstatic const char * const i80219_steppings[16] = { 110172738Simp "step A-0", "rev 1", "rev 2", "rev 3", 111172738Simp "rev 4", "rev 5", "rev 6", "rev 7", 112172738Simp "rev 8", "rev 9", "rev 10", "rev 11", 113172738Simp "rev 12", "rev 13", "rev 14", "rev 15", 114172738Simp}; 115172738Simp 116129198Scognetstatic const char * const i80321_steppings[16] = { 117129198Scognet "step A-0", "step B-0", "rev 2", "rev 3", 118129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 119129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 120129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 121129198Scognet}; 122129198Scognet 123164080Scognetstatic const char * const i81342_steppings[16] = { 124164080Scognet "step A-0", "rev 1", "rev 2", "rev 3", 125164080Scognet "rev 4", "rev 5", "rev 6", "rev 7", 126164080Scognet "rev 8", "rev 9", "rev 10", "rev 11", 127164080Scognet "rev 12", "rev 13", "rev 14", "rev 15", 128164080Scognet}; 129164080Scognet 130172738Simp/* Steppings for PXA2[15]0 */ 131129198Scognetstatic const char * const pxa2x0_steppings[16] = { 132129198Scognet "step A-0", "step A-1", "step B-0", "step B-1", 133129198Scognet "step B-2", "step C-0", "rev 6", "rev 7", 134129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 135129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 136129198Scognet}; 137129198Scognet 138172738Simp/* Steppings for PXA255/26x. 139235062Simp * rev 5: PXA26x B0, rev 6: PXA255 A0 140172738Simp */ 141172738Simpstatic const char * const pxa255_steppings[16] = { 142172738Simp "rev 0", "rev 1", "rev 2", "step A-0", 143172738Simp "rev 4", "step B-0", "step A-0", "rev 7", 144172738Simp "rev 8", "rev 9", "rev 10", "rev 11", 145172738Simp "rev 12", "rev 13", "rev 14", "rev 15", 146172738Simp}; 147172738Simp 148172738Simp/* Stepping for PXA27x */ 149172738Simpstatic const char * const pxa27x_steppings[16] = { 150172738Simp "step A-0", "step A-1", "step B-0", "step B-1", 151172738Simp "step C-0", "rev 5", "rev 6", "rev 7", 152172738Simp "rev 8", "rev 9", "rev 10", "rev 11", 153172738Simp "rev 12", "rev 13", "rev 14", "rev 15", 154172738Simp}; 155172738Simp 156129198Scognetstatic const char * const ixp425_steppings[16] = { 157164423Ssam "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3", 158129198Scognet "rev 4", "rev 5", "rev 6", "rev 7", 159129198Scognet "rev 8", "rev 9", "rev 10", "rev 11", 160129198Scognet "rev 12", "rev 13", "rev 14", "rev 15", 161129198Scognet}; 162129198Scognet 163129198Scognetstruct cpuidtab { 164129198Scognet u_int32_t cpuid; 165129198Scognet enum cpu_class cpu_class; 166129198Scognet const char *cpu_name; 167129198Scognet const char * const *cpu_steppings; 168129198Scognet}; 169129198Scognet 170129198Scognetconst struct cpuidtab cpuids[] = { 171129198Scognet { CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2", 172129198Scognet generic_steppings }, 173129198Scognet { CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250", 174129198Scognet generic_steppings }, 175129198Scognet 176129198Scognet { CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3", 177129198Scognet generic_steppings }, 178129198Scognet 179129198Scognet { CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600", 180129198Scognet generic_steppings }, 181129198Scognet { CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610", 182129198Scognet generic_steppings }, 183129198Scognet { CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620", 184129198Scognet generic_steppings }, 185129198Scognet 186129198Scognet { CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700", 187129198Scognet generic_steppings }, 188129198Scognet { CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710", 189129198Scognet generic_steppings }, 190129198Scognet { CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500", 191129198Scognet generic_steppings }, 192129198Scognet { CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a", 193129198Scognet generic_steppings }, 194129198Scognet { CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE", 195129198Scognet generic_steppings }, 196129198Scognet { CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T", 197129198Scognet generic_steppings }, 198129198Scognet { CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T", 199129198Scognet generic_steppings }, 200129198Scognet { CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)", 201129198Scognet generic_steppings }, 202129198Scognet { CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)", 203129198Scognet generic_steppings }, 204129198Scognet 205129198Scognet { CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810", 206129198Scognet generic_steppings }, 207129198Scognet 208129198Scognet { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T", 209129198Scognet generic_steppings }, 210152653Scognet { CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T", 211152653Scognet generic_steppings }, 212129198Scognet { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T", 213129198Scognet generic_steppings }, 214172738Simp { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S", 215172738Simp generic_steppings }, 216129198Scognet { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T", 217129198Scognet generic_steppings }, 218129198Scognet { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S", 219129198Scognet generic_steppings }, 220129198Scognet { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S", 221129198Scognet generic_steppings }, 222129198Scognet { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", 223129198Scognet generic_steppings }, 224207954Skevlo { CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526", 225204122Skevlo generic_steppings }, 226207611Skevlo { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE", 227207611Skevlo generic_steppings }, 228204122Skevlo 229129198Scognet { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", 230129198Scognet generic_steppings }, 231129198Scognet 232129198Scognet { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E", 233129198Scognet generic_steppings }, 234129198Scognet { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S", 235129198Scognet generic_steppings }, 236172738Simp { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S", 237172738Simp generic_steppings }, 238129198Scognet 239253857Sganbold { CPU_ID_CORTEXA7, CPU_CLASS_CORTEXA, "Cortex A7", 240253857Sganbold generic_steppings }, 241239268Sgonzo { CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEXA, "Cortex A8-r1", 242239268Sgonzo generic_steppings }, 243239268Sgonzo { CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEXA, "Cortex A8-r2", 244239268Sgonzo generic_steppings }, 245239268Sgonzo { CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEXA, "Cortex A8-r3", 246239268Sgonzo generic_steppings }, 247239268Sgonzo { CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEXA, "Cortex A9-r1", 248239268Sgonzo generic_steppings }, 249239268Sgonzo { CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEXA, "Cortex A9-r2", 250239268Sgonzo generic_steppings }, 251249999Swkoszek { CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3", 252249999Swkoszek generic_steppings }, 253252361Sray { CPU_ID_CORTEXA15, CPU_CLASS_CORTEXA, "Cortex A15", 254252361Sray generic_steppings }, 255239268Sgonzo 256129198Scognet { CPU_ID_SA110, CPU_CLASS_SA1, "SA-110", 257129198Scognet sa110_steppings }, 258129198Scognet { CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100", 259129198Scognet sa1100_steppings }, 260129198Scognet { CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110", 261129198Scognet sa1110_steppings }, 262129198Scognet 263129198Scognet { CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200", 264129198Scognet ixp12x0_steppings }, 265129198Scognet 266129198Scognet { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200", 267129198Scognet xscale_steppings }, 268129198Scognet 269129198Scognet { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz", 270129198Scognet i80321_steppings }, 271129198Scognet { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz", 272129198Scognet i80321_steppings }, 273129198Scognet { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz", 274129198Scognet i80321_steppings }, 275129198Scognet { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz", 276129198Scognet i80321_steppings }, 277129198Scognet 278164080Scognet { CPU_ID_81342, CPU_CLASS_XSCALE, "i81342", 279164080Scognet i81342_steppings }, 280164080Scognet 281161592Scognet { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz", 282172738Simp i80219_steppings }, 283161592Scognet { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz", 284172738Simp i80219_steppings }, 285161592Scognet 286172738Simp { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x", 287172738Simp pxa27x_steppings }, 288129198Scognet { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250", 289129198Scognet pxa2x0_steppings }, 290129198Scognet { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210", 291129198Scognet pxa2x0_steppings }, 292129198Scognet { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250", 293129198Scognet pxa2x0_steppings }, 294129198Scognet { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210", 295129198Scognet pxa2x0_steppings }, 296172738Simp { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255", 297172738Simp pxa255_steppings }, 298129198Scognet { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210", 299129198Scognet pxa2x0_steppings }, 300129198Scognet 301129198Scognet { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz", 302129198Scognet ixp425_steppings }, 303129198Scognet { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz", 304129198Scognet ixp425_steppings }, 305129198Scognet { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz", 306129198Scognet ixp425_steppings }, 307129198Scognet 308186352Ssam /* XXX ixp435 steppings? */ 309186352Ssam { CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435", 310186352Ssam ixp425_steppings }, 311186352Ssam 312172738Simp { CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S", 313172738Simp generic_steppings }, 314172738Simp { CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1", 315172738Simp generic_steppings }, 316244480Sgonzo { CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S", 317244480Sgonzo generic_steppings }, 318172738Simp 319183835Sraj { CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131", 320183835Sraj generic_steppings }, 321183835Sraj 322183835Sraj { CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD", 323183835Sraj generic_steppings }, 324239268Sgonzo { CPU_ID_MV88SV581X_V6, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 325183835Sraj generic_steppings }, 326239268Sgonzo { CPU_ID_ARM_88SV581X_V6, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 327239268Sgonzo generic_steppings }, 328239268Sgonzo { CPU_ID_MV88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 329239268Sgonzo generic_steppings }, 330239268Sgonzo { CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 331239268Sgonzo generic_steppings }, 332240486Sgber { CPU_ID_MV88SV584X_V6, CPU_CLASS_MARVELL, "Sheeva 88SV584x", 333239268Sgonzo generic_steppings }, 334240486Sgber { CPU_ID_ARM_88SV584X_V6, CPU_CLASS_MARVELL, "Sheeva 88SV584x", 335239268Sgonzo generic_steppings }, 336240486Sgber { CPU_ID_MV88SV584X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV584x", 337240486Sgber generic_steppings }, 338183835Sraj 339129198Scognet { 0, CPU_CLASS_NONE, NULL, NULL } 340129198Scognet}; 341129198Scognet 342129198Scognetstruct cpu_classtab { 343129198Scognet const char *class_name; 344129198Scognet const char *class_option; 345129198Scognet}; 346129198Scognet 347129198Scognetconst struct cpu_classtab cpu_classes[] = { 348129198Scognet { "unknown", NULL }, /* CPU_CLASS_NONE */ 349129198Scognet { "ARM2", "CPU_ARM2" }, /* CPU_CLASS_ARM2 */ 350129198Scognet { "ARM2as", "CPU_ARM250" }, /* CPU_CLASS_ARM2AS */ 351129198Scognet { "ARM3", "CPU_ARM3" }, /* CPU_CLASS_ARM3 */ 352129198Scognet { "ARM6", "CPU_ARM6" }, /* CPU_CLASS_ARM6 */ 353129198Scognet { "ARM7", "CPU_ARM7" }, /* CPU_CLASS_ARM7 */ 354129198Scognet { "ARM7TDMI", "CPU_ARM7TDMI" }, /* CPU_CLASS_ARM7TDMI */ 355129198Scognet { "ARM8", "CPU_ARM8" }, /* CPU_CLASS_ARM8 */ 356155242Simp { "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */ 357172738Simp { "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */ 358172738Simp { "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */ 359129198Scognet { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */ 360172738Simp { "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */ 361239268Sgonzo { "Cortex-A", "CPU_CORTEXA" }, /* CPU_CLASS_CORTEXA */ 362129198Scognet { "SA-1", "CPU_SA110" }, /* CPU_CLASS_SA1 */ 363129198Scognet { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */ 364172738Simp { "ARM11J", "CPU_ARM11" }, /* CPU_CLASS_ARM11J */ 365205027Sraj { "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */ 366129198Scognet}; 367129198Scognet 368129198Scognet/* 369129198Scognet * Report the type of the specified arm processor. This uses the generic and 370129198Scognet * arm specific information in the cpu structure to identify the processor. 371129198Scognet * The remaining fields in the cpu structure are filled in appropriately. 372129198Scognet */ 373129198Scognet 374129198Scognetstatic const char * const wtnames[] = { 375129198Scognet "write-through", 376129198Scognet "write-back", 377129198Scognet "write-back", 378129198Scognet "**unknown 3**", 379129198Scognet "**unknown 4**", 380129198Scognet "write-back-locking", /* XXX XScale-specific? */ 381129198Scognet "write-back-locking-A", 382129198Scognet "write-back-locking-B", 383129198Scognet "**unknown 8**", 384129198Scognet "**unknown 9**", 385129198Scognet "**unknown 10**", 386129198Scognet "**unknown 11**", 387129198Scognet "**unknown 12**", 388129198Scognet "**unknown 13**", 389172738Simp "write-back-locking-C", 390129198Scognet "**unknown 15**", 391129198Scognet}; 392129198Scognet 393239268Sgonzostatic void 394239268Sgonzoprint_enadis(int enadis, char *s) 395239268Sgonzo{ 396153940Snetchild 397239268Sgonzo printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en"); 398239268Sgonzo} 399239268Sgonzo 400129198Scognetextern int ctrl; 401197523Srpauloenum cpu_class cpu_class = CPU_CLASS_NONE; 402239268Sgonzo 403239268Sgonzou_int cpu_pfr(int num) 404239268Sgonzo{ 405239268Sgonzo u_int feat; 406239268Sgonzo 407239268Sgonzo switch (num) { 408239268Sgonzo case 0: 409239268Sgonzo __asm __volatile("mrc p15, 0, %0, c0, c1, 0" 410239268Sgonzo : "=r" (feat)); 411239268Sgonzo break; 412239268Sgonzo case 1: 413239268Sgonzo __asm __volatile("mrc p15, 0, %0, c0, c1, 1" 414239268Sgonzo : "=r" (feat)); 415239268Sgonzo break; 416239268Sgonzo default: 417239268Sgonzo panic("Processor Feature Register %d not implemented", num); 418239268Sgonzo break; 419239268Sgonzo } 420239268Sgonzo 421239268Sgonzo return (feat); 422239268Sgonzo} 423239268Sgonzo 424239268Sgonzostatic 425239268Sgonzovoid identify_armv7(void) 426239268Sgonzo{ 427239268Sgonzo u_int feature; 428239268Sgonzo 429239268Sgonzo printf("Supported features:"); 430239268Sgonzo /* Get Processor Feature Register 0 */ 431239268Sgonzo feature = cpu_pfr(0); 432239268Sgonzo 433239268Sgonzo if (feature & ARM_PFR0_ARM_ISA_MASK) 434239268Sgonzo printf(" ARM_ISA"); 435239268Sgonzo 436239268Sgonzo if (feature & ARM_PFR0_THUMB2) 437239268Sgonzo printf(" THUMB2"); 438239268Sgonzo else if (feature & ARM_PFR0_THUMB) 439239268Sgonzo printf(" THUMB"); 440239268Sgonzo 441239268Sgonzo if (feature & ARM_PFR0_JAZELLE_MASK) 442239268Sgonzo printf(" JAZELLE"); 443239268Sgonzo 444239268Sgonzo if (feature & ARM_PFR0_THUMBEE_MASK) 445239268Sgonzo printf(" THUMBEE"); 446239268Sgonzo 447239268Sgonzo 448239268Sgonzo /* Get Processor Feature Register 1 */ 449239268Sgonzo feature = cpu_pfr(1); 450239268Sgonzo 451239268Sgonzo if (feature & ARM_PFR1_ARMV4_MASK) 452239268Sgonzo printf(" ARMv4"); 453239268Sgonzo 454239268Sgonzo if (feature & ARM_PFR1_SEC_EXT_MASK) 455239268Sgonzo printf(" Security_Ext"); 456239268Sgonzo 457239268Sgonzo if (feature & ARM_PFR1_MICROCTRL_MASK) 458239268Sgonzo printf(" M_profile"); 459239268Sgonzo 460239268Sgonzo printf("\n"); 461239268Sgonzo} 462239268Sgonzo 463129198Scognetvoid 464129198Scognetidentify_arm_cpu(void) 465129198Scognet{ 466239268Sgonzo u_int cpuid, reg, size, sets, ways; 467239268Sgonzo u_int8_t type, linesize; 468129198Scognet int i; 469129198Scognet 470129198Scognet cpuid = cpu_id(); 471129198Scognet 472129198Scognet if (cpuid == 0) { 473129198Scognet printf("Processor failed probe - no CPU ID\n"); 474129198Scognet return; 475129198Scognet } 476129198Scognet 477129198Scognet for (i = 0; cpuids[i].cpuid != 0; i++) 478129198Scognet if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) { 479129198Scognet cpu_class = cpuids[i].cpu_class; 480155242Simp printf("CPU: %s %s (%s core)\n", 481129198Scognet cpuids[i].cpu_name, 482129198Scognet cpuids[i].cpu_steppings[cpuid & 483129198Scognet CPU_ID_REVISION_MASK], 484129198Scognet cpu_classes[cpu_class].class_name); 485129198Scognet break; 486129198Scognet } 487129198Scognet if (cpuids[i].cpuid == 0) 488129198Scognet printf("unknown CPU (ID = 0x%x)\n", cpuid); 489129198Scognet 490155242Simp printf(" "); 491239268Sgonzo 492239268Sgonzo if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) { 493239268Sgonzo identify_armv7(); 494239268Sgonzo } else { 495239268Sgonzo if (ctrl & CPU_CONTROL_BEND_ENABLE) 496239268Sgonzo printf(" Big-endian"); 497129198Scognet else 498239268Sgonzo printf(" Little-endian"); 499239268Sgonzo 500239268Sgonzo switch (cpu_class) { 501239268Sgonzo case CPU_CLASS_ARM6: 502239268Sgonzo case CPU_CLASS_ARM7: 503239268Sgonzo case CPU_CLASS_ARM7TDMI: 504239268Sgonzo case CPU_CLASS_ARM8: 505239268Sgonzo print_enadis(ctrl & CPU_CONTROL_IDC_ENABLE, "IDC"); 506239268Sgonzo break; 507239268Sgonzo case CPU_CLASS_ARM9TDMI: 508239268Sgonzo case CPU_CLASS_ARM9ES: 509239268Sgonzo case CPU_CLASS_ARM9EJS: 510239268Sgonzo case CPU_CLASS_ARM10E: 511239268Sgonzo case CPU_CLASS_ARM10EJ: 512239268Sgonzo case CPU_CLASS_SA1: 513239268Sgonzo case CPU_CLASS_XSCALE: 514239268Sgonzo case CPU_CLASS_ARM11J: 515239268Sgonzo case CPU_CLASS_MARVELL: 516239268Sgonzo print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC"); 517239268Sgonzo print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC"); 518171625Scognet#ifdef CPU_XSCALE_81342 519239268Sgonzo print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2"); 520171625Scognet#endif 521239268Sgonzo#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) 522239268Sgonzo i = sheeva_control_ext(0, 0); 523239268Sgonzo print_enadis(i & MV_WA_ENABLE, "WA"); 524239268Sgonzo print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming"); 525239268Sgonzo printf("\n "); 526239268Sgonzo print_enadis((i & MV_BTB_DISABLE) == 0, "BTB"); 527239268Sgonzo print_enadis(i & MV_L2_ENABLE, "L2"); 528239268Sgonzo print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0, 529239268Sgonzo "L2 prefetch"); 530239268Sgonzo printf("\n "); 531239268Sgonzo#endif 532239268Sgonzo break; 533239268Sgonzo default: 534239268Sgonzo break; 535239268Sgonzo } 536129198Scognet } 537129198Scognet 538239268Sgonzo print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB"); 539129198Scognet if (ctrl & CPU_CONTROL_LABT_ENABLE) 540129198Scognet printf(" LABT"); 541129198Scognet else 542129198Scognet printf(" EABT"); 543129198Scognet 544239268Sgonzo print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction"); 545239268Sgonzo printf("\n"); 546129198Scognet 547239268Sgonzo if (arm_cache_level) { 548239268Sgonzo printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1, 549239268Sgonzo arm_cache_loc, CPU_CLIDR_LOUIS(arm_cache_level) + 1); 550239268Sgonzo i = 0; 551239268Sgonzo while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) { 552239268Sgonzo printf("Cache level %d: \n", i + 1); 553239268Sgonzo if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 554239268Sgonzo type == CACHE_SEP_CACHE) { 555239268Sgonzo reg = arm_cache_type[2 * i]; 556239268Sgonzo ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1; 557239268Sgonzo sets = CPUV7_CT_xSIZE_SET(reg) + 1; 558239268Sgonzo linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4); 559239268Sgonzo size = (ways * sets * linesize) / 1024; 560239268Sgonzo 561239268Sgonzo if (type == CACHE_UNI_CACHE) 562239268Sgonzo printf(" %dKB/%dB %d-way unified cache", size, linesize,ways); 563239268Sgonzo else 564239268Sgonzo printf(" %dKB/%dB %d-way data cache", size, linesize, ways); 565239268Sgonzo if (reg & CPUV7_CT_CTYPE_WT) 566239268Sgonzo printf(" WT"); 567239268Sgonzo if (reg & CPUV7_CT_CTYPE_WB) 568239268Sgonzo printf(" WB"); 569239268Sgonzo if (reg & CPUV7_CT_CTYPE_RA) 570239268Sgonzo printf(" Read-Alloc"); 571239268Sgonzo if (reg & CPUV7_CT_CTYPE_WA) 572239268Sgonzo printf(" Write-Alloc"); 573239268Sgonzo printf("\n"); 574239268Sgonzo } 575239268Sgonzo 576239268Sgonzo if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 577239268Sgonzo reg = arm_cache_type[(2 * i) + 1]; 578239268Sgonzo 579239268Sgonzo ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1; 580239268Sgonzo sets = CPUV7_CT_xSIZE_SET(reg) + 1; 581239268Sgonzo linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4); 582239268Sgonzo size = (ways * sets * linesize) / 1024; 583239268Sgonzo 584239268Sgonzo printf(" %dKB/%dB %d-way instruction cache", size, linesize, ways); 585239268Sgonzo if (reg & CPUV7_CT_CTYPE_WT) 586239268Sgonzo printf(" WT"); 587239268Sgonzo if (reg & CPUV7_CT_CTYPE_WB) 588239268Sgonzo printf(" WB"); 589239268Sgonzo if (reg & CPUV7_CT_CTYPE_RA) 590239268Sgonzo printf(" Read-Alloc"); 591239268Sgonzo if (reg & CPUV7_CT_CTYPE_WA) 592239268Sgonzo printf(" Write-Alloc"); 593239268Sgonzo printf("\n"); 594239268Sgonzo } 595239268Sgonzo i++; 596239268Sgonzo } 597137272Scognet } else { 598239268Sgonzo /* Print cache info. */ 599239268Sgonzo if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) 600239268Sgonzo return; 601239268Sgonzo 602239268Sgonzo if (arm_pcache_unified) { 603239268Sgonzo printf(" %dKB/%dB %d-way %s unified cache\n", 604239268Sgonzo arm_pdcache_size / 1024, 605239268Sgonzo arm_pdcache_line_size, arm_pdcache_ways, 606239268Sgonzo wtnames[arm_pcache_type]); 607239268Sgonzo } else { 608239268Sgonzo printf(" %dKB/%dB %d-way instruction cache\n", 609239268Sgonzo arm_picache_size / 1024, 610239268Sgonzo arm_picache_line_size, arm_picache_ways); 611239268Sgonzo printf(" %dKB/%dB %d-way %s data cache\n", 612239268Sgonzo arm_pdcache_size / 1024, 613239268Sgonzo arm_pdcache_line_size, arm_pdcache_ways, 614239268Sgonzo wtnames[arm_pcache_type]); 615239268Sgonzo } 616137272Scognet } 617129198Scognet} 618