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 if (revision == 0) 133 chip_revision = OMAP4430_REV_ES1_0; 134 else 135 chip_revision = OMAP4430_REV_ES2_0; 136 break; 137 case 0xB95C: 138 if (revision == 3) 139 chip_revision = OMAP4430_REV_ES2_1; 140 else if (revision == 4) 141 chip_revision = OMAP4430_REV_ES2_2; 142 else 143 chip_revision = OMAP4430_REV_ES2_3; 144 break; 145 default: 146 /* Default to the latest revision if we can't determine type */ 147 chip_revision = OMAP4430_REV_ES2_3; 148 break; 149 } 150 printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 151 OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 152 OMAP_REV_MINOR(chip_revision)); 153 } 154 155 /** 156 * omap3_get_revision - determines omap3 revision 157 * 158 * Reads the registers to determine the revision of the chip we are currently 159 * running on. Stores the information in global variables. 160 * 161 * WARNING: This function currently only really works for OMAP3530 devices. 162 * 163 * 164 * 165 */ 166 static void 167 omap3_get_revision(void) 168 { 169 uint32_t id_code; 170 uint32_t revision; 171 uint32_t hawkeye; 172 bus_space_handle_t bsh; 173 174 /* The chip revsion is read from the device identification registers and 175 * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to 176 * 0x4A00_2218. This is part of the L4_CORE memory range and should have 177 * been mapped in by the machdep.c code. 178 * 179 * CONTROL_IDCODE 0x4830 A204 (this is the only one we need) 180 * 181 * 182 */ 183 //id_code = REG_READ32(OMAP35XX_L4_WAKEUP_VBASE + OMAP3_ID_CODE); 184 bus_space_map(fdtbus_bs_tag,OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh); 185 id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP3_ID_CODE); 186 bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); 187 188 hawkeye = ((id_code >> 12) & 0xffff); 189 revision = ((id_code >> 28) & 0xf); 190 191 switch (hawkeye) { 192 case 0xB6D6: 193 chip_revision = OMAP3350_REV_ES1_0; 194 break; 195 case 0xB7AE: 196 if (revision == 1) 197 chip_revision = OMAP3530_REV_ES2_0; 198 else if (revision == 2) 199 chip_revision = OMAP3530_REV_ES2_1; 200 else if (revision == 3) 201 chip_revision = OMAP3530_REV_ES3_0; 202 else if (revision == 4) 203 chip_revision = OMAP3530_REV_ES3_1; 204 else if (revision == 7) 205 chip_revision = OMAP3530_REV_ES3_1_2; 206 break; 207 default: 208 /* Default to the latest revision if we can't determine type */ 209 chip_revision = OMAP3530_REV_ES3_1_2; 210 break; 211 } 212 printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n", 213 OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision), 214 OMAP_REV_MINOR(chip_revision)); 215 } 216 217 static void 218 am335x_get_revision(void) 219 { 220 uint32_t dev_feature; 221 uint8_t cpu_last_char; 222 bus_space_handle_t bsh; 223 224 bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh); 225 chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID); 226 dev_feature = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEV_FEATURE); 227 bus_space_unmap(fdtbus_bs_tag, bsh, AM335X_CONTROL_SIZE); 228 229 switch (dev_feature) { 230 case 0x00FF0382: 231 cpu_last_char='2'; 232 break; 233 case 0x20FF0382: 234 cpu_last_char='4'; 235 break; 236 case 0x00FF0383: 237 cpu_last_char='6'; 238 break; 239 case 0x00FE0383: 240 cpu_last_char='7'; 241 break; 242 case 0x20FF0383: 243 cpu_last_char='8'; 244 break; 245 case 0x20FE0383: 246 cpu_last_char='9'; 247 break; 248 default: 249 cpu_last_char='x'; 250 } 251 252 printf("Texas Instruments AM335%c Processor, Revision ES1.%u\n", 253 cpu_last_char, AM335X_DEVREV(chip_revision)); 254 } 255 256 /** 257 * ti_cpu_ident - attempts to identify the chip we are running on 258 * @dummy: ignored 259 * 260 * This function is called before any of the driver are initialised, however 261 * the basic virt to phys maps have been setup in machdep.c so we can still 262 * access the required registers, we just have to use direct register reads 263 * and writes rather than going through the bus stuff. 264 * 265 * 266 */ 267 static void 268 ti_cpu_ident(void *dummy) 269 { 270 switch(ti_chip()) { 271 case CHIP_OMAP_3: 272 omap3_get_revision(); 273 break; 274 case CHIP_OMAP_4: 275 omap4_get_revision(); 276 break; 277 case CHIP_AM335X: 278 am335x_get_revision(); 279 break; 280 default: 281 panic("Unknown chip type, fixme!\n"); 282 } 283 } 284 285 SYSINIT(ti_cpu_ident, SI_SUB_CPU, SI_ORDER_SECOND, ti_cpu_ident, NULL); 286