aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-sti
diff options
context:
space:
mode:
authorPeter Griffin <peter.griffin@linaro.org>2015-06-09 09:33:00 -0400
committerMaxime Coquelin <maxime.coquelin@st.com>2015-07-22 05:14:18 -0400
commit94a8cfceaa7ee7e7187c5de074eb5138a6b77dcf (patch)
tree2c6127ed6971955b775d8e5dc32ae8ba48aa2ecc /arch/arm/mach-sti
parentd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff)
ARM: STi: Add code to release secondary cores from holding pen.
Most upstream devs boot STi platform via JTAG which abuses the boot process by setting the PC of secondary cores directly. As a consquence, booting STi platforms via u-boot results in only the primary core being brought up as the code to manage the holding pen is not upstream. This patch adds the necessary code to bring the secondary cores out of the holding pen. It uses the cpu-release-addr DT property to get the address of the holding pen from the bootloader. With this patch booting upstream kernels via u-boot works correctly: [ 0.045456] CPU: Testing write buffer coherency: ok [ 0.045597] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.045734] Setting up static identity map for 0x40209000 - 0x40209098 [ 0.065047] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 [ 0.065081] Brought up 2 CPUs [ 0.065089] SMP: Total of 2 processors activated (5983.43 BogoMIPS). [ 0.065092] CPU: All CPU(s) started in SVC mode. Signed-off-by: Peter Griffin <peter.griffin@linaro.org> Acked-by: Maxime Coquelin <maxime.coquelin@st.com> Signed-off-by: Maxime Coquelin <maxime.coquelin@st.com>
Diffstat (limited to 'arch/arm/mach-sti')
-rw-r--r--arch/arm/mach-sti/headsmp.S1
-rw-r--r--arch/arm/mach-sti/platsmp.c55
-rw-r--r--arch/arm/mach-sti/smp.h2
3 files changed, 55 insertions, 3 deletions
diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S
index 4c09bae86edf..e0ad451700d5 100644
--- a/arch/arm/mach-sti/headsmp.S
+++ b/arch/arm/mach-sti/headsmp.S
@@ -37,6 +37,7 @@ pen: ldr r7, [r6]
37 * should now contain the SVC stack for this core 37 * should now contain the SVC stack for this core
38 */ 38 */
39 b secondary_startup 39 b secondary_startup
40ENDPROC(sti_secondary_startup)
40 41
411: .long . 421: .long .
42 .long pen_release 43 .long pen_release
diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c
index d4b624f8dfcb..86bb48d81ec1 100644
--- a/arch/arm/mach-sti/platsmp.c
+++ b/arch/arm/mach-sti/platsmp.c
@@ -20,6 +20,7 @@
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/memblock.h>
23 24
24#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
25#include <asm/smp_plat.h> 26#include <asm/smp_plat.h>
@@ -99,14 +100,62 @@ static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
99 100
100static void __init sti_smp_prepare_cpus(unsigned int max_cpus) 101static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
101{ 102{
102 void __iomem *scu_base = NULL; 103 struct device_node *np;
103 struct device_node *np = of_find_compatible_node( 104 void __iomem *scu_base;
104 NULL, NULL, "arm,cortex-a9-scu"); 105 u32 __iomem *cpu_strt_ptr;
106 u32 release_phys;
107 int cpu;
108 unsigned long entry_pa = virt_to_phys(sti_secondary_startup);
109
110 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
111
105 if (np) { 112 if (np) {
106 scu_base = of_iomap(np, 0); 113 scu_base = of_iomap(np, 0);
107 scu_enable(scu_base); 114 scu_enable(scu_base);
108 of_node_put(np); 115 of_node_put(np);
109 } 116 }
117
118 if (max_cpus <= 1)
119 return;
120
121 for_each_possible_cpu(cpu) {
122
123 np = of_get_cpu_node(cpu, NULL);
124
125 if (!np)
126 continue;
127
128 if (of_property_read_u32(np, "cpu-release-addr",
129 &release_phys)) {
130 pr_err("CPU %d: missing or invalid cpu-release-addr "
131 "property\n", cpu);
132 continue;
133 }
134
135 /*
136 * holding pen is usually configured in SBC DMEM but can also be
137 * in RAM.
138 */
139
140 if (!memblock_is_memory(release_phys))
141 cpu_strt_ptr =
142 ioremap(release_phys, sizeof(release_phys));
143 else
144 cpu_strt_ptr =
145 (u32 __iomem *)phys_to_virt(release_phys);
146
147 __raw_writel(entry_pa, cpu_strt_ptr);
148
149 /*
150 * wmb so that data is actually written
151 * before cache flush is done
152 */
153 smp_wmb();
154 sync_cache_w(cpu_strt_ptr);
155
156 if (!memblock_is_memory(release_phys))
157 iounmap(cpu_strt_ptr);
158 }
110} 159}
111 160
112struct smp_operations __initdata sti_smp_ops = { 161struct smp_operations __initdata sti_smp_ops = {
diff --git a/arch/arm/mach-sti/smp.h b/arch/arm/mach-sti/smp.h
index 1871b72b1a7e..ae22707d301f 100644
--- a/arch/arm/mach-sti/smp.h
+++ b/arch/arm/mach-sti/smp.h
@@ -14,4 +14,6 @@
14 14
15extern struct smp_operations sti_smp_ops; 15extern struct smp_operations sti_smp_ops;
16 16
17void sti_secondary_startup(void);
18
17#endif 19#endif