aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2011-01-06 20:51:35 -0500
committerPaul Mundt <lethal@linux-sh.org>2011-01-06 20:51:35 -0500
commite9d728f528f9548c8dd013899b23e662fa7b6bca (patch)
treed88a5df6e5a2b33ebe088ad0223fe54679a59df3 /arch/arm/mach-shmobile
parent018a3fc7e3824ffcc80ad0160f9782c7d577c0c1 (diff)
parent6155f77d09b968f591876f368d4843168910449e (diff)
Merge branch 'rmobile/smp' into rmobile-latest
Conflicts: arch/arm/Kconfig arch/arm/mach-shmobile/include/mach/entry-macro-intc.S Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Makefile7
-rw-r--r--arch/arm/mach-shmobile/headsmp.S27
-rw-r--r--arch/arm/mach-shmobile/hotplug.c41
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h6
-rw-r--r--arch/arm/mach-shmobile/include/mach/smp.h16
-rw-r--r--arch/arm/mach-shmobile/localtimer.c25
-rw-r--r--arch/arm/mach-shmobile/platsmp.c85
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c97
8 files changed, 304 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index d16165a7b487..e2507f66f9d5 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -11,6 +11,12 @@ obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7377.o intc-sh7377.o
11obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o 11obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
12obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o 12obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
13 13
14# SMP objects
15smp-y := platsmp.o headsmp.o
16smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
17smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o
18smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
19
14# Pinmux setup 20# Pinmux setup
15pfc-y := 21pfc-y :=
16pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.o 22pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.o
@@ -32,4 +38,5 @@ obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o
32obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o 38obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
33 39
34# Framework support 40# Framework support
41obj-$(CONFIG_SMP) += $(smp-y)
35obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y) 42obj-$(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..d4cec6b4c7d9
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -0,0 +1,27 @@
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#include <asm/memory.h>
16
17 __INIT
18
19/*
20 * Reset vector for secondary CPUs.
21 * This will be mapped at address 0 by SBAR register.
22 * We need _long_ jump to the physical address.
23 */
24 .align 12
25ENTRY(shmobile_secondary_vector)
26 ldr pc, 1f
271: .long secondary_startup - PAGE_OFFSET + PHYS_OFFSET
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
16int platform_cpu_kill(unsigned int cpu)
17{
18 return 1;
19}
20
21void 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
34int 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 9f46cf5ca75f..013ac0ee8256 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
4extern struct sys_timer shmobile_timer; 4extern struct sys_timer shmobile_timer;
5extern void shmobile_setup_console(void); 5extern void shmobile_setup_console(void);
6extern void shmobile_secondary_vector(void);
6struct clk; 7struct clk;
7extern int clk_init(void); 8extern int clk_init(void);
8extern void shmobile_handle_irq_intc(struct pt_regs *); 9extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -40,4 +41,9 @@ extern void sh73a0_pinmux_init(void);
40extern struct clk sh73a0_extal1_clk; 41extern struct clk sh73a0_extal1_clk;
41extern struct clk sh73a0_extal2_clk; 42extern struct clk sh73a0_extal2_clk;
42 43
44extern unsigned int sh73a0_get_core_count(void);
45extern void sh73a0_secondary_init(unsigned int cpu);
46extern int sh73a0_boot_secondary(unsigned int cpu);
47extern void sh73a0_smp_prepare_cpus(void);
48
43#endif /* __ARCH_MACH_COMMON_H */ 49#endif /* __ARCH_MACH_COMMON_H */
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 */
10static 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 */
21void __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..3c2c0f49073e
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -0,0 +1,85 @@
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#include <asm/mach-types.h>
20#include <mach/common.h>
21
22static unsigned int __init shmobile_smp_get_core_count(void)
23{
24 if (machine_is_ag5evm())
25 return sh73a0_get_core_count();
26
27 return 1;
28}
29
30static void __init shmobile_smp_prepare_cpus(void)
31{
32 if (machine_is_ag5evm())
33 sh73a0_smp_prepare_cpus();
34}
35
36
37void __cpuinit platform_secondary_init(unsigned int cpu)
38{
39 trace_hardirqs_off();
40
41 if (machine_is_ag5evm())
42 sh73a0_secondary_init(cpu);
43}
44
45int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
46{
47 if (machine_is_ag5evm())
48 return sh73a0_boot_secondary(cpu);
49
50 return -ENOSYS;
51}
52
53void __init smp_init_cpus(void)
54{
55 unsigned int ncores = shmobile_smp_get_core_count();
56 unsigned int i;
57
58 for (i = 0; i < ncores; i++)
59 set_cpu_possible(i, true);
60}
61
62void __init smp_prepare_cpus(unsigned int max_cpus)
63{
64 unsigned int ncores = shmobile_smp_get_core_count();
65 unsigned int cpu = smp_processor_id();
66 int i;
67
68 smp_store_cpu_info(cpu);
69
70 if (max_cpus > ncores)
71 max_cpus = ncores;
72
73 for (i = 0; i < max_cpus; i++)
74 set_cpu_present(i, true);
75
76 if (max_cpus > 1) {
77 shmobile_smp_prepare_cpus();
78
79 /*
80 * Enable the local timer or broadcast device for the
81 * boot CPU, but only if we have more than one CPU.
82 */
83 percpu_timer_setup();
84 }
85}
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
new file mode 100644
index 000000000000..4e71fd416cd5
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -0,0 +1,97 @@
1/*
2 * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
3 *
4 * Copyright (C) 2010 Magnus Damm
5 * Copyright (C) 2010 Takashi Yoshii
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 as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/smp.h>
23#include <linux/spinlock.h>
24#include <linux/io.h>
25#include <mach/common.h>
26#include <asm/smp_scu.h>
27#include <asm/smp_twd.h>
28#include <asm/hardware/gic.h>
29
30#define WUPCR 0xe6151010
31#define SRESCR 0xe6151018
32#define PSTR 0xe6151040
33#define SBAR 0xe6180020
34#define APARMBAREA 0xe6f10020
35
36static void __iomem *scu_base_addr(void)
37{
38 return (void __iomem *)0xf0000000;
39}
40
41static DEFINE_SPINLOCK(scu_lock);
42static unsigned long tmp;
43
44static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
45{
46 void __iomem *scu_base = scu_base_addr();
47
48 spin_lock(&scu_lock);
49 tmp = __raw_readl(scu_base + 8);
50 tmp &= ~clr;
51 tmp |= set;
52 spin_unlock(&scu_lock);
53
54 /* disable cache coherency after releasing the lock */
55 __raw_writel(tmp, scu_base + 8);
56}
57
58unsigned int __init sh73a0_get_core_count(void)
59{
60 void __iomem *scu_base = scu_base_addr();
61
62 return scu_get_core_count(scu_base);
63}
64
65void __cpuinit sh73a0_secondary_init(unsigned int cpu)
66{
67 gic_cpu_init(0, __io(0xf0000100));
68}
69
70int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
71{
72 /* enable cache coherency */
73 modify_scu_cpu_psr(0, 3 << (cpu * 8));
74
75 if (((__raw_readw(__io(PSTR)) >> (4 * cpu)) & 3) == 3)
76 __raw_writel(1 << cpu, __io(WUPCR)); /* wake up */
77 else
78 __raw_writel(1 << cpu, __io(SRESCR)); /* reset */
79
80 return 0;
81}
82
83void __init sh73a0_smp_prepare_cpus(void)
84{
85#ifdef CONFIG_HAVE_ARM_TWD
86 twd_base = (void __iomem *)0xf0000600;
87#endif
88
89 scu_enable(scu_base_addr());
90
91 /* Map the reset vector (in headsmp.S) */
92 __raw_writel(0, __io(APARMBAREA)); /* 4k */
93 __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
94
95 /* enable cache coherency on CPU0 */
96 modify_scu_cpu_psr(0, 3 << (0 * 8));
97}