]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
ARM: 6331/1: ux500 cpu/SoC version macros v2
authorLinus Walleij <linus.walleij@stericsson.com>
Thu, 19 Aug 2010 09:27:49 +0000 (10:27 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 2 Sep 2010 14:46:19 +0000 (15:46 +0100)
This patch adds support for checking if the digital baseband (DB)
System-on-Chip (aka "cpu) ASIC hardware version is 1.0, 1.1 or
2.0. We print the result in the bootlog, the functions are then
used for runtime decisions based on hardware version.

Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/include/mach/db8500-regs.h
arch/arm/mach-ux500/include/mach/hardware.h
arch/arm/mach-ux500/include/mach/setup.h

index f21c444edd99f76db8b78ccd1b1bcfc1464c181b..4acab7544b3c1e95ea9a9f2c73cf0f1ffd34847d 100644 (file)
@@ -38,10 +38,12 @@ static struct platform_device *platform_devs[] __initdata = {
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
+       __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+       __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
 };
 
 static struct map_desc u8500ed_io_desc[] __initdata = {
@@ -53,6 +55,69 @@ static struct map_desc u8500v1_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
 };
 
+/*
+ * Functions to differentiate between later ASICs
+ * We look into the end of the ROM to locate the hardcoded ASIC ID.
+ * This is only needed to differentiate between minor revisions and
+ * process variants of an ASIC, the major revisions are encoded in
+ * the cpuid.
+ */
+#define U8500_ASIC_ID_LOC_ED_V1        (U8500_BOOT_ROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2   (U8500_BOOT_ROM_BASE + 0x1DBF4)
+#define U8500_ASIC_REV_ED      0x01
+#define U8500_ASIC_REV_V10     0xA0
+#define U8500_ASIC_REV_V11     0xA1
+#define U8500_ASIC_REV_V20     0xB0
+
+/**
+ * struct db8500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm
+ *  0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ * This field definion is not formally defined but makes
+ * sense.
+ */
+struct db8500_asic_id {
+       u8 process;
+       u16 partnumber;
+       u8 revision;
+};
+
+/* This isn't going to change at runtime */
+static struct db8500_asic_id db8500_id;
+
+static void __init get_db8500_asic_id(void)
+{
+       u32 asicid;
+
+       if (cpu_is_u8500v1() || cpu_is_u8500ed())
+               asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
+       else if (cpu_is_u8500v2())
+               asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
+       else
+               BUG();
+
+       db8500_id.process = (asicid >> 24);
+       db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
+       db8500_id.revision = asicid & 0xFFU;
+}
+
+bool cpu_is_u8500v10(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V10);
+}
+
+bool cpu_is_u8500v11(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V11);
+}
+
+bool cpu_is_u8500v20(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V20);
+}
+
 void __init u8500_map_io(void)
 {
        ux500_map_io();
@@ -63,6 +128,9 @@ void __init u8500_map_io(void)
                iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
        else
                iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+
+       /* Read out the ASIC ID as early as we can */
+       get_db8500_asic_id();
 }
 
 /*
@@ -70,6 +138,20 @@ void __init u8500_map_io(void)
  */
 void __init u8500_init_devices(void)
 {
+       /* Display some ASIC boilerplate */
+       pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
+               db8500_id.process, db8500_id.revision);
+       if (cpu_is_u8500ed())
+               pr_info("DB8500: Early Drop (ED)\n");
+       else if (cpu_is_u8500v10())
+               pr_info("DB8500: version 1.0\n");
+       else if (cpu_is_u8500v11())
+               pr_info("DB8500: version 1.1\n");
+       else if (cpu_is_u8500v20())
+               pr_info("DB8500: version 2.0\n");
+       else
+               pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
+
        ux500_init_devices();
 
        if (cpu_is_u8500ed())
index f000218210c947ea406692ee1663ee7ac5395ab9..f07d0986409d2341771a39e1298538d466192f36 100644 (file)
@@ -30,8 +30,6 @@
 #define U8500_ICN_BASE         0x81000000
 
 #define U8500_BOOT_ROM_BASE    0x90000000
-/* ASIC ID is at 0xff4 offset within this region */
-#define U8500_ASIC_ID_BASE     0x9001F000
 
 #define U8500_PER6_BASE                0xa03c0000
 #define U8500_PER5_BASE                0xa03e0000
index 8656379a83093c475c9eaf3b40b8cabb051f771d..32e883a8f2a22af6f122a9d529a6d85541d70b64 100644 (file)
@@ -104,16 +104,35 @@ static inline bool cpu_is_u8500(void)
 #endif
 }
 
+#define CPUID_DB8500ED 0x410fc090
+#define CPUID_DB8500V1 0x411fc091
+#define CPUID_DB8500V2 0x412fc091
+
 static inline bool cpu_is_u8500ed(void)
 {
-       return cpu_is_u8500() && (read_cpuid_id() & 15) == 0;
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
 }
 
 static inline bool cpu_is_u8500v1(void)
 {
-       return cpu_is_u8500() && (read_cpuid_id() & 15) == 1;
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
+}
+
+static inline bool cpu_is_u8500v2(void)
+{
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
 }
 
+#ifdef CONFIG_UX500_SOC_DB8500
+bool cpu_is_u8500v10(void);
+bool cpu_is_u8500v11(void);
+bool cpu_is_u8500v20(void);
+#else
+static inline bool cpu_is_u8500v10(void) { return false; }
+static inline bool cpu_is_u8500v11(void) { return false; }
+static inline bool cpu_is_u8500v20(void) { return false; }
+#endif
+
 static inline bool cpu_is_u5500(void)
 {
 #ifdef CONFIG_UX500_SOC_DB5500
index e978dbd9e2109a042c5984ad3e64edc87ffd81a0..54bbe648bf583575d390866d6b405e58a899abec 100644 (file)
@@ -38,4 +38,11 @@ extern struct sys_timer ux500_timer;
        .type           = MT_DEVICE,            \
 }
 
+#define __MEM_DEV_DESC(x, sz)  {               \
+       .virtual        = IO_ADDRESS(x),        \
+       .pfn            = __phys_to_pfn(x),     \
+       .length         = sz,                   \
+       .type           = MT_MEMORY,            \
+}
+
 #endif /*  __ASM_ARCH_SETUP_H */