aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2016-08-10 07:00:48 -0400
committerMasahiro Yamada <yamada.masahiro@socionext.com>2016-08-28 12:57:14 -0400
commitdd34b115666a1ccc69e3af52cc92c7410490f4fd (patch)
tree1a3d4af8a9fd3bafe7626d83b5753f478ea70234
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
ARM: uniphier: remove SoC-specific SMP code
The UniPhier architecture (32bit) switched over to PSCI. Remove the SoC-specific SMP operations. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
-rw-r--r--arch/arm/include/asm/hardware/cache-uniphier.h20
-rw-r--r--arch/arm/mach-uniphier/Makefile2
-rw-r--r--arch/arm/mach-uniphier/headsmp.S43
-rw-r--r--arch/arm/mach-uniphier/platsmp.c209
-rw-r--r--arch/arm/mm/cache-uniphier.c63
5 files changed, 6 insertions, 331 deletions
diff --git a/arch/arm/include/asm/hardware/cache-uniphier.h b/arch/arm/include/asm/hardware/cache-uniphier.h
index 102e3fbe1e10..eaa60da7dac3 100644
--- a/arch/arm/include/asm/hardware/cache-uniphier.h
+++ b/arch/arm/include/asm/hardware/cache-uniphier.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 2 * Copyright (C) 2015-2016 Socionext Inc.
3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -19,28 +20,11 @@
19 20
20#ifdef CONFIG_CACHE_UNIPHIER 21#ifdef CONFIG_CACHE_UNIPHIER
21int uniphier_cache_init(void); 22int uniphier_cache_init(void);
22int uniphier_cache_l2_is_enabled(void);
23void uniphier_cache_l2_touch_range(unsigned long start, unsigned long end);
24void uniphier_cache_l2_set_locked_ways(u32 way_mask);
25#else 23#else
26static inline int uniphier_cache_init(void) 24static inline int uniphier_cache_init(void)
27{ 25{
28 return -ENODEV; 26 return -ENODEV;
29} 27}
30
31static inline int uniphier_cache_l2_is_enabled(void)
32{
33 return 0;
34}
35
36static inline void uniphier_cache_l2_touch_range(unsigned long start,
37 unsigned long end)
38{
39}
40
41static inline void uniphier_cache_l2_set_locked_ways(u32 way_mask)
42{
43}
44#endif 28#endif
45 29
46#endif /* __CACHE_UNIPHIER_H */ 30#endif /* __CACHE_UNIPHIER_H */
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile
index 396afe109e67..6bea3d3a2dd7 100644
--- a/arch/arm/mach-uniphier/Makefile
+++ b/arch/arm/mach-uniphier/Makefile
@@ -1 +1 @@
obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj- += dummy.o
diff --git a/arch/arm/mach-uniphier/headsmp.S b/arch/arm/mach-uniphier/headsmp.S
deleted file mode 100644
index c819dff84546..000000000000
--- a/arch/arm/mach-uniphier/headsmp.S
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/linkage.h>
16#include <asm/assembler.h>
17#include <asm/cp15.h>
18
19ENTRY(uniphier_smp_trampoline)
20ARM_BE8(setend be) @ ensure we are in BE8 mode
21 mrc p15, 0, r0, c0, c0, 5 @ MPIDR (Multiprocessor Affinity Reg)
22 and r2, r0, #0x3 @ CPU ID
23 ldr r1, uniphier_smp_trampoline_jump
24 ldr r3, uniphier_smp_trampoline_poll_addr
25 mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register)
26 orr r0, r0, #CR_I @ Enable ICache
27 bic r0, r0, #(CR_C | CR_M) @ Disable MMU and Dcache
28 mcr p15, 0, r0, c1, c0, 0
29 b 1f @ cache the following 5 instructions
300: wfe
311: ldr r0, [r3]
32 cmp r0, r2
33 bxeq r1 @ branch to secondary_startup
34 b 0b
35 .globl uniphier_smp_trampoline_jump
36uniphier_smp_trampoline_jump:
37 .word 0 @ set virt_to_phys(secondary_startup)
38 .globl uniphier_smp_trampoline_poll_addr
39uniphier_smp_trampoline_poll_addr:
40 .word 0 @ set CPU ID to be kicked to this reg
41 .globl uniphier_smp_trampoline_end
42uniphier_smp_trampoline_end:
43ENDPROC(uniphier_smp_trampoline)
diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c
deleted file mode 100644
index 9978c41128f6..000000000000
--- a/arch/arm/mach-uniphier/platsmp.c
+++ /dev/null
@@ -1,209 +0,0 @@
1/*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#define pr_fmt(fmt) "uniphier: " fmt
16
17#include <linux/init.h>
18#include <linux/io.h>
19#include <linux/ioport.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/sizes.h>
23#include <asm/cacheflush.h>
24#include <asm/hardware/cache-uniphier.h>
25#include <asm/pgtable.h>
26#include <asm/smp.h>
27#include <asm/smp_scu.h>
28
29/*
30 * The secondary CPUs check this register from the boot ROM for the jump
31 * destination. After that, it can be reused as a scratch register.
32 */
33#define UNIPHIER_SMPCTRL_ROM_RSV2 0x208
34
35static void __iomem *uniphier_smp_rom_boot_rsv2;
36static unsigned int uniphier_smp_max_cpus;
37
38extern char uniphier_smp_trampoline;
39extern char uniphier_smp_trampoline_jump;
40extern char uniphier_smp_trampoline_poll_addr;
41extern char uniphier_smp_trampoline_end;
42
43/*
44 * Copy trampoline code to the tail of the 1st section of the page table used
45 * in the boot ROM. This area is directly accessible by the secondary CPUs
46 * for all the UniPhier SoCs.
47 */
48static const phys_addr_t uniphier_smp_trampoline_dest_end = SECTION_SIZE;
49static phys_addr_t uniphier_smp_trampoline_dest;
50
51static int __init uniphier_smp_copy_trampoline(phys_addr_t poll_addr)
52{
53 size_t trmp_size;
54 static void __iomem *trmp_base;
55
56 if (!uniphier_cache_l2_is_enabled()) {
57 pr_warn("outer cache is needed for SMP, but not enabled\n");
58 return -ENODEV;
59 }
60
61 uniphier_cache_l2_set_locked_ways(1);
62
63 outer_flush_all();
64
65 trmp_size = &uniphier_smp_trampoline_end - &uniphier_smp_trampoline;
66 uniphier_smp_trampoline_dest = uniphier_smp_trampoline_dest_end -
67 trmp_size;
68
69 uniphier_cache_l2_touch_range(uniphier_smp_trampoline_dest,
70 uniphier_smp_trampoline_dest_end);
71
72 trmp_base = ioremap_cache(uniphier_smp_trampoline_dest, trmp_size);
73 if (!trmp_base) {
74 pr_err("failed to map trampoline destination area\n");
75 return -ENOMEM;
76 }
77
78 memcpy(trmp_base, &uniphier_smp_trampoline, trmp_size);
79
80 writel(virt_to_phys(secondary_startup),
81 trmp_base + (&uniphier_smp_trampoline_jump -
82 &uniphier_smp_trampoline));
83
84 writel(poll_addr, trmp_base + (&uniphier_smp_trampoline_poll_addr -
85 &uniphier_smp_trampoline));
86
87 flush_cache_all(); /* flush out trampoline code to outer cache */
88
89 iounmap(trmp_base);
90
91 return 0;
92}
93
94static int __init uniphier_smp_prepare_trampoline(unsigned int max_cpus)
95{
96 struct device_node *np;
97 struct resource res;
98 phys_addr_t rom_rsv2_phys;
99 int ret;
100
101 np = of_find_compatible_node(NULL, NULL, "socionext,uniphier-smpctrl");
102 ret = of_address_to_resource(np, 0, &res);
103 of_node_put(np);
104 if (ret) {
105 pr_err("failed to get resource of SMP control\n");
106 return ret;
107 }
108
109 rom_rsv2_phys = res.start + UNIPHIER_SMPCTRL_ROM_RSV2;
110
111 ret = uniphier_smp_copy_trampoline(rom_rsv2_phys);
112 if (ret)
113 return ret;
114
115 uniphier_smp_rom_boot_rsv2 = ioremap(rom_rsv2_phys, SZ_4);
116 if (!uniphier_smp_rom_boot_rsv2) {
117 pr_err("failed to map ROM_BOOT_RSV2 register\n");
118 return -ENOMEM;
119 }
120
121 writel(uniphier_smp_trampoline_dest, uniphier_smp_rom_boot_rsv2);
122 asm("sev"); /* Bring up all secondary CPUs to the trampoline code */
123
124 uniphier_smp_max_cpus = max_cpus; /* save for later use */
125
126 return 0;
127}
128
129static void __init uniphier_smp_unprepare_trampoline(void)
130{
131 iounmap(uniphier_smp_rom_boot_rsv2);
132
133 if (uniphier_smp_trampoline_dest)
134 outer_inv_range(uniphier_smp_trampoline_dest,
135 uniphier_smp_trampoline_dest_end);
136
137 uniphier_cache_l2_set_locked_ways(0);
138}
139
140static int __init uniphier_smp_enable_scu(void)
141{
142 unsigned long scu_base_phys = 0;
143 void __iomem *scu_base;
144
145 if (scu_a9_has_base())
146 scu_base_phys = scu_a9_get_base();
147
148 if (!scu_base_phys) {
149 pr_err("failed to get scu base\n");
150 return -ENODEV;
151 }
152
153 scu_base = ioremap(scu_base_phys, SZ_128);
154 if (!scu_base) {
155 pr_err("failed to map scu base\n");
156 return -ENOMEM;
157 }
158
159 scu_enable(scu_base);
160 iounmap(scu_base);
161
162 return 0;
163}
164
165static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
166{
167 static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
168 int ret;
169
170 ret = uniphier_smp_prepare_trampoline(max_cpus);
171 if (ret)
172 goto err;
173
174 ret = uniphier_smp_enable_scu();
175 if (ret)
176 goto err;
177
178 return;
179err:
180 pr_warn("disabling SMP\n");
181 init_cpu_present(&only_cpu_0);
182 uniphier_smp_unprepare_trampoline();
183}
184
185static int __init uniphier_smp_boot_secondary(unsigned int cpu,
186 struct task_struct *idle)
187{
188 if (WARN_ON_ONCE(!uniphier_smp_rom_boot_rsv2))
189 return -EFAULT;
190
191 writel(cpu, uniphier_smp_rom_boot_rsv2);
192 readl(uniphier_smp_rom_boot_rsv2); /* relax */
193
194 asm("sev"); /* wake up secondary CPUs sleeping in the trampoline */
195
196 if (cpu == uniphier_smp_max_cpus - 1) {
197 /* clean up resources if this is the last CPU */
198 uniphier_smp_unprepare_trampoline();
199 }
200
201 return 0;
202}
203
204static const struct smp_operations uniphier_smp_ops __initconst = {
205 .smp_prepare_cpus = uniphier_smp_prepare_cpus,
206 .smp_boot_secondary = uniphier_smp_boot_secondary,
207};
208CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
209 &uniphier_smp_ops);
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
index c8e2f4947223..dfe97b409916 100644
--- a/arch/arm/mm/cache-uniphier.c
+++ b/arch/arm/mm/cache-uniphier.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 2 * Copyright (C) 2015-2016 Socionext Inc.
3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -43,27 +44,15 @@
43#define UNIPHIER_SSCOPE_CM_SYNC 0x8 /* sync (drain bufs) */ 44#define UNIPHIER_SSCOPE_CM_SYNC 0x8 /* sync (drain bufs) */
44#define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */ 45#define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */
45#define UNIPHIER_SSCOQM 0x248 /* Cache Operation Queue Mode */ 46#define UNIPHIER_SSCOQM 0x248 /* Cache Operation Queue Mode */
46#define UNIPHIER_SSCOQM_TID_MASK (0x3 << 21)
47#define UNIPHIER_SSCOQM_TID_LRU_DATA (0x0 << 21)
48#define UNIPHIER_SSCOQM_TID_LRU_INST (0x1 << 21)
49#define UNIPHIER_SSCOQM_TID_WAY (0x2 << 21)
50#define UNIPHIER_SSCOQM_S_MASK (0x3 << 17) 47#define UNIPHIER_SSCOQM_S_MASK (0x3 << 17)
51#define UNIPHIER_SSCOQM_S_RANGE (0x0 << 17) 48#define UNIPHIER_SSCOQM_S_RANGE (0x0 << 17)
52#define UNIPHIER_SSCOQM_S_ALL (0x1 << 17) 49#define UNIPHIER_SSCOQM_S_ALL (0x1 << 17)
53#define UNIPHIER_SSCOQM_S_WAY (0x2 << 17)
54#define UNIPHIER_SSCOQM_CE BIT(15) /* notify completion */ 50#define UNIPHIER_SSCOQM_CE BIT(15) /* notify completion */
55#define UNIPHIER_SSCOQM_CM_INV 0x0 /* invalidate */ 51#define UNIPHIER_SSCOQM_CM_INV 0x0 /* invalidate */
56#define UNIPHIER_SSCOQM_CM_CLEAN 0x1 /* clean */ 52#define UNIPHIER_SSCOQM_CM_CLEAN 0x1 /* clean */
57#define UNIPHIER_SSCOQM_CM_FLUSH 0x2 /* flush */ 53#define UNIPHIER_SSCOQM_CM_FLUSH 0x2 /* flush */
58#define UNIPHIER_SSCOQM_CM_PREFETCH 0x3 /* prefetch to cache */
59#define UNIPHIER_SSCOQM_CM_PREFETCH_BUF 0x4 /* prefetch to pf-buf */
60#define UNIPHIER_SSCOQM_CM_TOUCH 0x5 /* touch */
61#define UNIPHIER_SSCOQM_CM_TOUCH_ZERO 0x6 /* touch to zero */
62#define UNIPHIER_SSCOQM_CM_TOUCH_DIRTY 0x7 /* touch with dirty */
63#define UNIPHIER_SSCOQAD 0x24c /* Cache Operation Queue Address */ 54#define UNIPHIER_SSCOQAD 0x24c /* Cache Operation Queue Address */
64#define UNIPHIER_SSCOQSZ 0x250 /* Cache Operation Queue Size */ 55#define UNIPHIER_SSCOQSZ 0x250 /* Cache Operation Queue Size */
65#define UNIPHIER_SSCOQMASK 0x254 /* Cache Operation Queue Address Mask */
66#define UNIPHIER_SSCOQWN 0x258 /* Cache Operation Queue Way Number */
67#define UNIPHIER_SSCOPPQSEF 0x25c /* Cache Operation Queue Set Complete*/ 56#define UNIPHIER_SSCOPPQSEF 0x25c /* Cache Operation Queue Set Complete*/
68#define UNIPHIER_SSCOPPQSEF_FE BIT(1) 57#define UNIPHIER_SSCOPPQSEF_FE BIT(1)
69#define UNIPHIER_SSCOPPQSEF_OE BIT(0) 58#define UNIPHIER_SSCOPPQSEF_OE BIT(0)
@@ -72,9 +61,6 @@
72#define UNIPHIER_SSCOLPQS_EST BIT(1) 61#define UNIPHIER_SSCOLPQS_EST BIT(1)
73#define UNIPHIER_SSCOLPQS_QST BIT(0) 62#define UNIPHIER_SSCOLPQS_QST BIT(0)
74 63
75/* Is the touch/pre-fetch destination specified by ways? */
76#define UNIPHIER_SSCOQM_TID_IS_WAY(op) \
77 ((op & UNIPHIER_SSCOQM_TID_MASK) == UNIPHIER_SSCOQM_TID_WAY)
78/* Is the operation region specified by address range? */ 64/* Is the operation region specified by address range? */
79#define UNIPHIER_SSCOQM_S_IS_RANGE(op) \ 65#define UNIPHIER_SSCOQM_S_IS_RANGE(op) \
80 ((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE) 66 ((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
@@ -178,11 +164,6 @@ static void __uniphier_cache_maint_common(struct uniphier_cache_data *data,
178 writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD); 164 writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD);
179 writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ); 165 writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ);
180 } 166 }
181
182 /* set target ways if needed */
183 if (unlikely(UNIPHIER_SSCOQM_TID_IS_WAY(operation)))
184 writel_relaxed(data->way_locked_mask,
185 data->op_base + UNIPHIER_SSCOQWN);
186 } while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) & 167 } while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) &
187 (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE))); 168 (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)));
188 169
@@ -338,46 +319,8 @@ static void uniphier_cache_sync(void)
338 __uniphier_cache_sync(data); 319 __uniphier_cache_sync(data);
339} 320}
340 321
341int __init uniphier_cache_l2_is_enabled(void)
342{
343 struct uniphier_cache_data *data;
344
345 data = list_first_entry_or_null(&uniphier_cache_list,
346 struct uniphier_cache_data, list);
347 if (!data)
348 return 0;
349
350 return !!(readl_relaxed(data->ctrl_base + UNIPHIER_SSCC) &
351 UNIPHIER_SSCC_ON);
352}
353
354void __init uniphier_cache_l2_touch_range(unsigned long start,
355 unsigned long end)
356{
357 struct uniphier_cache_data *data;
358
359 data = list_first_entry_or_null(&uniphier_cache_list,
360 struct uniphier_cache_data, list);
361 if (data)
362 __uniphier_cache_maint_range(data, start, end,
363 UNIPHIER_SSCOQM_TID_WAY |
364 UNIPHIER_SSCOQM_CM_TOUCH);
365}
366
367void __init uniphier_cache_l2_set_locked_ways(u32 way_mask)
368{
369 struct uniphier_cache_data *data;
370
371 data = list_first_entry_or_null(&uniphier_cache_list,
372 struct uniphier_cache_data, list);
373 if (data)
374 __uniphier_cache_set_locked_ways(data, way_mask);
375}
376
377static const struct of_device_id uniphier_cache_match[] __initconst = { 322static const struct of_device_id uniphier_cache_match[] __initconst = {
378 { 323 { .compatible = "socionext,uniphier-system-cache" },
379 .compatible = "socionext,uniphier-system-cache",
380 },
381 { /* sentinel */ } 324 { /* sentinel */ }
382}; 325};
383 326