18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-omap1/id.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * OMAP1 CPU identification code 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2004 Nokia Corporation 88c2ecf20Sopenharmony_ci * Written by Tony Lindgren <tony@atomide.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/io.h> 158c2ecf20Sopenharmony_ci#include <asm/system_info.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "soc.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <mach/hardware.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "common.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define OMAP_DIE_ID_0 0xfffe1800 248c2ecf20Sopenharmony_ci#define OMAP_DIE_ID_1 0xfffe1804 258c2ecf20Sopenharmony_ci#define OMAP_PRODUCTION_ID_0 0xfffe2000 268c2ecf20Sopenharmony_ci#define OMAP_PRODUCTION_ID_1 0xfffe2004 278c2ecf20Sopenharmony_ci#define OMAP32_ID_0 0xfffed400 288c2ecf20Sopenharmony_ci#define OMAP32_ID_1 0xfffed404 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct omap_id { 318c2ecf20Sopenharmony_ci u16 jtag_id; /* Used to determine OMAP type */ 328c2ecf20Sopenharmony_ci u8 die_rev; /* Processor revision */ 338c2ecf20Sopenharmony_ci u32 omap_id; /* OMAP revision */ 348c2ecf20Sopenharmony_ci u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic unsigned int omap_revision; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* Register values to detect the OMAP version */ 408c2ecf20Sopenharmony_cistatic struct omap_id omap_ids[] __initdata = { 418c2ecf20Sopenharmony_ci { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, 428c2ecf20Sopenharmony_ci { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, 438c2ecf20Sopenharmony_ci { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, 448c2ecf20Sopenharmony_ci { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000}, 458c2ecf20Sopenharmony_ci { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, 468c2ecf20Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, 478c2ecf20Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, 488c2ecf20Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, 498c2ecf20Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, 508c2ecf20Sopenharmony_ci { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 518c2ecf20Sopenharmony_ci { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 528c2ecf20Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, 538c2ecf20Sopenharmony_ci { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, 548c2ecf20Sopenharmony_ci { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, 558c2ecf20Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, 568c2ecf20Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, 578c2ecf20Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, 588c2ecf20Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, 598c2ecf20Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, 608c2ecf20Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciunsigned int omap_rev(void) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return omap_revision; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(omap_rev); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* 708c2ecf20Sopenharmony_ci * Get OMAP type from PROD_ID. 718c2ecf20Sopenharmony_ci * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. 728c2ecf20Sopenharmony_ci * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. 738c2ecf20Sopenharmony_ci * Undocumented register in TEST BLOCK is used as fallback; This seems to 748c2ecf20Sopenharmony_ci * work on 1510, 1610 & 1710. The official way hopefully will work in future 758c2ecf20Sopenharmony_ci * processors. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_cistatic u16 __init omap_get_jtag_id(void) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci u32 prod_id, omap_id; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci prod_id = omap_readl(OMAP_PRODUCTION_ID_1); 828c2ecf20Sopenharmony_ci omap_id = omap_readl(OMAP32_ID_1); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */ 858c2ecf20Sopenharmony_ci if (((prod_id >> 20) == 0) || (prod_id == omap_id)) 868c2ecf20Sopenharmony_ci prod_id = 0; 878c2ecf20Sopenharmony_ci else 888c2ecf20Sopenharmony_ci prod_id &= 0xffff; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (prod_id) 918c2ecf20Sopenharmony_ci return prod_id; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Use OMAP32_ID_1 as fallback */ 948c2ecf20Sopenharmony_ci prod_id = ((omap_id >> 12) & 0xffff); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci return prod_id; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* 1008c2ecf20Sopenharmony_ci * Get OMAP revision from DIE_REV. 1018c2ecf20Sopenharmony_ci * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. 1028c2ecf20Sopenharmony_ci * Undocumented register in the TEST BLOCK is used as fallback. 1038c2ecf20Sopenharmony_ci * REVISIT: This does not seem to work on 1510 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic u8 __init omap_get_die_rev(void) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci u32 die_rev; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci die_rev = omap_readl(OMAP_DIE_ID_1); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* Check for broken OMAP_DIE_ID on early 1710 */ 1128c2ecf20Sopenharmony_ci if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) 1138c2ecf20Sopenharmony_ci die_rev = 0; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci die_rev = (die_rev >> 17) & 0xf; 1168c2ecf20Sopenharmony_ci if (die_rev) 1178c2ecf20Sopenharmony_ci return die_rev; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return die_rev; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_civoid __init omap_check_revision(void) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int i; 1278c2ecf20Sopenharmony_ci u16 jtag_id; 1288c2ecf20Sopenharmony_ci u8 die_rev; 1298c2ecf20Sopenharmony_ci u32 omap_id; 1308c2ecf20Sopenharmony_ci u8 cpu_type; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci jtag_id = omap_get_jtag_id(); 1338c2ecf20Sopenharmony_ci die_rev = omap_get_die_rev(); 1348c2ecf20Sopenharmony_ci omap_id = omap_readl(OMAP32_ID_0); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci#ifdef DEBUG 1378c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); 1388c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", 1398c2ecf20Sopenharmony_ci omap_readl(OMAP_DIE_ID_1), 1408c2ecf20Sopenharmony_ci (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); 1418c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n", 1428c2ecf20Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_0)); 1438c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", 1448c2ecf20Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_1), 1458c2ecf20Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); 1468c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); 1478c2ecf20Sopenharmony_ci printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); 1488c2ecf20Sopenharmony_ci printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); 1498c2ecf20Sopenharmony_ci#endif 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci system_serial_high = omap_readl(OMAP_DIE_ID_0); 1528c2ecf20Sopenharmony_ci system_serial_low = omap_readl(OMAP_DIE_ID_1); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* First check only the major version in a safe way */ 1558c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 1568c2ecf20Sopenharmony_ci if (jtag_id == (omap_ids[i].jtag_id)) { 1578c2ecf20Sopenharmony_ci omap_revision = omap_ids[i].type; 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* Check if we can find the die revision */ 1638c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 1648c2ecf20Sopenharmony_ci if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { 1658c2ecf20Sopenharmony_ci omap_revision = omap_ids[i].type; 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* Finally check also the omap_id */ 1718c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 1728c2ecf20Sopenharmony_ci if (jtag_id == omap_ids[i].jtag_id 1738c2ecf20Sopenharmony_ci && die_rev == omap_ids[i].die_rev 1748c2ecf20Sopenharmony_ci && omap_id == omap_ids[i].omap_id) { 1758c2ecf20Sopenharmony_ci omap_revision = omap_ids[i].type; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ 1818c2ecf20Sopenharmony_ci cpu_type = omap_revision >> 24; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci switch (cpu_type) { 1848c2ecf20Sopenharmony_ci case 0x07: 1858c2ecf20Sopenharmony_ci case 0x08: 1868c2ecf20Sopenharmony_ci omap_revision |= 0x07; 1878c2ecf20Sopenharmony_ci break; 1888c2ecf20Sopenharmony_ci case 0x03: 1898c2ecf20Sopenharmony_ci case 0x15: 1908c2ecf20Sopenharmony_ci omap_revision |= 0x15; 1918c2ecf20Sopenharmony_ci break; 1928c2ecf20Sopenharmony_ci case 0x16: 1938c2ecf20Sopenharmony_ci case 0x17: 1948c2ecf20Sopenharmony_ci omap_revision |= 0x16; 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci default: 1978c2ecf20Sopenharmony_ci printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type); 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci pr_info("OMAP%04x", omap_revision >> 16); 2018c2ecf20Sopenharmony_ci if ((omap_revision >> 8) & 0xff) 2028c2ecf20Sopenharmony_ci pr_cont("%x", (omap_revision >> 8) & 0xff); 2038c2ecf20Sopenharmony_ci pr_cont(" revision %i handled as %02xxx id: %08x%08x\n", 2048c2ecf20Sopenharmony_ci die_rev, omap_revision & 0xff, system_serial_low, 2058c2ecf20Sopenharmony_ci system_serial_high); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 208