aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-12-08 00:37:59 -0500
committerLinus Walleij <linus.walleij@stericsson.com>2011-01-10 12:34:53 -0500
commitabf12d719a2c9e45f7f90c02a3a25107206ed57a (patch)
tree0aa9d9ecc7188b748eeda954b609dd74a8f5d24f
parent5dc55e0a39434ec8bec7978aef2dc00c91a530ba (diff)
ux500: dynamic SOC detection
Dynamically detect the DBx500 SOC an revision based on the ASIC ID. Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/Makefile3
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c12
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c91
-rw-r--r--arch/arm/mach-ux500/cpu.c4
-rw-r--r--arch/arm/mach-ux500/id.c107
-rw-r--r--arch/arm/mach-ux500/include/mach/hardware.h50
-rw-r--r--arch/arm/mach-ux500/include/mach/id.h80
-rw-r--r--arch/arm/mach-ux500/include/mach/setup.h1
8 files changed, 212 insertions, 136 deletions
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index fc2180d7308b..53ebb429e971 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -2,7 +2,8 @@
2# Makefile for the linux kernel, U8500 machine. 2# Makefile for the linux kernel, U8500 machine.
3# 3#
4 4
5obj-y := clock.o cpu.o devices.o devices-common.o 5obj-y := clock.o cpu.o devices.o devices-common.o \
6 id.o
6obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o 7obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
7obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o 8obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
8obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ 9obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 7b0ab8336f3f..af04e0891a78 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -21,9 +21,12 @@
21 21
22#include "devices-db5500.h" 22#include "devices-db5500.h"
23 23
24static struct map_desc u5500_io_desc[] __initdata = { 24static struct map_desc u5500_uart_io_desc[] __initdata = {
25 __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K), 25 __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
26 __IO_DEV_DESC(U5500_UART2_BASE, SZ_4K), 26 __IO_DEV_DESC(U5500_UART2_BASE, SZ_4K),
27};
28
29static struct map_desc u5500_io_desc[] __initdata = {
27 __IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K), 30 __IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K),
28 __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K), 31 __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K),
29 __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K), 32 __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K),
@@ -153,6 +156,13 @@ static void __init db5500_add_gpios(void)
153 156
154void __init u5500_map_io(void) 157void __init u5500_map_io(void)
155{ 158{
159 /*
160 * Map the UARTs early so that the DEBUG_LL stuff continues to work.
161 */
162 iotable_init(u5500_uart_io_desc, ARRAY_SIZE(u5500_uart_io_desc));
163
164 ux500_map_io();
165
156 iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); 166 iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
157} 167}
158 168
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 1b2b81c0f27c..1748fbc58530 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -29,9 +29,12 @@ static struct platform_device *platform_devs[] __initdata = {
29}; 29};
30 30
31/* minimum static i/o mapping required to boot U8500 platforms */ 31/* minimum static i/o mapping required to boot U8500 platforms */
32static struct map_desc u8500_io_desc[] __initdata = { 32static struct map_desc u8500_uart_io_desc[] __initdata = {
33 __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), 33 __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
34 __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), 34 __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
35};
36
37static struct map_desc u8500_io_desc[] __initdata = {
35 __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), 38 __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K),
36 __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), 39 __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
37 __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), 40 __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
@@ -51,7 +54,6 @@ static struct map_desc u8500_io_desc[] __initdata = {
51 __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), 54 __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
52 __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), 55 __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
53 __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), 56 __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
54 __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
55}; 57};
56 58
57static struct map_desc u8500_ed_io_desc[] __initdata = { 59static struct map_desc u8500_ed_io_desc[] __initdata = {
@@ -68,71 +70,15 @@ static struct map_desc u8500_v2_io_desc[] __initdata = {
68 __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), 70 __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
69}; 71};
70 72
71/* 73void __init u8500_map_io(void)
72 * Functions to differentiate between later ASICs
73 * We look into the end of the ROM to locate the hardcoded ASIC ID.
74 * This is only needed to differentiate between minor revisions and
75 * process variants of an ASIC, the major revisions are encoded in
76 * the cpuid.
77 */
78#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4)
79#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4)
80#define U8500_ASIC_REV_ED 0x01
81#define U8500_ASIC_REV_V10 0xA0
82#define U8500_ASIC_REV_V11 0xA1
83#define U8500_ASIC_REV_V20 0xB0
84
85/**
86 * struct db8500_asic_id - fields of the ASIC ID
87 * @process: the manufacturing process, 0x40 is 40 nm
88 * 0x00 is "standard"
89 * @partnumber: hithereto 0x8500 for DB8500
90 * @revision: version code in the series
91 * This field definion is not formally defined but makes
92 * sense.
93 */
94struct db8500_asic_id {
95 u8 process;
96 u16 partnumber;
97 u8 revision;
98};
99
100/* This isn't going to change at runtime */
101static struct db8500_asic_id db8500_id;
102
103static void __init get_db8500_asic_id(void)
104{
105 u32 asicid;
106
107 if (cpu_is_u8500v1() || cpu_is_u8500ed())
108 asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
109 else if (cpu_is_u8500v2())
110 asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
111 else
112 BUG();
113
114 db8500_id.process = (asicid >> 24);
115 db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
116 db8500_id.revision = asicid & 0xFFU;
117}
118
119bool cpu_is_u8500v10(void)
120{
121 return (db8500_id.revision == U8500_ASIC_REV_V10);
122}
123
124bool cpu_is_u8500v11(void)
125{ 74{
126 return (db8500_id.revision == U8500_ASIC_REV_V11); 75 /*
127} 76 * Map the UARTs early so that the DEBUG_LL stuff continues to work.
77 */
78 iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc));
128 79
129bool cpu_is_u8500v20(void) 80 ux500_map_io();
130{
131 return (db8500_id.revision == U8500_ASIC_REV_V20);
132}
133 81
134void __init u8500_map_io(void)
135{
136 iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); 82 iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
137 83
138 if (cpu_is_u8500ed()) 84 if (cpu_is_u8500ed())
@@ -141,9 +87,6 @@ void __init u8500_map_io(void)
141 iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); 87 iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc));
142 else if (cpu_is_u8500v2()) 88 else if (cpu_is_u8500v2())
143 iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); 89 iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
144
145 /* Read out the ASIC ID as early as we can */
146 get_db8500_asic_id();
147} 90}
148 91
149static resource_size_t __initdata db8500_gpio_base[] = { 92static resource_size_t __initdata db8500_gpio_base[] = {
@@ -173,20 +116,6 @@ static void __init db8500_add_gpios(void)
173 */ 116 */
174void __init u8500_init_devices(void) 117void __init u8500_init_devices(void)
175{ 118{
176 /* Display some ASIC boilerplate */
177 pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
178 db8500_id.process, db8500_id.revision);
179 if (cpu_is_u8500ed())
180 pr_info("DB8500: Early Drop (ED)\n");
181 else if (cpu_is_u8500v10())
182 pr_info("DB8500: version 1.0\n");
183 else if (cpu_is_u8500v11())
184 pr_info("DB8500: version 1.1\n");
185 else if (cpu_is_u8500v20())
186 pr_info("DB8500: version 2.0\n");
187 else
188 pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
189
190 if (cpu_is_u8500ed()) 119 if (cpu_is_u8500ed())
191 dma40_u8500ed_fixup(); 120 dma40_u8500ed_fixup();
192 121
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 35a3af13fb30..5a43107c6232 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -27,10 +27,6 @@
27static void __iomem *l2x0_base; 27static void __iomem *l2x0_base;
28#endif 28#endif
29 29
30void __init ux500_map_io(void)
31{
32}
33
34void __init ux500_init_irq(void) 30void __init ux500_init_irq(void)
35{ 31{
36 void __iomem *dist_base; 32 void __iomem *dist_base;
diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c
new file mode 100644
index 000000000000..d35122ebc67b
--- /dev/null
+++ b/arch/arm/mach-ux500/id.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/io.h>
11
12#include <asm/cputype.h>
13#include <asm/tlbflush.h>
14#include <asm/cacheflush.h>
15#include <asm/mach/map.h>
16
17#include <mach/hardware.h>
18#include <mach/setup.h>
19
20struct dbx500_asic_id dbx500_id;
21
22static unsigned int ux500_read_asicid(phys_addr_t addr)
23{
24 phys_addr_t base = addr & ~0xfff;
25 struct map_desc desc = {
26 .virtual = IO_ADDRESS(base),
27 .pfn = __phys_to_pfn(base),
28 .length = SZ_16K,
29 .type = MT_DEVICE,
30 };
31
32 iotable_init(&desc, 1);
33
34 /* As in devicemaps_init() */
35 local_flush_tlb_all();
36 flush_cache_all();
37
38 return readl(__io_address(addr));
39}
40
41static void ux500_print_soc_info(unsigned int asicid)
42{
43 unsigned int rev = dbx500_revision();
44
45 pr_info("DB%4x ", dbx500_partnumber());
46
47 if (rev == 0x01)
48 pr_cont("Early Drop");
49 else if (rev >= 0xA0)
50 pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf);
51 else
52 pr_cont("Unknown");
53
54 pr_cont(" [%#010x]\n", asicid);
55}
56
57static unsigned int partnumber(unsigned int asicid)
58{
59 return (asicid >> 8) & 0xffff;
60}
61
62/*
63 * SOC MIDR ASICID ADDRESS ASICID VALUE
64 * DB8500ed 0x410fc090 0x9001FFF4 0x00850001
65 * DB8500v1 0x411fc091 0x9001FFF4 0x008500A0
66 * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1
67 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0
68 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0
69 */
70
71void __init ux500_map_io(void)
72{
73 unsigned int cpuid = read_cpuid_id();
74 unsigned int asicid = 0;
75 phys_addr_t addr = 0;
76
77 switch (cpuid) {
78 case 0x410fc090: /* DB8500ed */
79 case 0x411fc091: /* DB8500v1 */
80 addr = 0x9001FFF4;
81 break;
82
83 case 0x412fc091: /* DB8500v2 / DB5500v1 */
84 asicid = ux500_read_asicid(0x9001DBF4);
85 if (partnumber(asicid) == 0x8500)
86 /* DB8500v2 */
87 break;
88
89 /* DB5500v1 */
90 addr = 0x9001FFF4;
91 break;
92 }
93
94 if (addr)
95 asicid = ux500_read_asicid(addr);
96
97 if (!asicid) {
98 pr_err("Unable to identify SoC\n");
99 ux500_unknown_soc();
100 }
101
102 dbx500_id.process = asicid >> 24;
103 dbx500_id.partnumber = partnumber(asicid);
104 dbx500_id.revision = asicid & 0xff;
105
106 ux500_print_soc_info(asicid);
107}
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index bced4a8e16ef..bf63f2631ba0 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -34,57 +34,9 @@
34 34
35#ifndef __ASSEMBLY__ 35#ifndef __ASSEMBLY__
36 36
37#include <asm/cputype.h> 37#include <mach/id.h>
38
39static inline bool cpu_is_u8500(void)
40{
41#ifdef CONFIG_UX500_SOC_DB8500
42 return 1;
43#else
44 return 0;
45#endif
46}
47
48#define CPUID_DB8500ED 0x410fc090
49#define CPUID_DB8500V1 0x411fc091
50#define CPUID_DB8500V2 0x412fc091
51
52static inline bool cpu_is_u8500ed(void)
53{
54 return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
55}
56
57static inline bool cpu_is_u8500v1(void)
58{
59 return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
60}
61
62static inline bool cpu_is_u8500v2(void)
63{
64 return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
65}
66
67#ifdef CONFIG_UX500_SOC_DB8500
68bool cpu_is_u8500v10(void);
69bool cpu_is_u8500v11(void);
70bool cpu_is_u8500v20(void);
71#else
72static inline bool cpu_is_u8500v10(void) { return false; }
73static inline bool cpu_is_u8500v11(void) { return false; }
74static inline bool cpu_is_u8500v20(void) { return false; }
75#endif
76
77static inline bool cpu_is_u5500(void)
78{
79#ifdef CONFIG_UX500_SOC_DB5500
80 return 1;
81#else
82 return 0;
83#endif
84}
85 38
86#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) 39#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
87#define ux500_unknown_soc() BUG()
88 40
89#endif 41#endif
90 42
diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h
new file mode 100644
index 000000000000..f1288d10b6ab
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/id.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#ifndef __MACH_UX500_ID
9#define __MACH_UX500_ID
10
11/**
12 * struct dbx500_asic_id - fields of the ASIC ID
13 * @process: the manufacturing process, 0x40 is 40 nm 0x00 is "standard"
14 * @partnumber: hithereto 0x8500 for DB8500
15 * @revision: version code in the series
16 */
17struct dbx500_asic_id {
18 u16 partnumber;
19 u8 revision;
20 u8 process;
21};
22
23extern struct dbx500_asic_id dbx500_id;
24
25static inline unsigned int __attribute_const__ dbx500_partnumber(void)
26{
27 return dbx500_id.partnumber;
28}
29
30static inline unsigned int __attribute_const__ dbx500_revision(void)
31{
32 return dbx500_id.revision;
33}
34
35/*
36 * SOCs
37 */
38
39static inline bool __attribute_const__ cpu_is_u8500(void)
40{
41 return dbx500_partnumber() == 0x8500;
42}
43
44static inline bool __attribute_const__ cpu_is_u5500(void)
45{
46 return dbx500_partnumber() == 0x5500;
47}
48
49/*
50 * 8500 revisions
51 */
52
53static inline bool __attribute_const__ cpu_is_u8500ed(void)
54{
55 return cpu_is_u8500() && dbx500_revision() == 0x00;
56}
57
58static inline bool __attribute_const__ cpu_is_u8500v1(void)
59{
60 return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0;
61}
62
63static inline bool __attribute_const__ cpu_is_u8500v10(void)
64{
65 return cpu_is_u8500() && dbx500_revision() == 0xA0;
66}
67
68static inline bool __attribute_const__ cpu_is_u8500v11(void)
69{
70 return cpu_is_u8500() && dbx500_revision() == 0xA1;
71}
72
73static inline bool __attribute_const__ cpu_is_u8500v2(void)
74{
75 return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0);
76}
77
78#define ux500_unknown_soc() BUG()
79
80#endif
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 5d8423294d41..a7d363fdb4cd 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -14,6 +14,7 @@
14#include <asm/mach/time.h> 14#include <asm/mach/time.h>
15#include <linux/init.h> 15#include <linux/init.h>
16 16
17void __init ux500_map_io(void);
17extern void __init u5500_map_io(void); 18extern void __init u5500_map_io(void);
18extern void __init u8500_map_io(void); 19extern void __init u8500_map_io(void);
19 20