aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/arm/mach-realview/Makefile2
-rw-r--r--arch/arm/mach-realview/headsmp.S40
-rw-r--r--arch/arm/mach-realview/platsmp.c98
-rw-r--r--arch/arm/mach-vexpress/Makefile2
-rw-r--r--arch/arm/mach-vexpress/platsmp.c94
-rw-r--r--arch/arm/plat-versatile/Makefile2
-rw-r--r--arch/arm/plat-versatile/headsmp.S (renamed from arch/arm/mach-vexpress/headsmp.S)8
-rw-r--r--arch/arm/plat-versatile/platsmp.c104
8 files changed, 116 insertions, 234 deletions
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index ba85e5290b71..541fa4c109ef 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -8,5 +8,5 @@ obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
8obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o 8obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
9obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o 9obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o
10obj-$(CONFIG_MACH_REALVIEW_PBX) += realview_pbx.o 10obj-$(CONFIG_MACH_REALVIEW_PBX) += realview_pbx.o
11obj-$(CONFIG_SMP) += platsmp.o headsmp.o 11obj-$(CONFIG_SMP) += platsmp.o
12obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 12obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-realview/headsmp.S b/arch/arm/mach-realview/headsmp.S
deleted file mode 100644
index b34be4554d40..000000000000
--- a/arch/arm/mach-realview/headsmp.S
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * linux/arch/arm/mach-realview/headsmp.S
3 *
4 * Copyright (c) 2003 ARM Limited
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/linkage.h>
12#include <linux/init.h>
13
14 __INIT
15
16/*
17 * Realview specific entry point for secondary CPUs. This provides
18 * a "holding pen" into which all secondary cores are held until we're
19 * ready for them to initialise.
20 */
21ENTRY(realview_secondary_startup)
22 mrc p15, 0, r0, c0, c0, 5
23 and r0, r0, #15
24 adr r4, 1f
25 ldmia r4, {r5, r6}
26 sub r4, r4, r5
27 add r6, r6, r4
28pen: ldr r7, [r6]
29 cmp r7, r0
30 bne pen
31
32 /*
33 * we've been released from the holding pen: secondary_stack
34 * should now contain the SVC stack for this core
35 */
36 b secondary_startup
37
38 .align
391: .long .
40 .long pen_release
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 6959d13d908a..23919229e12d 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -10,44 +10,21 @@
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 <mach/hardware.h> 16#include <mach/hardware.h>
21#include <asm/mach-types.h> 17#include <asm/mach-types.h>
18#include <asm/smp_scu.h>
22#include <asm/unified.h> 19#include <asm/unified.h>
23 20
24#include <mach/board-eb.h> 21#include <mach/board-eb.h>
25#include <mach/board-pb11mp.h> 22#include <mach/board-pb11mp.h>
26#include <mach/board-pbx.h> 23#include <mach/board-pbx.h>
27#include <asm/smp_scu.h>
28 24
29#include "core.h" 25#include "core.h"
30 26
31extern void realview_secondary_startup(void); 27extern void versatile_secondary_startup(void);
32
33/*
34 * control for which core is the next to come out of the secondary
35 * boot "holding pen"
36 */
37volatile int __cpuinitdata pen_release = -1;
38
39/*
40 * Write pen_release in a way that is guaranteed to be visible to all
41 * observers, irrespective of whether they're taking part in coherency
42 * or not. This is necessary for the hotplug code to work reliably.
43 */
44static void __cpuinit write_pen_release(int val)
45{
46 pen_release = val;
47 smp_wmb();
48 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
49 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
50}
51 28
52static void __iomem *scu_base_addr(void) 29static void __iomem *scu_base_addr(void)
53{ 30{
@@ -62,75 +39,6 @@ static void __iomem *scu_base_addr(void)
62 return (void __iomem *)0; 39 return (void __iomem *)0;
63} 40}
64 41
65static DEFINE_SPINLOCK(boot_lock);
66
67void __cpuinit platform_secondary_init(unsigned int cpu)
68{
69 /*
70 * if any interrupts are already enabled for the primary
71 * core (e.g. timer irq), then they will not have been enabled
72 * for us: do so
73 */
74 gic_secondary_init(0);
75
76 /*
77 * let the primary processor know we're out of the
78 * pen, then head off into the C entry point
79 */
80 write_pen_release(-1);
81
82 /*
83 * Synchronise with the boot thread.
84 */
85 spin_lock(&boot_lock);
86 spin_unlock(&boot_lock);
87}
88
89int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
90{
91 unsigned long timeout;
92
93 /*
94 * set synchronisation state between this boot processor
95 * and the secondary one
96 */
97 spin_lock(&boot_lock);
98
99 /*
100 * The secondary processor is waiting to be released from
101 * the holding pen - release it, then wait for it to flag
102 * that it has been released by resetting pen_release.
103 *
104 * Note that "pen_release" is the hardware CPU ID, whereas
105 * "cpu" is Linux's internal ID.
106 */
107 write_pen_release(cpu);
108
109 /*
110 * Send the secondary CPU a soft interrupt, thereby causing
111 * the boot monitor to read the system wide flags register,
112 * and branch to the address found there.
113 */
114 smp_cross_call(cpumask_of(cpu), 1);
115
116 timeout = jiffies + (1 * HZ);
117 while (time_before(jiffies, timeout)) {
118 smp_rmb();
119 if (pen_release == -1)
120 break;
121
122 udelay(10);
123 }
124
125 /*
126 * now the secondary core is starting up let it run its
127 * calibrations, then wait for it to finish
128 */
129 spin_unlock(&boot_lock);
130
131 return pen_release != -1 ? -ENOSYS : 0;
132}
133
134/* 42/*
135 * Initialise the CPU possible map early - this describes the CPUs 43 * Initialise the CPU possible map early - this describes the CPUs
136 * which may be present or become present in the system. 44 * which may be present or become present in the system.
@@ -174,6 +82,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
174 * until it receives a soft interrupt, and then the 82 * until it receives a soft interrupt, and then the
175 * secondary CPU branches to this address. 83 * secondary CPU branches to this address.
176 */ 84 */
177 __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), 85 __raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)),
178 __io_address(REALVIEW_SYS_FLAGSSET)); 86 __io_address(REALVIEW_SYS_FLAGSSET));
179} 87}
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index cfe344ec1d6d..90551b9780ab 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -4,5 +4,5 @@
4 4
5obj-y := v2m.o 5obj-y := v2m.o
6obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o 6obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
7obj-$(CONFIG_SMP) += platsmp.o headsmp.o 7obj-$(CONFIG_SMP) += platsmp.o
8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
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}
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index b511abb10198..69714db47c33 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -4,4 +4,4 @@ obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
4obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o 4obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
5obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o 5obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
6obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o 6obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
7 7obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-vexpress/headsmp.S b/arch/arm/plat-versatile/headsmp.S
index 7a3f0632947c..d397a1fb2f54 100644
--- a/arch/arm/mach-vexpress/headsmp.S
+++ b/arch/arm/plat-versatile/headsmp.S
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-vexpress/headsmp.S 2 * linux/arch/arm/plat-versatile/headsmp.S
3 * 3 *
4 * Copyright (c) 2003 ARM Limited 4 * Copyright (c) 2003 ARM Limited
5 * All Rights Reserved 5 * All Rights Reserved
@@ -14,11 +14,11 @@
14 __INIT 14 __INIT
15 15
16/* 16/*
17 * Versatile Express specific entry point for secondary CPUs. This 17 * Realview/Versatile Express specific entry point for secondary CPUs.
18 * provides a "holding pen" into which all secondary cores are held 18 * This provides a "holding pen" into which all secondary cores are held
19 * until we're ready for them to initialise. 19 * until we're ready for them to initialise.
20 */ 20 */
21ENTRY(vexpress_secondary_startup) 21ENTRY(versatile_secondary_startup)
22 mrc p15, 0, r0, c0, c0, 5 22 mrc p15, 0, r0, c0, c0, 5
23 and r0, r0, #15 23 and r0, r0, #15
24 adr r4, 1f 24 adr r4, 1f
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
new file mode 100644
index 000000000000..ba3d471d4bcf
--- /dev/null
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -0,0 +1,104 @@
1/*
2 * linux/arch/arm/plat-versatile/platsmp.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/init.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>
17
18#include <asm/cacheflush.h>
19
20/*
21 * control for which core is the next to come out of the secondary
22 * boot "holding pen"
23 */
24volatile int __cpuinitdata pen_release = -1;
25
26/*
27 * Write pen_release in a way that is guaranteed to be visible to all
28 * observers, irrespective of whether they're taking part in coherency
29 * or not. This is necessary for the hotplug code to work reliably.
30 */
31static void __cpuinit write_pen_release(int val)
32{
33 pen_release = val;
34 smp_wmb();
35 __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
36 outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
37}
38
39static DEFINE_SPINLOCK(boot_lock);
40
41void __cpuinit platform_secondary_init(unsigned int cpu)
42{
43 /*
44 * if any interrupts are already enabled for the primary
45 * core (e.g. timer irq), then they will not have been enabled
46 * for us: do so
47 */
48 gic_secondary_init(0);
49
50 /*
51 * let the primary processor know we're out of the
52 * pen, then head off into the C entry point
53 */
54 write_pen_release(-1);
55
56 /*
57 * Synchronise with the boot thread.
58 */
59 spin_lock(&boot_lock);
60 spin_unlock(&boot_lock);
61}
62
63int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
64{
65 unsigned long timeout;
66
67 /*
68 * Set synchronisation state between this boot processor
69 * and the secondary one
70 */
71 spin_lock(&boot_lock);
72
73 /*
74 * This is really belt and braces; we hold unintended secondary
75 * CPUs in the holding pen until we're ready for them. However,
76 * since we haven't sent them a soft interrupt, they shouldn't
77 * be there.
78 */
79 write_pen_release(cpu);
80
81 /*
82 * Send the secondary CPU a soft interrupt, thereby causing
83 * the boot monitor to read the system wide flags register,
84 * and branch to the address found there.
85 */
86 smp_cross_call(cpumask_of(cpu), 1);
87
88 timeout = jiffies + (1 * HZ);
89 while (time_before(jiffies, timeout)) {
90 smp_rmb();
91 if (pen_release == -1)
92 break;
93
94 udelay(10);
95 }
96
97 /*
98 * now the secondary core is starting up let it run its
99 * calibrations, then wait for it to finish
100 */
101 spin_unlock(&boot_lock);
102
103 return pen_release != -1 ? -ENOSYS : 0;
104}