aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrice Chotard <patrice.chotard@st.com>2018-12-20 08:32:15 -0500
committerPatrice Chotard <patrice.chotard@st.com>2018-12-20 08:32:15 -0500
commit704cfd7f5f71c6bc6cdfaa63a16ed0f72882b1a1 (patch)
tree4fcd7d8f5bf6ea09b7a0bf88f68297606275e04d
parent651022382c7f8da46cb4872a545ee1da6d097d2a (diff)
ARM: sti: remove pen_release and boot_lock
The pen_release implementation was created for Versatile platforms to work around boot loaders that did not differentiate between the various different secondary CPUs on this ARM development platform. This should not be true of modern platforms where we send IPIs to specific CPUs to wake them up. Remove the pen_release stuff from SoCs that make use of the per-CPU IPI mechanism. The boot_lock is something that was required for ARM development platforms to ensure that the delay calibration worked properly. This is not necessary for modern platforms that have better bus bandwidth and do not need to calibrate the delay loop for secondary cores. Remove the boot_lock entirely. Due to pen_release and boot_lock removal, .smp_prepare_cpus and .smp_boot_secondary STi callbacks must be reworked properly to allow secondary CPU bring up. Secondary CPU is initialized and started by a U-BOOTROM firmware. Secondary CPU is spinning and waiting for a write at cpu_strt_ptr. Writing secondary_startup address at cpu_strt_ptr makes it to jump directly to secondary_startup(). This write must be done in .smp_boot_secondary callback and not in .smp_prepare_cpus as previously, this insures that secondary_data struct is populated in __cpu_up() (stack, pgdir and swapper_pg_dir fields). The IPI in sti_boot_secondary() is useless, so remove it. This patch is the merged of Russell's patch [1] and the rework of .smp_prepare_cpus and .smp_boot_secondary STi callbacks [2]. [1] https://patchwork.kernel.org/patch/10729435/ [2] https://patchwork.kernel.org/patch/10735795/ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
-rw-r--r--arch/arm/mach-sti/Makefile2
-rw-r--r--arch/arm/mach-sti/headsmp.S43
-rw-r--r--arch/arm/mach-sti/platsmp.c88
3 files changed, 15 insertions, 118 deletions
diff --git a/arch/arm/mach-sti/Makefile b/arch/arm/mach-sti/Makefile
index acb330916333..f85ff059cfba 100644
--- a/arch/arm/mach-sti/Makefile
+++ b/arch/arm/mach-sti/Makefile
@@ -1,2 +1,2 @@
1obj-$(CONFIG_SMP) += platsmp.o headsmp.o 1obj-$(CONFIG_SMP) += platsmp.o
2obj-$(CONFIG_ARCH_STI) += board-dt.o 2obj-$(CONFIG_ARCH_STI) += board-dt.o
diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S
deleted file mode 100644
index e0ad451700d5..000000000000
--- a/arch/arm/mach-sti/headsmp.S
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * arch/arm/mach-sti/headsmp.S
3 *
4 * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
5 * http://www.st.com
6 *
7 * Cloned from linux/arch/arm/mach-vexpress/headsmp.S
8 *
9 * Copyright (c) 2003 ARM Limited
10 * All Rights Reserved
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16#include <linux/linkage.h>
17#include <linux/init.h>
18
19/*
20 * ST specific entry point for secondary CPUs. This provides
21 * a "holding pen" into which all secondary cores are held until we're
22 * ready for them to initialise.
23 */
24ENTRY(sti_secondary_startup)
25 mrc p15, 0, r0, c0, c0, 5
26 and r0, r0, #15
27 adr r4, 1f
28 ldmia r4, {r5, r6}
29 sub r4, r4, r5
30 add r6, r6, r4
31pen: ldr r7, [r6]
32 cmp r7, r0
33 bne pen
34
35 /*
36 * we've been released from the holding pen: secondary_stack
37 * should now contain the SVC stack for this core
38 */
39 b secondary_startup
40ENDPROC(sti_secondary_startup)
41
421: .long .
43 .long pen_release
diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c
index 231f19e17436..d0272a839ffb 100644
--- a/arch/arm/mach-sti/platsmp.c
+++ b/arch/arm/mach-sti/platsmp.c
@@ -28,82 +28,33 @@
28 28
29#include "smp.h" 29#include "smp.h"
30 30
31static void write_pen_release(int val) 31static u32 __iomem *cpu_strt_ptr;
32{
33 pen_release = val;
34 smp_wmb();
35 sync_cache_w(&pen_release);
36}
37
38static DEFINE_SPINLOCK(boot_lock);
39
40static void sti_secondary_init(unsigned int cpu)
41{
42 /*
43 * let the primary processor know we're out of the
44 * pen, then head off into the C entry point
45 */
46 write_pen_release(-1);
47
48 /*
49 * Synchronise with the boot thread.
50 */
51 spin_lock(&boot_lock);
52 spin_unlock(&boot_lock);
53}
54 32
55static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) 33static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
56{ 34{
57 unsigned long timeout; 35 unsigned long entry_pa = __pa_symbol(secondary_startup);
58
59 /*
60 * set synchronisation state between this boot processor
61 * and the secondary one
62 */
63 spin_lock(&boot_lock);
64 36
65 /* 37 /*
66 * The secondary processor is waiting to be released from 38 * Secondary CPU is initialised and started by a U-BOOTROM firmware.
67 * the holding pen - release it, then wait for it to flag 39 * Secondary CPU is spinning and waiting for a write at cpu_strt_ptr.
68 * that it has been released by resetting pen_release. 40 * Writing secondary_startup address at cpu_strt_ptr makes it to
69 * 41 * jump directly to secondary_startup().
70 * Note that "pen_release" is the hardware CPU ID, whereas
71 * "cpu" is Linux's internal ID.
72 */ 42 */
73 write_pen_release(cpu_logical_map(cpu)); 43 __raw_writel(entry_pa, cpu_strt_ptr);
74 44
75 /* 45 /* wmb so that data is actually written before cache flush is done */
76 * Send the secondary CPU a soft interrupt, thereby causing 46 smp_wmb();
77 * it to jump to the secondary entrypoint. 47 sync_cache_w(cpu_strt_ptr);
78 */
79 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
80
81 timeout = jiffies + (1 * HZ);
82 while (time_before(jiffies, timeout)) {
83 smp_rmb();
84 if (pen_release == -1)
85 break;
86
87 udelay(10);
88 }
89
90 /*
91 * now the secondary core is starting up let it run its
92 * calibrations, then wait for it to finish
93 */
94 spin_unlock(&boot_lock);
95 48
96 return pen_release != -1 ? -ENOSYS : 0; 49 return 0;
97} 50}
98 51
99static void __init sti_smp_prepare_cpus(unsigned int max_cpus) 52static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
100{ 53{
101 struct device_node *np; 54 struct device_node *np;
102 void __iomem *scu_base; 55 void __iomem *scu_base;
103 u32 __iomem *cpu_strt_ptr;
104 u32 release_phys; 56 u32 release_phys;
105 int cpu; 57 int cpu;
106 unsigned long entry_pa = __pa_symbol(sti_secondary_startup);
107 58
108 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); 59 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
109 60
@@ -131,8 +82,8 @@ static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
131 } 82 }
132 83
133 /* 84 /*
134 * holding pen is usually configured in SBC DMEM but can also be 85 * cpu-release-addr is usually configured in SBC DMEM but can
135 * in RAM. 86 * also be in RAM.
136 */ 87 */
137 88
138 if (!memblock_is_memory(release_phys)) 89 if (!memblock_is_memory(release_phys))
@@ -142,22 +93,11 @@ static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
142 cpu_strt_ptr = 93 cpu_strt_ptr =
143 (u32 __iomem *)phys_to_virt(release_phys); 94 (u32 __iomem *)phys_to_virt(release_phys);
144 95
145 __raw_writel(entry_pa, cpu_strt_ptr); 96 set_cpu_possible(cpu, true);
146
147 /*
148 * wmb so that data is actually written
149 * before cache flush is done
150 */
151 smp_wmb();
152 sync_cache_w(cpu_strt_ptr);
153
154 if (!memblock_is_memory(release_phys))
155 iounmap(cpu_strt_ptr);
156 } 97 }
157} 98}
158 99
159const struct smp_operations sti_smp_ops __initconst = { 100const struct smp_operations sti_smp_ops __initconst = {
160 .smp_prepare_cpus = sti_smp_prepare_cpus, 101 .smp_prepare_cpus = sti_smp_prepare_cpus,
161 .smp_secondary_init = sti_secondary_init,
162 .smp_boot_secondary = sti_boot_secondary, 102 .smp_boot_secondary = sti_boot_secondary,
163}; 103};