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/resource.h> 44 #include <machine/intr.h> 45 46 #include <arm/ti/tivar.h> 47 #include <arm/ti/ti_cpuid.h> 48 49 #include <arm/ti/omap4/omap4_reg.h> 50 #include <arm/ti/am335x/am335x_reg.h> 51 52 #define OMAP4_STD_FUSE_DIE_ID_0 0x2200 53 #define OMAP4_ID_CODE 0x2204 54 #define OMAP4_STD_FUSE_DIE_ID_1 0x2208 55 #define OMAP4_STD_FUSE_DIE_ID_2 0x220C 56 #define OMAP4_STD_FUSE_DIE_ID_3 0x2210 57 #define OMAP4_STD_FUSE_PROD_ID_0 0x2214 58 #define OMAP4_STD_FUSE_PROD_ID_1 0x2218 59 60 #define OMAP3_ID_CODE 0xA204 61 62 static uint32_t chip_revision = 0xffffffff; 63 64 /** 65 * ti_revision - Returns the revision number of the device 66 * 67 * Simply returns an identifier for the revision of the chip we are running 68 * on. 69 * 70 * RETURNS 71 * A 32-bit identifier for the current chip 72 */ 73 uint32_t 74 ti_revision(void) 75 { 76 return chip_revision; 77 } 78 79 /** 80 * omap4_get_revision - determines omap4 revision 81 * 82 * Reads the registers to determine the revision of the chip we are currently 83 * running on. Stores the information in global variables. 84 * 85 * 86 */ 87 static void 88 omap4_get_revision(void) 89 { 90 uint32_t id_code; 91 uint32_t revision; 92 uint32_t hawkeye; 93 bus_space_handle_t bsh; 94 95 /* The chip revsion is read from the device identification registers and 96 * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 97 * 0x4A00_2218. This is part of the L4_CORE memory range and should have 98 * been mapped in by the machdep.c code. 99 * 100 * STD_FUSE_DIE_ID_0 0x4A00 2200 101 * ID_CODE 0x4A00 2204 (this is the only one we need) 102 * STD_FUSE_DIE_ID_1 0x4A00 2208 103 * STD_FUSE_DIE_ID_2 0x4A00 220C 104 * STD_FUSE_DIE_ID_3 0x4A00 2210 105 * STD_FUSE_PROD_ID_0 0x4A00 2214 106 * STD_FUSE_PROD_ID_1 0x4A00 2218 107 */ 108 /* FIXME Should we map somewhere else? */ 109 bus_space_map(fdtbus_bs_tag,OMAP44XX_L4_CORE_HWBASE, 0x4000, 0, &bsh); 110 id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP4_ID_CODE); 111 bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); 112 113 hawkeye = ((id_code >> 12) & 0xffff); 114 revision = ((id_code >> 28) & 0xf); 115 116 /* Apparently according to the linux code there were some ES2.0 samples that 117 * have the wrong id code and report themselves as ES1.0 silicon. So used 118 * the ARM cpuid to get the correct revision. 119 */ 120 if (revision == 0) { 121 id_code = cpu_ident(); 122 revision = (id_code & 0xf) - 1; 123 } 124 125 switch (hawkeye) { 126 case 0xB852: 127 switch (revision) { 128 case 0: 129 chip_revision = OMAP4430_REV_ES1_0; 130 break; 131 case 1: 132 chip_revision = OMAP4430_REV_ES2_1; 133 break; 134 default: 135 chip_revision = OMAP4430_REV_UNKNOWN; 136 break; 137 } 138 break; 139 140 case 0xB95C: 141 switch (revision) { 142 case 3: 143 chip_revision = OMAP4430_REV_ES2_1; 144 break; 145 case 4: 146 chip_revision = OMAP4430_REV_ES2_2; 147 break; 148 case 6: 149 chip_revision = OMAP4430_REV_ES2_3; 150 break; 151 default: 152 chip_revision = OMAP4430_REV_UNKNOWN; 153 break; 154 } 155 break; 156 157 case 0xB94E: 158 switch (revision) { 159 case 0: 160 chip_revision = OMAP4460_REV_ES1_0; 161 break; 162 case 2: 163 chip_revision = OMAP4460_REV_ES1_1; 164 break; 165 default: 166 chip_revision = OMAP4460_REV_UNKNOWN; 167 break; 168 } 169 break; 170 171 case 0xB975: 172 switch (revision) { 173 case 0: 174 chip_revision = OMAP4470_REV_ES1_0; 175 break; 176 default: 177 chip_revision = OMAP4470_REV_UNKNOWN; 178 break; 179 } 180 break; 181 182 default: 183 /* Default to the latest revision if we can't determine type */ 184 chip_revision = OMAP_UNKNOWN_DEV; 185 break; 186 } 187 if (chip_revision != OMAP_UNKNOWN_DEV) { 188 printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 189 OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 190 OMAP_REV_MINOR(chip_revision)); 191 } 192 else { 193 printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n", 194 hawkeye, revision); 195 } 196 } 197 198 static void 199 am335x_get_revision(void) 200 { 201 uint32_t dev_feature; 202 char cpu_last_char; 203 bus_space_handle_t bsh; 204 int major; 205 int minor; 206 207 bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh); 208 chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID); 209 dev_feature = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEV_FEATURE); 210 bus_space_unmap(fdtbus_bs_tag, bsh, AM335X_CONTROL_SIZE); 211 212 switch (dev_feature) { 213 case 0x00FF0382: 214 cpu_last_char='2'; 215 break; 216 case 0x20FF0382: 217 cpu_last_char='4'; 218 break; 219 case 0x00FF0383: 220 cpu_last_char='6'; 221 break; 222 case 0x00FE0383: 223 cpu_last_char='7'; 224 break; 225 case 0x20FF0383: 226 cpu_last_char='8'; 227 break; 228 case 0x20FE0383: 229 cpu_last_char='9'; 230 break; 231 default: 232 cpu_last_char='x'; 233 } 234 235 switch(AM335X_DEVREV(chip_revision)) { 236 case 0: 237 major = 1; 238 minor = 0; 239 break; 240 case 1: 241 major = 2; 242 minor = 0; 243 break; 244 case 2: 245 major = 2; 246 minor = 1; 247 break; 248 default: 249 major = 0; 250 minor = AM335X_DEVREV(chip_revision); 251 break; 252 } 253 printf("Texas Instruments AM335%c Processor, Revision ES%u.%u\n", 254 cpu_last_char, major, minor); 255 } 256 257 /** 258 * ti_cpu_ident - attempts to identify the chip we are running on 259 * @dummy: ignored 260 * 261 * This function is called before any of the driver are initialised, however 262 * the basic virt to phys maps have been setup in machdep.c so we can still 263 * access the required registers, we just have to use direct register reads 264 * and writes rather than going through the bus stuff. 265 * 266 * 267 */ 268 static void 269 ti_cpu_ident(void *dummy) 270 { 271 switch(ti_chip()) { 272 case CHIP_OMAP_4: 273 omap4_get_revision(); 274 break; 275 case CHIP_AM335X: 276 am335x_get_revision(); 277 break; 278 default: 279 panic("Unknown chip type, fixme!\n"); 280 } 281 } 282 283 SYSINIT(ti_cpu_ident, SI_SUB_CPU, SI_ORDER_SECOND, ti_cpu_ident, NULL); 284