aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-01-23 05:54:44 -0500
committerLinus Walleij <linus.walleij@linaro.org>2012-05-01 18:25:13 -0400
commitbc71c0961c61d6082472203bfae9596899c9c896 (patch)
tree8a29af932f2acdb8249b1aedb12f7d48d14cf51b
parent66f75a5d028beaf67c931435fdc3e7823125730c (diff)
ARM: ux500: core U9540 support
This adds support for the U9540 variant of the U8500 series. This is an application processor without internal modem. This is the most basic part with ASIC ID, CPU-related fixes, IRQ list, register ranges, timer, UART, and L2 cache setup. This is based on a patch by Michel Jaouen which was rewritten to fit with the latest 3.3 kernel. ChangeLog v1->v2: deleted the irqs-db9540.h file since we expect to migrate to using Device Tree for getting the IRQs to devices. ChangeLog v2->v3: introduced a fixed virtual offset for the ROM as suggested by Arnd Bergmann. Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Sebastien Pasdeloup <sebastien.pasdeloup-nonst@stericsson.com> Signed-off-by: Michel Jaouen <michel.jaouen@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c2
-rw-r--r--arch/arm/mach-ux500/cache-l2x0.c16
-rw-r--r--arch/arm/mach-ux500/clock.c2
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c6
-rw-r--r--arch/arm/mach-ux500/cpu.c4
-rw-r--r--arch/arm/mach-ux500/id.c9
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h6
-rw-r--r--arch/arm/mach-ux500/include/mach/hardware.h3
-rw-r--r--arch/arm/mach-ux500/include/mach/id.h17
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-ux500/platsmp.c4
-rw-r--r--arch/arm/mach-ux500/timer.c2
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c2
13 files changed, 57 insertions, 18 deletions
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
index 5af36aa56c08..b29a788f498c 100644
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -102,7 +102,7 @@ static int __init mop500_uib_init(void)
102 struct i2c_adapter *i2c0; 102 struct i2c_adapter *i2c0;
103 int ret; 103 int ret;
104 104
105 if (!cpu_is_u8500()) 105 if (!cpu_is_u8500_family())
106 return -ENODEV; 106 return -ENODEV;
107 107
108 if (uib) { 108 if (uib) {
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 77a75ed0df67..677bb7683c71 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -36,9 +36,11 @@ static int __init ux500_l2x0_unlock(void)
36 36
37static int __init ux500_l2x0_init(void) 37static int __init ux500_l2x0_init(void)
38{ 38{
39 u32 aux_val = 0x3e000000;
40
39 if (cpu_is_u5500()) 41 if (cpu_is_u5500())
40 l2x0_base = __io_address(U5500_L2CC_BASE); 42 l2x0_base = __io_address(U5500_L2CC_BASE);
41 else if (cpu_is_u8500()) 43 else if (cpu_is_u8500_family())
42 l2x0_base = __io_address(U8500_L2CC_BASE); 44 l2x0_base = __io_address(U8500_L2CC_BASE);
43 else 45 else
44 ux500_unknown_soc(); 46 ux500_unknown_soc();
@@ -46,11 +48,19 @@ static int __init ux500_l2x0_init(void)
46 /* Unlock before init */ 48 /* Unlock before init */
47 ux500_l2x0_unlock(); 49 ux500_l2x0_unlock();
48 50
51 /* DB9540's L2 has 128KB way size */
52 if (cpu_is_u9540())
53 /* 128KB way size */
54 aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
55 else
56 /* 64KB way size */
57 aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
58
49 /* 64KB way size, 8 way associativity, force WA */ 59 /* 64KB way size, 8 way associativity, force WA */
50 if (of_have_populated_dt()) 60 if (of_have_populated_dt())
51 l2x0_of_init(0x3e060000, 0xc0000fff); 61 l2x0_of_init(aux_val, 0xc0000fff);
52 else 62 else
53 l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); 63 l2x0_init(l2x0_base, aux_val, 0xc0000fff);
54 64
55 /* 65 /*
56 * We can't disable l2 as we are in non secure mode, currently 66 * We can't disable l2 as we are in non secure mode, currently
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index ec35f0aa5665..cc87f7788ff5 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -151,7 +151,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk)
151 151
152 if (cpu_is_u5500()) 152 if (cpu_is_u5500())
153 addr = __io_address(U5500_PRCMU_BASE); 153 addr = __io_address(U5500_PRCMU_BASE);
154 else if (cpu_is_u8500()) 154 else if (cpu_is_u8500_family())
155 addr = __io_address(U8500_PRCMU_BASE); 155 addr = __io_address(U8500_PRCMU_BASE);
156 else 156 else
157 ux500_unknown_soc(); 157 ux500_unknown_soc();
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 9bd8163896cf..0bdcdd96fdc8 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -34,8 +34,8 @@ static struct map_desc u8500_uart_io_desc[] __initdata = {
34 __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), 34 __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
35 __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), 35 __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
36}; 36};
37 37/* U8500 and U9540 common io_desc */
38static struct map_desc u8500_io_desc[] __initdata = { 38static struct map_desc u8500_common_io_desc[] __initdata = {
39 /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ 39 /* SCU base also covers GIC CPU BASE and TWD with its 4K page */
40 __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), 40 __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
41 __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), 41 __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
@@ -66,7 +66,7 @@ void __init u8500_map_io(void)
66 66
67 ux500_map_io(); 67 ux500_map_io();
68 68
69 iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); 69 iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc));
70 70
71 _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); 71 _PRCMU_BASE = __io_address(U8500_PRCMU_BASE);
72} 72}
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index d11f3892a27d..857e48167526 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -43,7 +43,7 @@ void __init ux500_init_irq(void)
43 if (cpu_is_u5500()) { 43 if (cpu_is_u5500()) {
44 dist_base = __io_address(U5500_GIC_DIST_BASE); 44 dist_base = __io_address(U5500_GIC_DIST_BASE);
45 cpu_base = __io_address(U5500_GIC_CPU_BASE); 45 cpu_base = __io_address(U5500_GIC_CPU_BASE);
46 } else if (cpu_is_u8500()) { 46 } else if (cpu_is_u8500_family()) {
47 dist_base = __io_address(U8500_GIC_DIST_BASE); 47 dist_base = __io_address(U8500_GIC_DIST_BASE);
48 cpu_base = __io_address(U8500_GIC_CPU_BASE); 48 cpu_base = __io_address(U8500_GIC_CPU_BASE);
49 } else 49 } else
@@ -62,7 +62,7 @@ void __init ux500_init_irq(void)
62 */ 62 */
63 if (cpu_is_u5500()) 63 if (cpu_is_u5500())
64 db5500_prcmu_early_init(); 64 db5500_prcmu_early_init();
65 if (cpu_is_u8500()) 65 if (cpu_is_u8500_family())
66 db8500_prcmu_early_init(); 66 db8500_prcmu_early_init();
67 clk_init(); 67 clk_init();
68} 68}
diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c
index 15a0f63b2e2b..d1579920139f 100644
--- a/arch/arm/mach-ux500/id.c
+++ b/arch/arm/mach-ux500/id.c
@@ -23,7 +23,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr)
23{ 23{
24 phys_addr_t base = addr & ~0xfff; 24 phys_addr_t base = addr & ~0xfff;
25 struct map_desc desc = { 25 struct map_desc desc = {
26 .virtual = IO_ADDRESS(base), 26 .virtual = UX500_VIRT_ROM,
27 .pfn = __phys_to_pfn(base), 27 .pfn = __phys_to_pfn(base),
28 .length = SZ_16K, 28 .length = SZ_16K,
29 .type = MT_DEVICE, 29 .type = MT_DEVICE,
@@ -35,7 +35,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr)
35 local_flush_tlb_all(); 35 local_flush_tlb_all();
36 flush_cache_all(); 36 flush_cache_all();
37 37
38 return readl(__io_address(addr)); 38 return readl(IOMEM(UX500_VIRT_ROM + (addr & 0xfff)));
39} 39}
40 40
41static void ux500_print_soc_info(unsigned int asicid) 41static void ux500_print_soc_info(unsigned int asicid)
@@ -67,6 +67,7 @@ static unsigned int partnumber(unsigned int asicid)
67 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 67 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0
68 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 68 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2
69 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 69 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0
70 * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx
70 */ 71 */
71 72
72void __init ux500_map_io(void) 73void __init ux500_map_io(void)
@@ -91,6 +92,10 @@ void __init ux500_map_io(void)
91 /* DB5500v1 */ 92 /* DB5500v1 */
92 addr = 0x9001FFF4; 93 addr = 0x9001FFF4;
93 break; 94 break;
95
96 case 0x413fc090: /* DB9540 */
97 addr = 0xFFFFDBF4;
98 break;
94 } 99 }
95 100
96 if (addr) 101 if (addr)
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 9ec20b96d8f2..1530d493879d 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -41,6 +41,10 @@
41/* ASIC ID is at 0xbf4 offset within this region */ 41/* ASIC ID is at 0xbf4 offset within this region */
42#define U8500_ASIC_ID_BASE 0x9001D000 42#define U8500_ASIC_ID_BASE 0x9001D000
43 43
44#define U9540_BOOT_ROM_BASE 0xFFFE0000
45/* ASIC ID is at 0xbf4 offset within this region */
46#define U9540_ASIC_ID_BASE 0xFFFFD000
47
44#define U8500_PER6_BASE 0xa03c0000 48#define U8500_PER6_BASE 0xa03c0000
45#define U8500_PER7_BASE 0xa03d0000 49#define U8500_PER7_BASE 0xa03d0000
46#define U8500_PER5_BASE 0xa03e0000 50#define U8500_PER5_BASE 0xa03e0000
@@ -96,7 +100,9 @@
96#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) 100#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
97#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) 101#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
98#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) 102#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
103#define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000)
99#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) 104#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
105#define U9540_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x6A000)
100#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) 106#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
101#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338) 107#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
102#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450) 108#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index f84698936d36..836165778a2d 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -17,6 +17,8 @@
17 */ 17 */
18#define U8500_IO_VIRTUAL 0xf0000000 18#define U8500_IO_VIRTUAL 0xf0000000
19#define U8500_IO_PHYSICAL 0xa0000000 19#define U8500_IO_PHYSICAL 0xa0000000
20/* This is where we map in the ROM to check ASIC IDs */
21#define UX500_VIRT_ROM 0xf0000000
20 22
21/* This macro is used in assembly, so no cast */ 23/* This macro is used in assembly, so no cast */
22#define IO_ADDRESS(x) \ 24#define IO_ADDRESS(x) \
@@ -24,6 +26,7 @@
24 26
25/* typesafe io address */ 27/* typesafe io address */
26#define __io_address(n) IOMEM(IO_ADDRESS(n)) 28#define __io_address(n) IOMEM(IO_ADDRESS(n))
29
27/* Used by some plat-nomadik code */ 30/* Used by some plat-nomadik code */
28#define io_p2v(n) __io_address(n) 31#define io_p2v(n) __io_address(n)
29 32
diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h
index 833d6a6edc9b..c6e2db9e9e51 100644
--- a/arch/arm/mach-ux500/include/mach/id.h
+++ b/arch/arm/mach-ux500/include/mach/id.h
@@ -41,6 +41,16 @@ static inline bool __attribute_const__ cpu_is_u8500(void)
41 return dbx500_partnumber() == 0x8500; 41 return dbx500_partnumber() == 0x8500;
42} 42}
43 43
44static inline bool __attribute_const__ cpu_is_u9540(void)
45{
46 return dbx500_partnumber() == 0x9540;
47}
48
49static inline bool cpu_is_u8500_family(void)
50{
51 return cpu_is_u8500() || cpu_is_u9540();
52}
53
44static inline bool __attribute_const__ cpu_is_u5500(void) 54static inline bool __attribute_const__ cpu_is_u5500(void)
45{ 55{
46 return dbx500_partnumber() == 0x5500; 56 return dbx500_partnumber() == 0x5500;
@@ -111,7 +121,12 @@ static inline bool cpu_is_u8500v21(void)
111 121
112static inline bool cpu_is_u8500v20_or_later(void) 122static inline bool cpu_is_u8500v20_or_later(void)
113{ 123{
114 return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); 124 /*
125 * U9540 has so much in common with U8500 that is is considered a
126 * U8500 variant.
127 */
128 return cpu_is_u9540() ||
129 (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11());
115} 130}
116 131
117static inline bool ux500_is_svp(void) 132static inline bool ux500_is_svp(void)
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index c23a6b5f0c4e..7da9ec58a531 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -24,7 +24,7 @@
24 */ 24 */
25#define IRQ_MTU0 (IRQ_SHPI_START + 4) 25#define IRQ_MTU0 (IRQ_SHPI_START + 4)
26 26
27#define DBX500_NR_INTERNAL_IRQS 160 27#define DBX500_NR_INTERNAL_IRQS 166
28 28
29/* After chip-specific IRQ numbers we have the GPIO ones */ 29/* After chip-specific IRQ numbers we have the GPIO ones */
30#define NOMADIK_NR_GPIO 288 30#define NOMADIK_NR_GPIO 288
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index eff5842f6232..f499a0703928 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -50,7 +50,7 @@ static void __iomem *scu_base_addr(void)
50{ 50{
51 if (cpu_is_u5500()) 51 if (cpu_is_u5500())
52 return __io_address(U5500_SCU_BASE); 52 return __io_address(U5500_SCU_BASE);
53 else if (cpu_is_u8500()) 53 else if (cpu_is_u8500_family())
54 return __io_address(U8500_SCU_BASE); 54 return __io_address(U8500_SCU_BASE);
55 else 55 else
56 ux500_unknown_soc(); 56 ux500_unknown_soc();
@@ -122,7 +122,7 @@ static void __init wakeup_secondary(void)
122 122
123 if (cpu_is_u5500()) 123 if (cpu_is_u5500())
124 backupram = __io_address(U5500_BACKUPRAM0_BASE); 124 backupram = __io_address(U5500_BACKUPRAM0_BASE);
125 else if (cpu_is_u8500()) 125 else if (cpu_is_u8500_family())
126 backupram = __io_address(U8500_BACKUPRAM0_BASE); 126 backupram = __io_address(U8500_BACKUPRAM0_BASE);
127 else 127 else
128 ux500_unknown_soc(); 128 ux500_unknown_soc();
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index d37df98b5c32..3bfbfdf833c6 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -51,7 +51,7 @@ static void __init ux500_timer_init(void)
51 if (cpu_is_u5500()) { 51 if (cpu_is_u5500()) {
52 mtu_timer_base = __io_address(U5500_MTU0_BASE); 52 mtu_timer_base = __io_address(U5500_MTU0_BASE);
53 prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE); 53 prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
54 } else if (cpu_is_u8500()) { 54 } else if (cpu_is_u8500_family()) {
55 mtu_timer_base = __io_address(U8500_MTU0_BASE); 55 mtu_timer_base = __io_address(U8500_MTU0_BASE);
56 prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); 56 prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
57 } else { 57 } else {
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 0bf1b8910eeb..74b830b635a6 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -161,7 +161,7 @@ static struct cpufreq_driver db8500_cpufreq_driver = {
161 161
162static int __init db8500_cpufreq_register(void) 162static int __init db8500_cpufreq_register(void)
163{ 163{
164 if (!cpu_is_u8500v20_or_later()) 164 if (!cpu_is_u8500_family())
165 return -ENODEV; 165 return -ENODEV;
166 166
167 pr_info("cpufreq for DB8500 started\n"); 167 pr_info("cpufreq for DB8500 started\n");