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