1 /* 2 * linux/arch/arm/mach-omap2/id.c 3 * 4 * OMAP2 CPU identification code 5 * 6 * Copyright (C) 2005 Nokia Corporation 7 * Written by Tony Lindgren <tony@atomide.com> 8 * 9 * Copyright (C) 2009 Texas Instruments 10 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 17 #include <linux/module.h> 18 #include <linux/kernel.h> 19 #include <linux/init.h> 20 #include <linux/io.h> 21 22 #include <asm/cputype.h> 23 24 #include <mach/common.h> 25 #include <mach/control.h> 26 #include <mach/cpu.h> 27 28 static struct omap_chip_id omap_chip; 29 static unsigned int omap_revision; 30 31 32 unsigned int omap_rev(void) 33 { 34 return omap_revision; 35 } 36 EXPORT_SYMBOL(omap_rev); 37 38 /** 39 * omap_chip_is - test whether currently running OMAP matches a chip type 40 * @oc: omap_chip_t to test against 41 * 42 * Test whether the currently-running OMAP chip matches the supplied 43 * chip type 'oc'. Returns 1 upon a match; 0 upon failure. 44 */ 45 int omap_chip_is(struct omap_chip_id oci) 46 { 47 return (oci.oc & omap_chip.oc) ? 1 : 0; 48 } 49 EXPORT_SYMBOL(omap_chip_is); 50 51 int omap_type(void) 52 { 53 u32 val = 0; 54 55 if (cpu_is_omap24xx()) 56 val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS); 57 else if (cpu_is_omap34xx()) 58 val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS); 59 else { 60 pr_err("Cannot detect omap type!\n"); 61 goto out; 62 } 63 64 val &= OMAP2_DEVICETYPE_MASK; 65 val >>= 8; 66 67 out: 68 return val; 69 } 70 EXPORT_SYMBOL(omap_type); 71 72 73 /*----------------------------------------------------------------------------*/ 74 75 #define OMAP_TAP_IDCODE 0x0204 76 #define OMAP_TAP_DIE_ID_0 0x0218 77 #define OMAP_TAP_DIE_ID_1 0x021C 78 #define OMAP_TAP_DIE_ID_2 0x0220 79 #define OMAP_TAP_DIE_ID_3 0x0224 80 81 #define read_tap_reg(reg) __raw_readl(tap_base + (reg)) 82 83 struct omap_id { 84 u16 hawkeye; /* Silicon type (Hawkeye id) */ 85 u8 dev; /* Device type from production_id reg */ 86 u32 type; /* Combined type id copied to omap_revision */ 87 }; 88 89 /* Register values to detect the OMAP version */ 90 static struct omap_id omap_ids[] __initdata = { 91 { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200024 }, 92 { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201024 }, 93 { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202024 }, 94 { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220024 }, 95 { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230024 }, 96 { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300024 }, 97 }; 98 99 static void __iomem *tap_base; 100 static u16 tap_prod_id; 101 102 void __init omap24xx_check_revision(void) 103 { 104 int i, j; 105 u32 idcode, prod_id; 106 u16 hawkeye; 107 u8 dev_type, rev; 108 109 idcode = read_tap_reg(OMAP_TAP_IDCODE); 110 prod_id = read_tap_reg(tap_prod_id); 111 hawkeye = (idcode >> 12) & 0xffff; 112 rev = (idcode >> 28) & 0x0f; 113 dev_type = (prod_id >> 16) & 0x0f; 114 115 pr_debug("OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n", 116 idcode, rev, hawkeye, (idcode >> 1) & 0x7ff); 117 pr_debug("OMAP_TAP_DIE_ID_0: 0x%08x\n", 118 read_tap_reg(OMAP_TAP_DIE_ID_0)); 119 pr_debug("OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n", 120 read_tap_reg(OMAP_TAP_DIE_ID_1), 121 (read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf); 122 pr_debug("OMAP_TAP_DIE_ID_2: 0x%08x\n", 123 read_tap_reg(OMAP_TAP_DIE_ID_2)); 124 pr_debug("OMAP_TAP_DIE_ID_3: 0x%08x\n", 125 read_tap_reg(OMAP_TAP_DIE_ID_3)); 126 pr_debug("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n", 127 prod_id, dev_type); 128 129 /* Check hawkeye ids */ 130 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 131 if (hawkeye == omap_ids[i].hawkeye) 132 break; 133 } 134 135 if (i == ARRAY_SIZE(omap_ids)) { 136 printk(KERN_ERR "Unknown OMAP CPU id\n"); 137 return; 138 } 139 140 for (j = i; j < ARRAY_SIZE(omap_ids); j++) { 141 if (dev_type == omap_ids[j].dev) 142 break; 143 } 144 145 if (j == ARRAY_SIZE(omap_ids)) { 146 printk(KERN_ERR "Unknown OMAP device type. " 147 "Handling it as OMAP%04x\n", 148 omap_ids[i].type >> 16); 149 j = i; 150 } 151 152 pr_info("OMAP%04x", omap_rev() >> 16); 153 if ((omap_rev() >> 8) & 0x0f) 154 pr_info("ES%x", (omap_rev() >> 12) & 0xf); 155 pr_info("\n"); 156 } 157 158 void __init omap34xx_check_revision(void) 159 { 160 u32 cpuid, idcode; 161 u16 hawkeye; 162 u8 rev; 163 char *rev_name = "ES1.0"; 164 165 /* 166 * We cannot access revision registers on ES1.0. 167 * If the processor type is Cortex-A8 and the revision is 0x0 168 * it means its Cortex r0p0 which is 3430 ES1.0. 169 */ 170 cpuid = read_cpuid(CPUID_ID); 171 if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) { 172 omap_revision = OMAP3430_REV_ES1_0; 173 goto out; 174 } 175 176 /* 177 * Detection for 34xx ES2.0 and above can be done with just 178 * hawkeye and rev. See TRM 1.5.2 Device Identification. 179 * Note that rev does not map directly to our defined processor 180 * revision numbers as ES1.0 uses value 0. 181 */ 182 idcode = read_tap_reg(OMAP_TAP_IDCODE); 183 hawkeye = (idcode >> 12) & 0xffff; 184 rev = (idcode >> 28) & 0xff; 185 186 if (hawkeye == 0xb7ae) { 187 switch (rev) { 188 case 0: 189 omap_revision = OMAP3430_REV_ES2_0; 190 rev_name = "ES2.0"; 191 break; 192 case 2: 193 omap_revision = OMAP3430_REV_ES2_1; 194 rev_name = "ES2.1"; 195 break; 196 case 3: 197 omap_revision = OMAP3430_REV_ES3_0; 198 rev_name = "ES3.0"; 199 break; 200 case 4: 201 omap_revision = OMAP3430_REV_ES3_1; 202 rev_name = "ES3.1"; 203 break; 204 default: 205 /* Use the latest known revision as default */ 206 omap_revision = OMAP3430_REV_ES3_1; 207 rev_name = "Unknown revision\n"; 208 } 209 } 210 211 out: 212 pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name); 213 } 214 215 /* 216 * Try to detect the exact revision of the omap we're running on 217 */ 218 void __init omap2_check_revision(void) 219 { 220 /* 221 * At this point we have an idea about the processor revision set 222 * earlier with omap2_set_globals_tap(). 223 */ 224 if (cpu_is_omap24xx()) 225 omap24xx_check_revision(); 226 else if (cpu_is_omap34xx()) 227 omap34xx_check_revision(); 228 else if (cpu_is_omap44xx()) { 229 printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n"); 230 return; 231 } else 232 pr_err("OMAP revision unknown, please fix!\n"); 233 234 /* 235 * OK, now we know the exact revision. Initialize omap_chip bits 236 * for powerdowmain and clockdomain code. 237 */ 238 if (cpu_is_omap243x()) { 239 /* Currently only supports 2430ES2.1 and 2430-all */ 240 omap_chip.oc |= CHIP_IS_OMAP2430; 241 } else if (cpu_is_omap242x()) { 242 /* Currently only supports 2420ES2.1.1 and 2420-all */ 243 omap_chip.oc |= CHIP_IS_OMAP2420; 244 } else if (cpu_is_omap343x()) { 245 omap_chip.oc = CHIP_IS_OMAP3430; 246 if (omap_rev() == OMAP3430_REV_ES1_0) 247 omap_chip.oc |= CHIP_IS_OMAP3430ES1; 248 else if (omap_rev() >= OMAP3430_REV_ES2_0 && 249 omap_rev() <= OMAP3430_REV_ES2_1) 250 omap_chip.oc |= CHIP_IS_OMAP3430ES2; 251 else if (omap_rev() == OMAP3430_REV_ES3_0) 252 omap_chip.oc |= CHIP_IS_OMAP3430ES3_0; 253 else if (omap_rev() == OMAP3430_REV_ES3_1) 254 omap_chip.oc |= CHIP_IS_OMAP3430ES3_1; 255 } else { 256 pr_err("Uninitialized omap_chip, please fix!\n"); 257 } 258 } 259 260 /* 261 * Set up things for map_io and processor detection later on. Gets called 262 * pretty much first thing from board init. For multi-omap, this gets 263 * cpu_is_omapxxxx() working accurately enough for map_io. Then we'll try to 264 * detect the exact revision later on in omap2_detect_revision() once map_io 265 * is done. 266 */ 267 void __init omap2_set_globals_tap(struct omap_globals *omap2_globals) 268 { 269 omap_revision = omap2_globals->class; 270 tap_base = omap2_globals->tap; 271 272 if (cpu_is_omap34xx()) 273 tap_prod_id = 0x0210; 274 else 275 tap_prod_id = 0x0208; 276 } 277