diff options
author | Pawel Moll <pawel.moll@arm.com> | 2013-09-17 13:30:58 -0400 |
---|---|---|
committer | Pawel Moll <pawel.moll@arm.com> | 2014-05-15 12:02:21 -0400 |
commit | d2606f81d5632f873884f1988fb2e9d3f057fcb6 (patch) | |
tree | e3f10081aad9c8beb7514c9176937f7d0f93d181 /arch/arm/mach-vexpress | |
parent | dcdea6295d3b2ec1aafd8480860f34062d2d3a93 (diff) |
ARM: vexpress: Simplify SMP operations for DT-powered system
As all cores must be properly described in the Device Tree,
there is no point in getting their numbers from SCU on
A5/A9 platforms. This significantly simplifies the code,
removing the need for flat-tree scanning and early static
mapping.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Diffstat (limited to 'arch/arm/mach-vexpress')
-rw-r--r-- | arch/arm/mach-vexpress/core.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/platsmp.c | 158 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 6 |
3 files changed, 41 insertions, 126 deletions
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index bde4374ab6d5..152fad91b3ae 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h | |||
@@ -4,10 +4,9 @@ | |||
4 | /* Tile's peripherals static mappings should start here */ | 4 | /* Tile's peripherals static mappings should start here */ |
5 | #define V2T_PERIPH 0xf8200000 | 5 | #define V2T_PERIPH 0xf8200000 |
6 | 6 | ||
7 | void vexpress_dt_smp_map_io(void); | ||
8 | |||
9 | bool vexpress_smp_init_ops(void); | 7 | bool vexpress_smp_init_ops(void); |
10 | 8 | ||
11 | extern struct smp_operations vexpress_smp_ops; | 9 | extern struct smp_operations vexpress_smp_ops; |
10 | extern struct smp_operations vexpress_smp_dt_ops; | ||
12 | 11 | ||
13 | extern void vexpress_cpu_die(unsigned int cpu); | 12 | extern void vexpress_cpu_die(unsigned int cpu); |
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 12a875182836..a1f3804fd5a5 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c | |||
@@ -12,8 +12,7 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of_address.h> |
16 | #include <linux/of_fdt.h> | ||
17 | #include <linux/vexpress.h> | 16 | #include <linux/vexpress.h> |
18 | 17 | ||
19 | #include <asm/mcpm.h> | 18 | #include <asm/mcpm.h> |
@@ -26,125 +25,13 @@ | |||
26 | 25 | ||
27 | #include "core.h" | 26 | #include "core.h" |
28 | 27 | ||
29 | #if defined(CONFIG_OF) | ||
30 | |||
31 | static enum { | ||
32 | GENERIC_SCU, | ||
33 | CORTEX_A9_SCU, | ||
34 | } vexpress_dt_scu __initdata = GENERIC_SCU; | ||
35 | |||
36 | static struct map_desc vexpress_dt_cortex_a9_scu_map __initdata = { | ||
37 | .virtual = V2T_PERIPH, | ||
38 | /* .pfn set in vexpress_dt_init_cortex_a9_scu() */ | ||
39 | .length = SZ_128, | ||
40 | .type = MT_DEVICE, | ||
41 | }; | ||
42 | |||
43 | static void *vexpress_dt_cortex_a9_scu_base __initdata; | ||
44 | |||
45 | const static char *vexpress_dt_cortex_a9_match[] __initconst = { | ||
46 | "arm,cortex-a5-scu", | ||
47 | "arm,cortex-a9-scu", | ||
48 | NULL | ||
49 | }; | ||
50 | |||
51 | static int __init vexpress_dt_find_scu(unsigned long node, | ||
52 | const char *uname, int depth, void *data) | ||
53 | { | ||
54 | if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) { | ||
55 | phys_addr_t phys_addr; | ||
56 | __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); | ||
57 | |||
58 | if (WARN_ON(!reg)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | phys_addr = be32_to_cpup(reg); | ||
62 | vexpress_dt_scu = CORTEX_A9_SCU; | ||
63 | |||
64 | vexpress_dt_cortex_a9_scu_map.pfn = __phys_to_pfn(phys_addr); | ||
65 | iotable_init(&vexpress_dt_cortex_a9_scu_map, 1); | ||
66 | vexpress_dt_cortex_a9_scu_base = ioremap(phys_addr, SZ_256); | ||
67 | if (WARN_ON(!vexpress_dt_cortex_a9_scu_base)) | ||
68 | return -EFAULT; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | void __init vexpress_dt_smp_map_io(void) | ||
75 | { | ||
76 | if (initial_boot_params) | ||
77 | WARN_ON(of_scan_flat_dt(vexpress_dt_find_scu, NULL)); | ||
78 | } | ||
79 | |||
80 | static void __init vexpress_dt_smp_init_cpus(void) | ||
81 | { | ||
82 | int ncores = 0, i; | ||
83 | |||
84 | switch (vexpress_dt_scu) { | ||
85 | case GENERIC_SCU: | ||
86 | return; | ||
87 | case CORTEX_A9_SCU: | ||
88 | ncores = scu_get_core_count(vexpress_dt_cortex_a9_scu_base); | ||
89 | break; | ||
90 | default: | ||
91 | WARN_ON(1); | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | if (ncores < 2) | ||
96 | return; | ||
97 | |||
98 | if (ncores > nr_cpu_ids) { | ||
99 | pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", | ||
100 | ncores, nr_cpu_ids); | ||
101 | ncores = nr_cpu_ids; | ||
102 | } | ||
103 | |||
104 | for (i = 0; i < ncores; ++i) | ||
105 | set_cpu_possible(i, true); | ||
106 | } | ||
107 | |||
108 | static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) | ||
109 | { | ||
110 | |||
111 | switch (vexpress_dt_scu) { | ||
112 | case GENERIC_SCU: | ||
113 | break; | ||
114 | case CORTEX_A9_SCU: | ||
115 | scu_enable(vexpress_dt_cortex_a9_scu_base); | ||
116 | break; | ||
117 | default: | ||
118 | WARN_ON(1); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | #else | ||
124 | |||
125 | static void __init vexpress_dt_smp_init_cpus(void) | ||
126 | { | ||
127 | WARN_ON(1); | ||
128 | } | ||
129 | |||
130 | void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) | ||
131 | { | ||
132 | WARN_ON(1); | ||
133 | } | ||
134 | |||
135 | #endif | ||
136 | |||
137 | /* | 28 | /* |
138 | * Initialise the CPU possible map early - this describes the CPUs | 29 | * Initialise the CPU possible map early - this describes the CPUs |
139 | * which may be present or become present in the system. | 30 | * which may be present or become present in the system. |
140 | */ | 31 | */ |
141 | static void __init vexpress_smp_init_cpus(void) | 32 | static void __init vexpress_smp_init_cpus(void) |
142 | { | 33 | { |
143 | if (ct_desc) | 34 | ct_desc->init_cpu_map(); |
144 | ct_desc->init_cpu_map(); | ||
145 | else | ||
146 | vexpress_dt_smp_init_cpus(); | ||
147 | |||
148 | } | 35 | } |
149 | 36 | ||
150 | static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) | 37 | static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) |
@@ -153,10 +40,7 @@ static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) | |||
153 | * Initialise the present map, which describes the set of CPUs | 40 | * Initialise the present map, which describes the set of CPUs |
154 | * actually populated at the present time. | 41 | * actually populated at the present time. |
155 | */ | 42 | */ |
156 | if (ct_desc) | 43 | ct_desc->smp_enable(max_cpus); |
157 | ct_desc->smp_enable(max_cpus); | ||
158 | else | ||
159 | vexpress_dt_smp_prepare_cpus(max_cpus); | ||
160 | 44 | ||
161 | /* | 45 | /* |
162 | * Write the address of secondary startup into the | 46 | * Write the address of secondary startup into the |
@@ -194,3 +78,39 @@ bool __init vexpress_smp_init_ops(void) | |||
194 | #endif | 78 | #endif |
195 | return false; | 79 | return false; |
196 | } | 80 | } |
81 | |||
82 | #if defined(CONFIG_OF) | ||
83 | |||
84 | static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = { | ||
85 | { .compatible = "arm,cortex-a5-scu", }, | ||
86 | { .compatible = "arm,cortex-a9-scu", }, | ||
87 | {} | ||
88 | }; | ||
89 | |||
90 | static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus) | ||
91 | { | ||
92 | struct device_node *scu = of_find_matching_node(NULL, | ||
93 | vexpress_smp_dt_scu_match); | ||
94 | |||
95 | if (scu) | ||
96 | scu_enable(of_iomap(scu, 0)); | ||
97 | |||
98 | /* | ||
99 | * Write the address of secondary startup into the | ||
100 | * system-wide flags register. The boot monitor waits | ||
101 | * until it receives a soft interrupt, and then the | ||
102 | * secondary CPU branches to this address. | ||
103 | */ | ||
104 | vexpress_flags_set(virt_to_phys(versatile_secondary_startup)); | ||
105 | } | ||
106 | |||
107 | struct smp_operations __initdata vexpress_smp_dt_ops = { | ||
108 | .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus, | ||
109 | .smp_secondary_init = versatile_secondary_init, | ||
110 | .smp_boot_secondary = versatile_boot_secondary, | ||
111 | #ifdef CONFIG_HOTPLUG_CPU | ||
112 | .cpu_die = vexpress_cpu_die, | ||
113 | #endif | ||
114 | }; | ||
115 | |||
116 | #endif | ||
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index d8a9fd7a695d..d8b419bcf3c3 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -400,10 +400,6 @@ void __init v2m_dt_map_io(void) | |||
400 | iotable_init(&v2m_rs1_io_desc, 1); | 400 | iotable_init(&v2m_rs1_io_desc, 1); |
401 | else | 401 | else |
402 | iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); | 402 | iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); |
403 | |||
404 | #if defined(CONFIG_SMP) | ||
405 | vexpress_dt_smp_map_io(); | ||
406 | #endif | ||
407 | } | 403 | } |
408 | 404 | ||
409 | void __init v2m_dt_init_early(void) | 405 | void __init v2m_dt_init_early(void) |
@@ -434,7 +430,7 @@ static const char * const v2m_dt_match[] __initconst = { | |||
434 | 430 | ||
435 | DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") | 431 | DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") |
436 | .dt_compat = v2m_dt_match, | 432 | .dt_compat = v2m_dt_match, |
437 | .smp = smp_ops(vexpress_smp_ops), | 433 | .smp = smp_ops(vexpress_smp_dt_ops), |
438 | .smp_init = smp_init_ops(vexpress_smp_init_ops), | 434 | .smp_init = smp_init_ops(vexpress_smp_init_ops), |
439 | .map_io = v2m_dt_map_io, | 435 | .map_io = v2m_dt_map_io, |
440 | .init_early = v2m_dt_init_early, | 436 | .init_early = v2m_dt_init_early, |