Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/arch/arm/mach-omap1/id.c
0004  *
0005  * OMAP1 CPU identification code
0006  *
0007  * Copyright (C) 2004 Nokia Corporation
0008  * Written by Tony Lindgren <tony@atomide.com>
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/init.h>
0014 #include <linux/io.h>
0015 #include <linux/soc/ti/omap1-io.h>
0016 #include <asm/system_info.h>
0017 
0018 #include "soc.h"
0019 #include "hardware.h"
0020 #include "common.h"
0021 
0022 #define OMAP_DIE_ID_0       0xfffe1800
0023 #define OMAP_DIE_ID_1       0xfffe1804
0024 #define OMAP_PRODUCTION_ID_0    0xfffe2000
0025 #define OMAP_PRODUCTION_ID_1    0xfffe2004
0026 #define OMAP32_ID_0     0xfffed400
0027 #define OMAP32_ID_1     0xfffed404
0028 
0029 struct omap_id {
0030     u16 jtag_id;    /* Used to determine OMAP type */
0031     u8  die_rev;    /* Processor revision */
0032     u32 omap_id;    /* OMAP revision */
0033     u32 type;       /* Cpu id bits [31:08], cpu class bits [07:00] */
0034 };
0035 
0036 static unsigned int omap_revision;
0037 
0038 /* Register values to detect the OMAP version */
0039 static struct omap_id omap_ids[] __initdata = {
0040     { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
0041     { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
0042     { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
0043     { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000},
0044     { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
0045     { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
0046     { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
0047     { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
0048     { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
0049     { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
0050     { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
0051     { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
0052     { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
0053     { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
0054     { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
0055     { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
0056     { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
0057     { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
0058     { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
0059     { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
0060 };
0061 
0062 unsigned int omap_rev(void)
0063 {
0064     return omap_revision;
0065 }
0066 EXPORT_SYMBOL(omap_rev);
0067 
0068 /*
0069  * Get OMAP type from PROD_ID.
0070  * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
0071  * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
0072  * Undocumented register in TEST BLOCK is used as fallback; This seems to
0073  * work on 1510, 1610 & 1710. The official way hopefully will work in future
0074  * processors.
0075  */
0076 static u16 __init omap_get_jtag_id(void)
0077 {
0078     u32 prod_id, omap_id;
0079 
0080     prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
0081     omap_id = omap_readl(OMAP32_ID_1);
0082 
0083     /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */
0084     if (((prod_id >> 20) == 0) || (prod_id == omap_id))
0085         prod_id = 0;
0086     else
0087         prod_id &= 0xffff;
0088 
0089     if (prod_id)
0090         return prod_id;
0091 
0092     /* Use OMAP32_ID_1 as fallback */
0093     prod_id = ((omap_id >> 12) & 0xffff);
0094 
0095     return prod_id;
0096 }
0097 
0098 /*
0099  * Get OMAP revision from DIE_REV.
0100  * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
0101  * Undocumented register in the TEST BLOCK is used as fallback.
0102  * REVISIT: This does not seem to work on 1510
0103  */
0104 static u8 __init omap_get_die_rev(void)
0105 {
0106     u32 die_rev;
0107 
0108     die_rev = omap_readl(OMAP_DIE_ID_1);
0109 
0110     /* Check for broken OMAP_DIE_ID on early 1710 */
0111     if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
0112         die_rev = 0;
0113 
0114     die_rev = (die_rev >> 17) & 0xf;
0115     if (die_rev)
0116         return die_rev;
0117 
0118     die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
0119 
0120     return die_rev;
0121 }
0122 
0123 void __init omap_check_revision(void)
0124 {
0125     int i;
0126     u16 jtag_id;
0127     u8 die_rev;
0128     u32 omap_id;
0129     u8 cpu_type;
0130 
0131     jtag_id = omap_get_jtag_id();
0132     die_rev = omap_get_die_rev();
0133     omap_id = omap_readl(OMAP32_ID_0);
0134 
0135 #ifdef DEBUG
0136     printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
0137     printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
0138         omap_readl(OMAP_DIE_ID_1),
0139            (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
0140     printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n",
0141         omap_readl(OMAP_PRODUCTION_ID_0));
0142     printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
0143         omap_readl(OMAP_PRODUCTION_ID_1),
0144         omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
0145     printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
0146     printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
0147     printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
0148 #endif
0149 
0150     system_serial_high = omap_readl(OMAP_DIE_ID_0);
0151     system_serial_low = omap_readl(OMAP_DIE_ID_1);
0152 
0153     /* First check only the major version in a safe way */
0154     for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
0155         if (jtag_id == (omap_ids[i].jtag_id)) {
0156             omap_revision = omap_ids[i].type;
0157             break;
0158         }
0159     }
0160 
0161     /* Check if we can find the die revision */
0162     for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
0163         if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
0164             omap_revision = omap_ids[i].type;
0165             break;
0166         }
0167     }
0168 
0169     /* Finally check also the omap_id */
0170     for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
0171         if (jtag_id == omap_ids[i].jtag_id
0172             && die_rev == omap_ids[i].die_rev
0173             && omap_id == omap_ids[i].omap_id) {
0174             omap_revision = omap_ids[i].type;
0175             break;
0176         }
0177     }
0178 
0179     /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
0180     cpu_type = omap_revision >> 24;
0181 
0182     switch (cpu_type) {
0183     case 0x07:
0184     case 0x08:
0185         omap_revision |= 0x07;
0186         break;
0187     case 0x03:
0188     case 0x15:
0189         omap_revision |= 0x15;
0190         break;
0191     case 0x16:
0192     case 0x17:
0193         omap_revision |= 0x16;
0194         break;
0195     default:
0196         printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type);
0197     }
0198 
0199     pr_info("OMAP%04x", omap_revision >> 16);
0200     if ((omap_revision >> 8) & 0xff)
0201         pr_cont("%x", (omap_revision >> 8) & 0xff);
0202     pr_cont(" revision %i handled as %02xxx id: %08x%08x\n",
0203            die_rev, omap_revision & 0xff, system_serial_low,
0204            system_serial_high);
0205 }
0206