1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/arch/arm/mach-omap1/id.c 4 * 5 * OMAP1 CPU identification code 6 * 7 * Copyright (C) 2004 Nokia Corporation 8 * Written by Tony Lindgren <tony@atomide.com> 9 */ 10 11 #include <linux/module.h> 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/io.h> 15 #include <linux/soc/ti/omap1-io.h> 16 #include <asm/system_info.h> 17 18 #include "soc.h" 19 #include "hardware.h" 20 #include "common.h" 21 22 #define OMAP_DIE_ID_0 0xfffe1800 23 #define OMAP_DIE_ID_1 0xfffe1804 24 #define OMAP_PRODUCTION_ID_0 0xfffe2000 25 #define OMAP_PRODUCTION_ID_1 0xfffe2004 26 #define OMAP32_ID_0 0xfffed400 27 #define OMAP32_ID_1 0xfffed404 28 29 struct omap_id { 30 u16 jtag_id; /* Used to determine OMAP type */ 31 u8 die_rev; /* Processor revision */ 32 u32 omap_id; /* OMAP revision */ 33 u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ 34 }; 35 36 static unsigned int omap_revision; 37 38 /* Register values to detect the OMAP version */ 39 static struct omap_id omap_ids[] __initdata = { 40 { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, 41 { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, 42 { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, 43 { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000}, 44 { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, 45 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, 46 { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, 47 { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, 48 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, 49 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 50 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 51 { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, 52 { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, 53 { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, 54 { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, 55 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, 56 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, 57 { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, 58 { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, 59 { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, 60 }; 61 62 unsigned int omap_rev(void) 63 { 64 return omap_revision; 65 } 66 EXPORT_SYMBOL(omap_rev); 67 68 /* 69 * Get OMAP type from PROD_ID. 70 * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. 71 * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. 72 * Undocumented register in TEST BLOCK is used as fallback; This seems to 73 * work on 1510, 1610 & 1710. The official way hopefully will work in future 74 * processors. 75 */ 76 static u16 __init omap_get_jtag_id(void) 77 { 78 u32 prod_id, omap_id; 79 80 prod_id = omap_readl(OMAP_PRODUCTION_ID_1); 81 omap_id = omap_readl(OMAP32_ID_1); 82 83 /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */ 84 if (((prod_id >> 20) == 0) || (prod_id == omap_id)) 85 prod_id = 0; 86 else 87 prod_id &= 0xffff; 88 89 if (prod_id) 90 return prod_id; 91 92 /* Use OMAP32_ID_1 as fallback */ 93 prod_id = ((omap_id >> 12) & 0xffff); 94 95 return prod_id; 96 } 97 98 /* 99 * Get OMAP revision from DIE_REV. 100 * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. 101 * Undocumented register in the TEST BLOCK is used as fallback. 102 * REVISIT: This does not seem to work on 1510 103 */ 104 static u8 __init omap_get_die_rev(void) 105 { 106 u32 die_rev; 107 108 die_rev = omap_readl(OMAP_DIE_ID_1); 109 110 /* Check for broken OMAP_DIE_ID on early 1710 */ 111 if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) 112 die_rev = 0; 113 114 die_rev = (die_rev >> 17) & 0xf; 115 if (die_rev) 116 return die_rev; 117 118 die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; 119 120 return die_rev; 121 } 122 123 void __init omap_check_revision(void) 124 { 125 int i; 126 u16 jtag_id; 127 u8 die_rev; 128 u32 omap_id; 129 u8 cpu_type; 130 131 jtag_id = omap_get_jtag_id(); 132 die_rev = omap_get_die_rev(); 133 omap_id = omap_readl(OMAP32_ID_0); 134 135 #ifdef DEBUG 136 printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); 137 printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", 138 omap_readl(OMAP_DIE_ID_1), 139 (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); 140 printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n", 141 omap_readl(OMAP_PRODUCTION_ID_0)); 142 printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", 143 omap_readl(OMAP_PRODUCTION_ID_1), 144 omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); 145 printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); 146 printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); 147 printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); 148 #endif 149 150 system_serial_high = omap_readl(OMAP_DIE_ID_0); 151 system_serial_low = omap_readl(OMAP_DIE_ID_1); 152 153 /* First check only the major version in a safe way */ 154 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 155 if (jtag_id == (omap_ids[i].jtag_id)) { 156 omap_revision = omap_ids[i].type; 157 break; 158 } 159 } 160 161 /* Check if we can find the die revision */ 162 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 163 if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { 164 omap_revision = omap_ids[i].type; 165 break; 166 } 167 } 168 169 /* Finally check also the omap_id */ 170 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 171 if (jtag_id == omap_ids[i].jtag_id 172 && die_rev == omap_ids[i].die_rev 173 && omap_id == omap_ids[i].omap_id) { 174 omap_revision = omap_ids[i].type; 175 break; 176 } 177 } 178 179 /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ 180 cpu_type = omap_revision >> 24; 181 182 switch (cpu_type) { 183 case 0x07: 184 case 0x08: 185 omap_revision |= 0x07; 186 break; 187 case 0x03: 188 case 0x15: 189 omap_revision |= 0x15; 190 break; 191 case 0x16: 192 case 0x17: 193 omap_revision |= 0x16; 194 break; 195 default: 196 printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type); 197 } 198 199 pr_info("OMAP%04x", omap_revision >> 16); 200 if ((omap_revision >> 8) & 0xff) 201 pr_cont("%x", (omap_revision >> 8) & 0xff); 202 pr_cont(" revision %i handled as %02xxx id: %08x%08x\n", 203 die_rev, omap_revision & 0xff, system_serial_low, 204 system_serial_high); 205 } 206 207