1 /*- 2 * Copyright (c) 2011 3 * Ben Gray <ben.r.gray@gmail.com>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/bus.h> 36 #include <sys/resource.h> 37 #include <sys/rman.h> 38 #include <sys/lock.h> 39 #include <sys/mutex.h> 40 41 #include <machine/bus.h> 42 #include <machine/fdt.h> 43 #include <machine/cpu.h> 44 #include <machine/cpufunc.h> 45 #include <machine/frame.h> 46 #include <machine/resource.h> 47 #include <machine/intr.h> 48 49 #include <arm/ti/tivar.h> 50 #include <arm/ti/ti_cpuid.h> 51 52 #include <arm/ti/omap4/omap4_reg.h> 53 #include <arm/ti/omap3/omap3_reg.h> 54 #include <arm/ti/am335x/am335x_reg.h> 55 56 #define OMAP4_STD_FUSE_DIE_ID_0 0x2200 57 #define OMAP4_ID_CODE 0x2204 58 #define OMAP4_STD_FUSE_DIE_ID_1 0x2208 59 #define OMAP4_STD_FUSE_DIE_ID_2 0x220C 60 #define OMAP4_STD_FUSE_DIE_ID_3 0x2210 61 #define OMAP4_STD_FUSE_PROD_ID_0 0x2214 62 #define OMAP4_STD_FUSE_PROD_ID_1 0x2218 63 64 #define OMAP3_ID_CODE 0xA204 65 66 static uint32_t chip_revision = 0xffffffff; 67 68 /** 69 * ti_revision - Returns the revision number of the device 70 * 71 * Simply returns an identifier for the revision of the chip we are running 72 * on. 73 * 74 * RETURNS 75 * A 32-bit identifier for the current chip 76 */ 77 uint32_t 78 ti_revision(void) 79 { 80 return chip_revision; 81 } 82 83 /** 84 * omap4_get_revision - determines omap4 revision 85 * 86 * Reads the registers to determine the revision of the chip we are currently 87 * running on. Stores the information in global variables. 88 * 89 * 90 */ 91 static void 92 omap4_get_revision(void) 93 { 94 uint32_t id_code; 95 uint32_t revision; 96 uint32_t hawkeye; 97 bus_space_handle_t bsh; 98 99 /* The chip revsion is read from the device identification registers and 100 * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 101 * 0x4A00_2218. This is part of the L4_CORE memory range and should have 102 * been mapped in by the machdep.c code. 103 * 104 * STD_FUSE_DIE_ID_0 0x4A00 2200 105 * ID_CODE 0x4A00 2204 (this is the only one we need) 106 * STD_FUSE_DIE_ID_1 0x4A00 2208 107 * STD_FUSE_DIE_ID_2 0x4A00 220C 108 * STD_FUSE_DIE_ID_3 0x4A00 2210 109 * STD_FUSE_PROD_ID_0 0x4A00 2214 110 * STD_FUSE_PROD_ID_1 0x4A00 2218 111 */ 112 // id_code = REG_READ32(OMAP44XX_L4_CORE_VBASE + OMAP4_ID_CODE); 113 //FIXME Should we map somewhere else? 114 bus_space_map(fdtbus_bs_tag,OMAP44XX_L4_CORE_HWBASE, 0x4000, 0, &bsh); 115 id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP4_ID_CODE); 116 bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); 117 118 hawkeye = ((id_code >> 12) & 0xffff); 119 revision = ((id_code >> 28) & 0xf); 120 121 /* Apparently according to the linux code there were some ES2.0 samples that 122 * have the wrong id code and report themselves as ES1.0 silicon. So used 123 * the ARM cpuid to get the correct revision. 124 */ 125 if (revision == 0) { 126 id_code = cpufunc_id(); 127 revision = (id_code & 0xf) - 1; 128 } 129 130 switch (hawkeye) { 131 case 0xB852: 132 switch (revision) { 133 case 0: 134 chip_revision = OMAP4430_REV_ES1_0; 135 break; 136 case 1: 137 chip_revision = OMAP4430_REV_ES2_1; 138 break; 139 default: 140 chip_revision = OMAP4430_REV_UNKNOWN; 141 break; 142 } 143 break; 144 145 case 0xB95C: 146 switch (revision) { 147 case 3: 148 chip_revision = OMAP4430_REV_ES2_1; 149 break; 150 case 4: 151 chip_revision = OMAP4430_REV_ES2_2; 152 break; 153 case 6: 154 chip_revision = OMAP4430_REV_ES2_3; 155 break; 156 default: 157 chip_revision = OMAP4430_REV_UNKNOWN; 158 break; 159 } 160 break; 161 162 case 0xB94E: 163 switch (revision) { 164 case 0: 165 chip_revision = OMAP4460_REV_ES1_0; 166 break; 167 case 2: 168 chip_revision = OMAP4460_REV_ES1_1; 169 break; 170 default: 171 chip_revision = OMAP4460_REV_UNKNOWN; 172 break; 173 } 174 break; 175 176 case 0xB975: 177 switch (revision) { 178 case 0: 179 chip_revision = OMAP4470_REV_ES1_0; 180 break; 181 default: 182 chip_revision = OMAP4470_REV_UNKNOWN; 183 break; 184 } 185 break; 186 187 default: 188 /* Default to the latest revision if we can't determine type */ 189 chip_revision = OMAP_UNKNOWN_DEV; 190 break; 191 } 192 if (chip_revision != OMAP_UNKNOWN_DEV) { 193 printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 194 OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 195 OMAP_REV_MINOR(chip_revision)); 196 } 197 else { 198 printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n", 199 hawkeye, revision); 200 } 201 } 202 203 /** 204 * omap3_get_revision - determines omap3 revision 205 * 206 * Reads the registers to determine the revision of the chip we are currently 207 * running on. Stores the information in global variables. 208 * 209 * WARNING: This function currently only really works for OMAP3530 devices. 210 * 211 * 212 * 213 */ 214 static void 215 omap3_get_revision(void) 216 { 217 uint32_t id_code; 218 uint32_t revision; 219 uint32_t hawkeye; 220 bus_space_handle_t bsh; 221 222 /* The chip revsion is read from the device identification registers and 223 * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 224 * 0x4A00_2218. This is part of the L4_CORE memory range and should have 225 * been mapped in by the machdep.c code. 226 * 227 * CONTROL_IDCODE 0x4830 A204 (this is the only one we need) 228 * 229 * 230 */ 231 //id_code = REG_READ32(OMAP35XX_L4_WAKEUP_VBASE + OMAP3_ID_CODE); 232 bus_space_map(fdtbus_bs_tag,OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh); 233 id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP3_ID_CODE); 234 bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); 235 236 hawkeye = ((id_code >> 12) & 0xffff); 237 revision = ((id_code >> 28) & 0xf); 238 239 switch (hawkeye) { 240 case 0xB6D6: 241 chip_revision = OMAP3350_REV_ES1_0; 242 break; 243 case 0xB7AE: 244 if (revision == 1) 245 chip_revision = OMAP3530_REV_ES2_0; 246 else if (revision == 2) 247 chip_revision = OMAP3530_REV_ES2_1; 248 else if (revision == 3) 249 chip_revision = OMAP3530_REV_ES3_0; 250 else if (revision == 4) 251 chip_revision = OMAP3530_REV_ES3_1; 252 else if (revision == 7) 253 chip_revision = OMAP3530_REV_ES3_1_2; 254 break; 255 default: 256 /* Default to the latest revision if we can't determine type */ 257 chip_revision = OMAP3530_REV_ES3_1_2; 258 break; 259 } 260 printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 261 OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 262 OMAP_REV_MINOR(chip_revision)); 263 } 264 265 static void 266 am335x_get_revision(void) 267 { 268 uint32_t dev_feature; 269 uint8_t cpu_last_char; 270 bus_space_handle_t bsh; 271 272 bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh); 273 chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID); 274 dev_feature = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEV_FEATURE); 275 bus_space_unmap(fdtbus_bs_tag, bsh, AM335X_CONTROL_SIZE); 276 277 switch (dev_feature) { 278 case 0x00FF0382: 279 cpu_last_char='2'; 280 break; 281 case 0x20FF0382: 282 cpu_last_char='4'; 283 break; 284 case 0x00FF0383: 285 cpu_last_char='6'; 286 break; 287 case 0x00FE0383: 288 cpu_last_char='7'; 289 break; 290 case 0x20FF0383: 291 cpu_last_char='8'; 292 break; 293 case 0x20FE0383: 294 cpu_last_char='9'; 295 break; 296 default: 297 cpu_last_char='x'; 298 } 299 300 printf("Texas Instruments AM335%c Processor, Revision ES1.%u\n", 301 cpu_last_char, AM335X_DEVREV(chip_revision)); 302 } 303 304 /** 305 * ti_cpu_ident - attempts to identify the chip we are running on 306 * @dummy: ignored 307 * 308 * This function is called before any of the driver are initialised, however 309 * the basic virt to phys maps have been setup in machdep.c so we can still 310 * access the required registers, we just have to use direct register reads 311 * and writes rather than going through the bus stuff. 312 * 313 * 314 */ 315 static void 316 ti_cpu_ident(void *dummy) 317 { 318 switch(ti_chip()) { 319 case CHIP_OMAP_3: 320 omap3_get_revision(); 321 break; 322 case CHIP_OMAP_4: 323 omap4_get_revision(); 324 break; 325 case CHIP_AM335X: 326 am335x_get_revision(); 327 break; 328 default: 329 panic("Unknown chip type, fixme!\n"); 330 } 331 } 332 333 SYSINIT(ti_cpu_ident, SI_SUB_CPU, SI_ORDER_SECOND, ti_cpu_ident, NULL); 334