162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/arch/arm/mach-omap1/id.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * OMAP1 CPU identification code 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2004 Nokia Corporation 862306a36Sopenharmony_ci * Written by Tony Lindgren <tony@atomide.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/soc/ti/omap1-io.h> 1662306a36Sopenharmony_ci#include <asm/system_info.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "soc.h" 1962306a36Sopenharmony_ci#include "hardware.h" 2062306a36Sopenharmony_ci#include "common.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define OMAP_DIE_ID_0 0xfffe1800 2362306a36Sopenharmony_ci#define OMAP_DIE_ID_1 0xfffe1804 2462306a36Sopenharmony_ci#define OMAP_PRODUCTION_ID_0 0xfffe2000 2562306a36Sopenharmony_ci#define OMAP_PRODUCTION_ID_1 0xfffe2004 2662306a36Sopenharmony_ci#define OMAP32_ID_0 0xfffed400 2762306a36Sopenharmony_ci#define OMAP32_ID_1 0xfffed404 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct omap_id { 3062306a36Sopenharmony_ci u16 jtag_id; /* Used to determine OMAP type */ 3162306a36Sopenharmony_ci u8 die_rev; /* Processor revision */ 3262306a36Sopenharmony_ci u32 omap_id; /* OMAP revision */ 3362306a36Sopenharmony_ci u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic unsigned int omap_revision; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Register values to detect the OMAP version */ 3962306a36Sopenharmony_cistatic struct omap_id omap_ids[] __initdata = { 4062306a36Sopenharmony_ci { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, 4162306a36Sopenharmony_ci { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, 4262306a36Sopenharmony_ci { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, 4362306a36Sopenharmony_ci { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000}, 4462306a36Sopenharmony_ci { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, 4562306a36Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, 4662306a36Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, 4762306a36Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, 4862306a36Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, 4962306a36Sopenharmony_ci { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 5062306a36Sopenharmony_ci { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, 5162306a36Sopenharmony_ci { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, 5262306a36Sopenharmony_ci { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, 5362306a36Sopenharmony_ci { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, 5462306a36Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, 5562306a36Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, 5662306a36Sopenharmony_ci { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, 5762306a36Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, 5862306a36Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, 5962306a36Sopenharmony_ci { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciunsigned int omap_rev(void) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return omap_revision; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ciEXPORT_SYMBOL(omap_rev); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * Get OMAP type from PROD_ID. 7062306a36Sopenharmony_ci * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. 7162306a36Sopenharmony_ci * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. 7262306a36Sopenharmony_ci * Undocumented register in TEST BLOCK is used as fallback; This seems to 7362306a36Sopenharmony_ci * work on 1510, 1610 & 1710. The official way hopefully will work in future 7462306a36Sopenharmony_ci * processors. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_cistatic u16 __init omap_get_jtag_id(void) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci u32 prod_id, omap_id; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci prod_id = omap_readl(OMAP_PRODUCTION_ID_1); 8162306a36Sopenharmony_ci omap_id = omap_readl(OMAP32_ID_1); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */ 8462306a36Sopenharmony_ci if (((prod_id >> 20) == 0) || (prod_id == omap_id)) 8562306a36Sopenharmony_ci prod_id = 0; 8662306a36Sopenharmony_ci else 8762306a36Sopenharmony_ci prod_id &= 0xffff; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (prod_id) 9062306a36Sopenharmony_ci return prod_id; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Use OMAP32_ID_1 as fallback */ 9362306a36Sopenharmony_ci prod_id = ((omap_id >> 12) & 0xffff); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci return prod_id; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* 9962306a36Sopenharmony_ci * Get OMAP revision from DIE_REV. 10062306a36Sopenharmony_ci * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. 10162306a36Sopenharmony_ci * Undocumented register in the TEST BLOCK is used as fallback. 10262306a36Sopenharmony_ci * REVISIT: This does not seem to work on 1510 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_cistatic u8 __init omap_get_die_rev(void) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci u32 die_rev; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci die_rev = omap_readl(OMAP_DIE_ID_1); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Check for broken OMAP_DIE_ID on early 1710 */ 11162306a36Sopenharmony_ci if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) 11262306a36Sopenharmony_ci die_rev = 0; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci die_rev = (die_rev >> 17) & 0xf; 11562306a36Sopenharmony_ci if (die_rev) 11662306a36Sopenharmony_ci return die_rev; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return die_rev; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_civoid __init omap_check_revision(void) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci int i; 12662306a36Sopenharmony_ci u16 jtag_id; 12762306a36Sopenharmony_ci u8 die_rev; 12862306a36Sopenharmony_ci u32 omap_id; 12962306a36Sopenharmony_ci u8 cpu_type; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci jtag_id = omap_get_jtag_id(); 13262306a36Sopenharmony_ci die_rev = omap_get_die_rev(); 13362306a36Sopenharmony_ci omap_id = omap_readl(OMAP32_ID_0); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#ifdef DEBUG 13662306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); 13762306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", 13862306a36Sopenharmony_ci omap_readl(OMAP_DIE_ID_1), 13962306a36Sopenharmony_ci (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); 14062306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n", 14162306a36Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_0)); 14262306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", 14362306a36Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_1), 14462306a36Sopenharmony_ci omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); 14562306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); 14662306a36Sopenharmony_ci printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); 14762306a36Sopenharmony_ci printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); 14862306a36Sopenharmony_ci#endif 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci system_serial_high = omap_readl(OMAP_DIE_ID_0); 15162306a36Sopenharmony_ci system_serial_low = omap_readl(OMAP_DIE_ID_1); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* First check only the major version in a safe way */ 15462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 15562306a36Sopenharmony_ci if (jtag_id == (omap_ids[i].jtag_id)) { 15662306a36Sopenharmony_ci omap_revision = omap_ids[i].type; 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Check if we can find the die revision */ 16262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 16362306a36Sopenharmony_ci if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { 16462306a36Sopenharmony_ci omap_revision = omap_ids[i].type; 16562306a36Sopenharmony_ci break; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* Finally check also the omap_id */ 17062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { 17162306a36Sopenharmony_ci if (jtag_id == omap_ids[i].jtag_id 17262306a36Sopenharmony_ci && die_rev == omap_ids[i].die_rev 17362306a36Sopenharmony_ci && omap_id == omap_ids[i].omap_id) { 17462306a36Sopenharmony_ci omap_revision = omap_ids[i].type; 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ 18062306a36Sopenharmony_ci cpu_type = omap_revision >> 24; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci switch (cpu_type) { 18362306a36Sopenharmony_ci case 0x07: 18462306a36Sopenharmony_ci case 0x08: 18562306a36Sopenharmony_ci omap_revision |= 0x07; 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci case 0x03: 18862306a36Sopenharmony_ci case 0x15: 18962306a36Sopenharmony_ci omap_revision |= 0x15; 19062306a36Sopenharmony_ci break; 19162306a36Sopenharmony_ci case 0x16: 19262306a36Sopenharmony_ci case 0x17: 19362306a36Sopenharmony_ci omap_revision |= 0x16; 19462306a36Sopenharmony_ci break; 19562306a36Sopenharmony_ci default: 19662306a36Sopenharmony_ci printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci pr_info("OMAP%04x", omap_revision >> 16); 20062306a36Sopenharmony_ci if ((omap_revision >> 8) & 0xff) 20162306a36Sopenharmony_ci pr_cont("%x", (omap_revision >> 8) & 0xff); 20262306a36Sopenharmony_ci pr_cont(" revision %i handled as %02xxx id: %08x%08x\n", 20362306a36Sopenharmony_ci die_rev, omap_revision & 0xff, system_serial_low, 20462306a36Sopenharmony_ci system_serial_high); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 207