aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vexpress/platsmp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-01-19 05:24:56 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-02-19 06:11:41 -0500
commit0462b4477ea3260304bbcd97c64c0b704b4f0f85 (patch)
treebf5baa29b411f0ea5f3ebeb30d12a4faf83a72cb /arch/arm/mach-vexpress/platsmp.c
parentcdab142a80d859984eb5e3876e0e762b1f0bded9 (diff)
ARM: realview/vexpress: consolidate SMP bringup code
Realview and Versatile Express share the same SMP bringup code, so consolidate the two implementations. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-vexpress/platsmp.c')
-rw-r--r--arch/arm/mach-vexpress/platsmp.c94
1 files changed, 2 insertions, 92 deletions
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 634bf1d3a311..18927023c2cc 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -10,13 +10,9 @@
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/jiffies.h>
16#include <linux/smp.h> 13#include <linux/smp.h>
17#include <linux/io.h> 14#include <linux/io.h>
18 15
19#include <asm/cacheflush.h>
20#include <asm/smp_scu.h> 16#include <asm/smp_scu.h>
21#include <asm/unified.h> 17#include <asm/unified.h>
22 18
@@ -26,99 +22,13 @@
26 22
27#include "core.h" 23#include "core.h"
28 24
29extern void vexpress_secondary_startup(void); 25extern void versatile_secondary_startup(void);
30
31/*
32 * control for which core is the next to come out of the secondary
33 * boot "holding pen"
34 */
35volatile int __cpuinitdata pen_release = -1;
36
37/*
38 * Write pen_release in a way that is guaranteed to be visible to all
39 * observers, irrespective of whether they're taking part in coherency
40 * or not. This is necessary for the hotplug code to work reliably.
41 */
42static void __cpuinit write_pen_release(int val)
43{
44 pen_release = val;
45 smp_wmb();
46 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
47 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
48}
49 26
50static void __iomem *scu_base_addr(void) 27static void __iomem *scu_base_addr(void)
51{ 28{
52 return MMIO_P2V(A9_MPCORE_SCU); 29 return MMIO_P2V(A9_MPCORE_SCU);
53} 30}
54 31
55static DEFINE_SPINLOCK(boot_lock);
56
57void __cpuinit platform_secondary_init(unsigned int cpu)
58{
59 /*
60 * if any interrupts are already enabled for the primary
61 * core (e.g. timer irq), then they will not have been enabled
62 * for us: do so
63 */
64 gic_secondary_init(0);
65
66 /*
67 * let the primary processor know we're out of the
68 * pen, then head off into the C entry point
69 */
70 write_pen_release(-1);
71
72 /*
73 * Synchronise with the boot thread.
74 */
75 spin_lock(&boot_lock);
76 spin_unlock(&boot_lock);
77}
78
79int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
80{
81 unsigned long timeout;
82
83 /*
84 * Set synchronisation state between this boot processor
85 * and the secondary one
86 */
87 spin_lock(&boot_lock);
88
89 /*
90 * This is really belt and braces; we hold unintended secondary
91 * CPUs in the holding pen until we're ready for them. However,
92 * since we haven't sent them a soft interrupt, they shouldn't
93 * be there.
94 */
95 write_pen_release(cpu);
96
97 /*
98 * Send the secondary CPU a soft interrupt, thereby causing
99 * the boot monitor to read the system wide flags register,
100 * and branch to the address found there.
101 */
102 smp_cross_call(cpumask_of(cpu), 1);
103
104 timeout = jiffies + (1 * HZ);
105 while (time_before(jiffies, timeout)) {
106 smp_rmb();
107 if (pen_release == -1)
108 break;
109
110 udelay(10);
111 }
112
113 /*
114 * now the secondary core is starting up let it run its
115 * calibrations, then wait for it to finish
116 */
117 spin_unlock(&boot_lock);
118
119 return pen_release != -1 ? -ENOSYS : 0;
120}
121
122/* 32/*
123 * Initialise the CPU possible map early - this describes the CPUs 33 * Initialise the CPU possible map early - this describes the CPUs
124 * which may be present or become present in the system. 34 * which may be present or become present in the system.
@@ -163,6 +73,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
163 * secondary CPU branches to this address. 73 * secondary CPU branches to this address.
164 */ 74 */
165 writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); 75 writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
166 writel(BSYM(virt_to_phys(vexpress_secondary_startup)), 76 writel(BSYM(virt_to_phys(versatile_secondary_startup)),
167 MMIO_P2V(V2M_SYS_FLAGSSET)); 77 MMIO_P2V(V2M_SYS_FLAGSSET));
168} 78}