1239281Sgonzo/*- 2239281Sgonzo * Copyright (c) 2011 3239281Sgonzo * Ben Gray <ben.r.gray@gmail.com>. 4239281Sgonzo * All rights reserved. 5239281Sgonzo * 6239281Sgonzo * Redistribution and use in source and binary forms, with or without 7239281Sgonzo * modification, are permitted provided that the following conditions 8239281Sgonzo * are met: 9239281Sgonzo * 1. Redistributions of source code must retain the above copyright 10239281Sgonzo * notice, this list of conditions and the following disclaimer. 11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12239281Sgonzo * notice, this list of conditions and the following disclaimer in the 13239281Sgonzo * documentation and/or other materials provided with the distribution. 14239281Sgonzo * 15239281Sgonzo * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16239281Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17239281Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18239281Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19239281Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20239281Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21239281Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22239281Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23239281Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24239281Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25239281Sgonzo * SUCH DAMAGE. 26239281Sgonzo */ 27239281Sgonzo 28239281Sgonzo#include <sys/cdefs.h> 29239281Sgonzo__FBSDID("$FreeBSD: releng/10.2/sys/arm/ti/ti_cpuid.c 259329 2013-12-13 20:43:11Z ian $"); 30239281Sgonzo 31239281Sgonzo#include <sys/param.h> 32239281Sgonzo#include <sys/systm.h> 33239281Sgonzo#include <sys/kernel.h> 34239281Sgonzo#include <sys/module.h> 35239281Sgonzo#include <sys/bus.h> 36239281Sgonzo#include <sys/resource.h> 37239281Sgonzo#include <sys/rman.h> 38239281Sgonzo#include <sys/lock.h> 39239281Sgonzo#include <sys/mutex.h> 40239281Sgonzo 41239281Sgonzo#include <machine/bus.h> 42239281Sgonzo#include <machine/fdt.h> 43239281Sgonzo#include <machine/cpu.h> 44239281Sgonzo#include <machine/cpufunc.h> 45239281Sgonzo#include <machine/resource.h> 46239281Sgonzo#include <machine/intr.h> 47239281Sgonzo 48239281Sgonzo#include <arm/ti/tivar.h> 49239281Sgonzo#include <arm/ti/ti_cpuid.h> 50239281Sgonzo 51239281Sgonzo#include <arm/ti/omap4/omap4_reg.h> 52239281Sgonzo#include <arm/ti/omap3/omap3_reg.h> 53239281Sgonzo#include <arm/ti/am335x/am335x_reg.h> 54239281Sgonzo 55239281Sgonzo#define OMAP4_STD_FUSE_DIE_ID_0 0x2200 56239281Sgonzo#define OMAP4_ID_CODE 0x2204 57239281Sgonzo#define OMAP4_STD_FUSE_DIE_ID_1 0x2208 58239281Sgonzo#define OMAP4_STD_FUSE_DIE_ID_2 0x220C 59239281Sgonzo#define OMAP4_STD_FUSE_DIE_ID_3 0x2210 60239281Sgonzo#define OMAP4_STD_FUSE_PROD_ID_0 0x2214 61239281Sgonzo#define OMAP4_STD_FUSE_PROD_ID_1 0x2218 62239281Sgonzo 63239281Sgonzo#define OMAP3_ID_CODE 0xA204 64239281Sgonzo 65239281Sgonzostatic uint32_t chip_revision = 0xffffffff; 66239281Sgonzo 67239281Sgonzo/** 68239281Sgonzo * ti_revision - Returns the revision number of the device 69239281Sgonzo * 70239281Sgonzo * Simply returns an identifier for the revision of the chip we are running 71239281Sgonzo * on. 72239281Sgonzo * 73239281Sgonzo * RETURNS 74239281Sgonzo * A 32-bit identifier for the current chip 75239281Sgonzo */ 76239281Sgonzouint32_t 77239281Sgonzoti_revision(void) 78239281Sgonzo{ 79239281Sgonzo return chip_revision; 80239281Sgonzo} 81239281Sgonzo 82239281Sgonzo/** 83239281Sgonzo * omap4_get_revision - determines omap4 revision 84239281Sgonzo * 85239281Sgonzo * Reads the registers to determine the revision of the chip we are currently 86239281Sgonzo * running on. Stores the information in global variables. 87239281Sgonzo * 88239281Sgonzo * 89239281Sgonzo */ 90239281Sgonzostatic void 91239281Sgonzoomap4_get_revision(void) 92239281Sgonzo{ 93239281Sgonzo uint32_t id_code; 94239281Sgonzo uint32_t revision; 95239281Sgonzo uint32_t hawkeye; 96239281Sgonzo bus_space_handle_t bsh; 97239281Sgonzo 98239281Sgonzo /* The chip revsion is read from the device identification registers and 99239281Sgonzo * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 100239281Sgonzo * 0x4A00_2218. This is part of the L4_CORE memory range and should have 101239281Sgonzo * been mapped in by the machdep.c code. 102239281Sgonzo * 103239281Sgonzo * STD_FUSE_DIE_ID_0 0x4A00 2200 104239281Sgonzo * ID_CODE 0x4A00 2204 (this is the only one we need) 105239281Sgonzo * STD_FUSE_DIE_ID_1 0x4A00 2208 106239281Sgonzo * STD_FUSE_DIE_ID_2 0x4A00 220C 107239281Sgonzo * STD_FUSE_DIE_ID_3 0x4A00 2210 108239281Sgonzo * STD_FUSE_PROD_ID_0 0x4A00 2214 109239281Sgonzo * STD_FUSE_PROD_ID_1 0x4A00 2218 110239281Sgonzo */ 111246850Sgonzo /* FIXME Should we map somewhere else? */ 112239281Sgonzo bus_space_map(fdtbus_bs_tag,OMAP44XX_L4_CORE_HWBASE, 0x4000, 0, &bsh); 113239281Sgonzo id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP4_ID_CODE); 114239281Sgonzo bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); 115239281Sgonzo 116239281Sgonzo hawkeye = ((id_code >> 12) & 0xffff); 117239281Sgonzo revision = ((id_code >> 28) & 0xf); 118239281Sgonzo 119239281Sgonzo /* Apparently according to the linux code there were some ES2.0 samples that 120239281Sgonzo * have the wrong id code and report themselves as ES1.0 silicon. So used 121239281Sgonzo * the ARM cpuid to get the correct revision. 122239281Sgonzo */ 123239281Sgonzo if (revision == 0) { 124239281Sgonzo id_code = cpufunc_id(); 125239281Sgonzo revision = (id_code & 0xf) - 1; 126239281Sgonzo } 127239281Sgonzo 128239281Sgonzo switch (hawkeye) { 129239281Sgonzo case 0xB852: 130245137Sgonzo switch (revision) { 131245137Sgonzo case 0: 132239281Sgonzo chip_revision = OMAP4430_REV_ES1_0; 133245137Sgonzo break; 134245137Sgonzo case 1: 135245137Sgonzo chip_revision = OMAP4430_REV_ES2_1; 136245137Sgonzo break; 137245137Sgonzo default: 138245137Sgonzo chip_revision = OMAP4430_REV_UNKNOWN; 139245137Sgonzo break; 140245137Sgonzo } 141239281Sgonzo break; 142245137Sgonzo 143239281Sgonzo case 0xB95C: 144245137Sgonzo switch (revision) { 145245137Sgonzo case 3: 146239281Sgonzo chip_revision = OMAP4430_REV_ES2_1; 147245137Sgonzo break; 148245137Sgonzo case 4: 149239281Sgonzo chip_revision = OMAP4430_REV_ES2_2; 150245137Sgonzo break; 151245137Sgonzo case 6: 152239281Sgonzo chip_revision = OMAP4430_REV_ES2_3; 153245137Sgonzo break; 154245137Sgonzo default: 155245137Sgonzo chip_revision = OMAP4430_REV_UNKNOWN; 156245137Sgonzo break; 157245137Sgonzo } 158239281Sgonzo break; 159245137Sgonzo 160245137Sgonzo case 0xB94E: 161245137Sgonzo switch (revision) { 162245137Sgonzo case 0: 163245137Sgonzo chip_revision = OMAP4460_REV_ES1_0; 164245137Sgonzo break; 165245137Sgonzo case 2: 166245137Sgonzo chip_revision = OMAP4460_REV_ES1_1; 167245137Sgonzo break; 168245137Sgonzo default: 169245137Sgonzo chip_revision = OMAP4460_REV_UNKNOWN; 170245137Sgonzo break; 171245137Sgonzo } 172245137Sgonzo break; 173245137Sgonzo 174245137Sgonzo case 0xB975: 175245137Sgonzo switch (revision) { 176245137Sgonzo case 0: 177245137Sgonzo chip_revision = OMAP4470_REV_ES1_0; 178245137Sgonzo break; 179245137Sgonzo default: 180245137Sgonzo chip_revision = OMAP4470_REV_UNKNOWN; 181245137Sgonzo break; 182245137Sgonzo } 183245137Sgonzo break; 184245137Sgonzo 185239281Sgonzo default: 186239281Sgonzo /* Default to the latest revision if we can't determine type */ 187245137Sgonzo chip_revision = OMAP_UNKNOWN_DEV; 188239281Sgonzo break; 189239281Sgonzo } 190245137Sgonzo if (chip_revision != OMAP_UNKNOWN_DEV) { 191245137Sgonzo printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 192245137Sgonzo OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 193245137Sgonzo OMAP_REV_MINOR(chip_revision)); 194245137Sgonzo } 195245137Sgonzo else { 196245137Sgonzo printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n", 197245137Sgonzo hawkeye, revision); 198245137Sgonzo } 199239281Sgonzo} 200239281Sgonzo 201239281Sgonzo/** 202239281Sgonzo * omap3_get_revision - determines omap3 revision 203239281Sgonzo * 204239281Sgonzo * Reads the registers to determine the revision of the chip we are currently 205239281Sgonzo * running on. Stores the information in global variables. 206239281Sgonzo * 207239281Sgonzo * WARNING: This function currently only really works for OMAP3530 devices. 208239281Sgonzo * 209239281Sgonzo * 210239281Sgonzo * 211239281Sgonzo */ 212239281Sgonzostatic void 213239281Sgonzoomap3_get_revision(void) 214239281Sgonzo{ 215239281Sgonzo uint32_t id_code; 216239281Sgonzo uint32_t revision; 217239281Sgonzo uint32_t hawkeye; 218239281Sgonzo bus_space_handle_t bsh; 219239281Sgonzo 220239281Sgonzo /* The chip revsion is read from the device identification registers and 221239281Sgonzo * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 222239281Sgonzo * 0x4A00_2218. This is part of the L4_CORE memory range and should have 223239281Sgonzo * been mapped in by the machdep.c code. 224239281Sgonzo * 225239281Sgonzo * CONTROL_IDCODE 0x4830 A204 (this is the only one we need) 226239281Sgonzo * 227239281Sgonzo * 228239281Sgonzo */ 229246850Sgonzo bus_space_map(fdtbus_bs_tag, OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh); 230239281Sgonzo id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP3_ID_CODE); 231246850Sgonzo bus_space_unmap(fdtbus_bs_tag, bsh, 0x10000); 232239281Sgonzo 233239281Sgonzo hawkeye = ((id_code >> 12) & 0xffff); 234239281Sgonzo revision = ((id_code >> 28) & 0xf); 235239281Sgonzo 236239281Sgonzo switch (hawkeye) { 237239281Sgonzo case 0xB6D6: 238239281Sgonzo chip_revision = OMAP3350_REV_ES1_0; 239239281Sgonzo break; 240239281Sgonzo case 0xB7AE: 241239281Sgonzo if (revision == 1) 242239281Sgonzo chip_revision = OMAP3530_REV_ES2_0; 243239281Sgonzo else if (revision == 2) 244239281Sgonzo chip_revision = OMAP3530_REV_ES2_1; 245239281Sgonzo else if (revision == 3) 246239281Sgonzo chip_revision = OMAP3530_REV_ES3_0; 247239281Sgonzo else if (revision == 4) 248239281Sgonzo chip_revision = OMAP3530_REV_ES3_1; 249239281Sgonzo else if (revision == 7) 250239281Sgonzo chip_revision = OMAP3530_REV_ES3_1_2; 251239281Sgonzo break; 252239281Sgonzo default: 253239281Sgonzo /* Default to the latest revision if we can't determine type */ 254239281Sgonzo chip_revision = OMAP3530_REV_ES3_1_2; 255239281Sgonzo break; 256239281Sgonzo } 257239281Sgonzo printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 258239281Sgonzo OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 259239281Sgonzo OMAP_REV_MINOR(chip_revision)); 260239281Sgonzo} 261239281Sgonzo 262239281Sgonzostatic void 263239281Sgonzoam335x_get_revision(void) 264239281Sgonzo{ 265239281Sgonzo uint32_t dev_feature; 266239281Sgonzo uint8_t cpu_last_char; 267239281Sgonzo bus_space_handle_t bsh; 268239281Sgonzo 269239281Sgonzo bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh); 270239281Sgonzo chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID); 271239281Sgonzo dev_feature = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEV_FEATURE); 272239281Sgonzo bus_space_unmap(fdtbus_bs_tag, bsh, AM335X_CONTROL_SIZE); 273239281Sgonzo 274239281Sgonzo switch (dev_feature) { 275239281Sgonzo case 0x00FF0382: 276239281Sgonzo cpu_last_char='2'; 277239281Sgonzo break; 278239281Sgonzo case 0x20FF0382: 279239281Sgonzo cpu_last_char='4'; 280239281Sgonzo break; 281239281Sgonzo case 0x00FF0383: 282239281Sgonzo cpu_last_char='6'; 283239281Sgonzo break; 284239281Sgonzo case 0x00FE0383: 285239281Sgonzo cpu_last_char='7'; 286239281Sgonzo break; 287239281Sgonzo case 0x20FF0383: 288239281Sgonzo cpu_last_char='8'; 289239281Sgonzo break; 290239281Sgonzo case 0x20FE0383: 291239281Sgonzo cpu_last_char='9'; 292239281Sgonzo break; 293239281Sgonzo default: 294239281Sgonzo cpu_last_char='x'; 295239281Sgonzo } 296239281Sgonzo 297239281Sgonzo printf("Texas Instruments AM335%c Processor, Revision ES1.%u\n", 298239281Sgonzo cpu_last_char, AM335X_DEVREV(chip_revision)); 299239281Sgonzo} 300239281Sgonzo 301239281Sgonzo/** 302239281Sgonzo * ti_cpu_ident - attempts to identify the chip we are running on 303239281Sgonzo * @dummy: ignored 304239281Sgonzo * 305239281Sgonzo * This function is called before any of the driver are initialised, however 306239281Sgonzo * the basic virt to phys maps have been setup in machdep.c so we can still 307239281Sgonzo * access the required registers, we just have to use direct register reads 308239281Sgonzo * and writes rather than going through the bus stuff. 309239281Sgonzo * 310239281Sgonzo * 311239281Sgonzo */ 312239281Sgonzostatic void 313239281Sgonzoti_cpu_ident(void *dummy) 314239281Sgonzo{ 315239281Sgonzo switch(ti_chip()) { 316239281Sgonzo case CHIP_OMAP_3: 317239281Sgonzo omap3_get_revision(); 318239281Sgonzo break; 319239281Sgonzo case CHIP_OMAP_4: 320239281Sgonzo omap4_get_revision(); 321239281Sgonzo break; 322239281Sgonzo case CHIP_AM335X: 323239281Sgonzo am335x_get_revision(); 324239281Sgonzo break; 325239281Sgonzo default: 326239281Sgonzo panic("Unknown chip type, fixme!\n"); 327239281Sgonzo } 328239281Sgonzo} 329239281Sgonzo 330239281SgonzoSYSINIT(ti_cpu_ident, SI_SUB_CPU, SI_ORDER_SECOND, ti_cpu_ident, NULL); 331