diff options
author | Magnus Damm <damm@opensource.se> | 2010-12-14 02:56:55 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-12-14 04:15:44 -0500 |
commit | 1c51ed4fb9f11fa1e0873aa2d5b28f42a85ac299 (patch) | |
tree | 258c5de6db68146a86fc27ae1dc2b8fed2dc40e3 /arch/arm | |
parent | 09dd7ded60019d6a4fd2ae20a08c4ad2bc3ed3e9 (diff) |
ARM: mach-shmobile: SMP base support
Add SMP base support for R-Mobile / SH-Mobile processors.
This patch contains all base code to support CONFIG_SMP
regardless of ARCH_SHMOBILE processor type. Both local timer
and CPU hotplug are supported, but no processor specific
code is included.
At this point only the default behavior is in place, so
a single core will always be used even though CONFIG_SMP
is enabled on multicore systems.
The SMP Kconfig entry for arch/arm/Kconfig is excluded from
this patch to simplify merging.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-shmobile/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/headsmp.S | 26 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/hotplug.c | 41 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/entry-macro-intc.S | 6 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/smp.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/localtimer.c | 25 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/platsmp.c | 73 |
8 files changed, 194 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index f5ad0892984d..d4346ddd9121 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile | |||
@@ -11,6 +11,11 @@ obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7377.o intc-sh7377.o | |||
11 | obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o | 11 | obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o |
12 | obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o | 12 | obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o |
13 | 13 | ||
14 | # SMP objects | ||
15 | smp-y := platsmp.o headsmp.o | ||
16 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
17 | smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
18 | |||
14 | # Pinmux setup | 19 | # Pinmux setup |
15 | pfc-y := | 20 | pfc-y := |
16 | pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.o | 21 | pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.o |
@@ -26,4 +31,5 @@ obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o | |||
26 | obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o | 31 | obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o |
27 | 32 | ||
28 | # Framework support | 33 | # Framework support |
34 | obj-$(CONFIG_SMP) += $(smp-y) | ||
29 | obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y) | 35 | obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y) |
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S new file mode 100644 index 000000000000..a5c5af1e6bce --- /dev/null +++ b/arch/arm/mach-shmobile/headsmp.S | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * SMP support for R-Mobile / SH-Mobile | ||
3 | * | ||
4 | * Copyright (C) 2010 Magnus Damm | ||
5 | * Copyright (C) 2010 Takashi Yoshii | ||
6 | * | ||
7 | * Based on vexpress, Copyright (c) 2003 ARM Limited, All Rights Reserved | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/linkage.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | __INIT | ||
17 | |||
18 | /* | ||
19 | * Reset vector for secondary CPUs. | ||
20 | * This will be mapped at address 0 by SBAR register. | ||
21 | * We need _long_ jump to the physical address. | ||
22 | */ | ||
23 | .align 12 | ||
24 | ENTRY(shmobile_secondary_vector) | ||
25 | ldr pc, 1f | ||
26 | 1: .long secondary_startup - CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START | ||
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c new file mode 100644 index 000000000000..238a0d97d2d5 --- /dev/null +++ b/arch/arm/mach-shmobile/hotplug.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * SMP support for R-Mobile / SH-Mobile | ||
3 | * | ||
4 | * Copyright (C) 2010 Magnus Damm | ||
5 | * | ||
6 | * Based on realview, Copyright (C) 2002 ARM Ltd, All Rights Reserved | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/smp.h> | ||
15 | |||
16 | int platform_cpu_kill(unsigned int cpu) | ||
17 | { | ||
18 | return 1; | ||
19 | } | ||
20 | |||
21 | void platform_cpu_die(unsigned int cpu) | ||
22 | { | ||
23 | while (1) { | ||
24 | /* | ||
25 | * here's the WFI | ||
26 | */ | ||
27 | asm(".word 0xe320f003\n" | ||
28 | : | ||
29 | : | ||
30 | : "memory", "cc"); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | int platform_cpu_disable(unsigned int cpu) | ||
35 | { | ||
36 | /* | ||
37 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
38 | * e.g. clock tick interrupts) | ||
39 | */ | ||
40 | return cpu == 0 ? -EPERM : 0; | ||
41 | } | ||
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 15932fd2435e..32822f7556ea 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | extern struct sys_timer shmobile_timer; | 4 | extern struct sys_timer shmobile_timer; |
5 | extern void shmobile_setup_console(void); | 5 | extern void shmobile_setup_console(void); |
6 | extern void shmobile_secondary_vector(void); | ||
6 | struct clk; | 7 | struct clk; |
7 | extern int clk_init(void); | 8 | extern int clk_init(void); |
8 | 9 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro-intc.S b/arch/arm/mach-shmobile/include/mach/entry-macro-intc.S index a285d13c7416..d06d4ba3251e 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro-intc.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro-intc.S | |||
@@ -17,6 +17,12 @@ | |||
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
19 | 19 | ||
20 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
21 | .endm | ||
22 | |||
23 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
24 | .endm | ||
25 | |||
20 | .macro disable_fiq | 26 | .macro disable_fiq |
21 | .endm | 27 | .endm |
22 | 28 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/smp.h b/arch/arm/mach-shmobile/include/mach/smp.h new file mode 100644 index 000000000000..f4a35ff82c67 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/smp.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __MACH_SMP_H | ||
2 | #define __MACH_SMP_H | ||
3 | |||
4 | #include <asm/hardware/gic.h> | ||
5 | #include <asm/smp_mpidr.h> | ||
6 | |||
7 | /* | ||
8 | * We use IRQ1 as the IPI | ||
9 | */ | ||
10 | static inline void smp_cross_call(const struct cpumask *mask) | ||
11 | { | ||
12 | #if defined(CONFIG_ARM_GIC) | ||
13 | gic_raise_softirq(mask, 1); | ||
14 | #endif | ||
15 | } | ||
16 | #endif | ||
diff --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c new file mode 100644 index 000000000000..2111c28b724e --- /dev/null +++ b/arch/arm/mach-shmobile/localtimer.c | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * SMP support for R-Mobile / SH-Mobile - local timer portion | ||
3 | * | ||
4 | * Copyright (C) 2010 Magnus Damm | ||
5 | * | ||
6 | * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/smp.h> | ||
14 | #include <linux/clockchips.h> | ||
15 | #include <asm/smp_twd.h> | ||
16 | #include <asm/localtimer.h> | ||
17 | |||
18 | /* | ||
19 | * Setup the local clock events for a CPU. | ||
20 | */ | ||
21 | void __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
22 | { | ||
23 | evt->irq = 29; | ||
24 | twd_timer_setup(evt); | ||
25 | } | ||
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c new file mode 100644 index 000000000000..b41f5d0650e4 --- /dev/null +++ b/arch/arm/mach-shmobile/platsmp.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * SMP support for R-Mobile / SH-Mobile | ||
3 | * | ||
4 | * Copyright (C) 2010 Magnus Damm | ||
5 | * | ||
6 | * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <asm/localtimer.h> | ||
19 | |||
20 | static unsigned int __init shmobile_smp_get_core_count(void) | ||
21 | { | ||
22 | return 1; | ||
23 | } | ||
24 | |||
25 | static void __init shmobile_smp_prepare_cpus(void) | ||
26 | { | ||
27 | /* do nothing for now */ | ||
28 | } | ||
29 | |||
30 | |||
31 | void __cpuinit platform_secondary_init(unsigned int cpu) | ||
32 | { | ||
33 | trace_hardirqs_off(); | ||
34 | } | ||
35 | |||
36 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
37 | { | ||
38 | return -ENOSYS; | ||
39 | } | ||
40 | |||
41 | void __init smp_init_cpus(void) | ||
42 | { | ||
43 | unsigned int ncores = shmobile_smp_get_core_count(); | ||
44 | unsigned int i; | ||
45 | |||
46 | for (i = 0; i < ncores; i++) | ||
47 | set_cpu_possible(i, true); | ||
48 | } | ||
49 | |||
50 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
51 | { | ||
52 | unsigned int ncores = shmobile_smp_get_core_count(); | ||
53 | unsigned int cpu = smp_processor_id(); | ||
54 | int i; | ||
55 | |||
56 | smp_store_cpu_info(cpu); | ||
57 | |||
58 | if (max_cpus > ncores) | ||
59 | max_cpus = ncores; | ||
60 | |||
61 | for (i = 0; i < max_cpus; i++) | ||
62 | set_cpu_present(i, true); | ||
63 | |||
64 | if (max_cpus > 1) { | ||
65 | shmobile_smp_prepare_cpus(); | ||
66 | |||
67 | /* | ||
68 | * Enable the local timer or broadcast device for the | ||
69 | * boot CPU, but only if we have more than one CPU. | ||
70 | */ | ||
71 | percpu_timer_setup(); | ||
72 | } | ||
73 | } | ||