aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-09-06 02:59:40 -0400
committerArnd Bergmann <arnd@arndb.de>2011-10-31 09:26:24 -0400
commit69c31b7a6e9cd4654ed0bfc7e70b4d7076a5cdb3 (patch)
tree2f0581360d423e9d472a4c163e91babde57cd167 /arch
parent9fbbe6890c88aa332efe61d5894108dd8b932530 (diff)
arm/imx6q: add smp and cpu hotplug support
It adds smp and cpu hotplug support for imx6q. Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-imx/Makefile5
-rw-r--r--arch/arm/mach-imx/head-v7.S71
-rw-r--r--arch/arm/mach-imx/hotplug.c44
-rw-r--r--arch/arm/mach-imx/localtimer.c35
-rw-r--r--arch/arm/mach-imx/platsmp.c85
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h5
7 files changed, 246 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 40372a8e301..66b86489384 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -611,6 +611,7 @@ config SOC_IMX6Q
611 select ARM_GIC 611 select ARM_GIC
612 select CACHE_L2X0 612 select CACHE_L2X0
613 select CPU_V7 613 select CPU_V7
614 select HAVE_ARM_SCU
614 select HAVE_IMX_GPC 615 select HAVE_IMX_GPC
615 select HAVE_IMX_MMDC 616 select HAVE_IMX_MMDC
616 select HAVE_IMX_SRC 617 select HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 65218d98a78..f1098507a88 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -65,4 +65,9 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
65obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o 65obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
66obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o 66obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
67obj-$(CONFIG_HAVE_IMX_SRC) += src.o 67obj-$(CONFIG_HAVE_IMX_SRC) += src.o
68obj-$(CONFIG_CPU_V7) += head-v7.o
69AFLAGS_head-v7.o :=-Wa,-march=armv7-a
70obj-$(CONFIG_SMP) += platsmp.o
71obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
72obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
68obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o 73obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
new file mode 100644
index 00000000000..ede908bca7d
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/linkage.h>
14#include <linux/init.h>
15#include <asm/hardware/cache-l2x0.h>
16
17 .section ".text.head", "ax"
18 __CPUINIT
19
20/*
21 * The secondary kernel init calls v7_flush_dcache_all before it enables
22 * the L1; however, the L1 comes out of reset in an undefined state, so
23 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
24 * of cache lines with uninitialized data and uninitialized tags to get
25 * written out to memory, which does really unpleasant things to the main
26 * processor. We fix this by performing an invalidate, rather than a
27 * clean + invalidate, before jumping into the kernel.
28 *
29 * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
30 * to be called for both secondary cores startup and primary core resume
31 * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
32 */
33ENTRY(v7_invalidate_l1)
34 mov r0, #0
35 mcr p15, 2, r0, c0, c0, 0
36 mrc p15, 1, r0, c0, c0, 0
37
38 ldr r1, =0x7fff
39 and r2, r1, r0, lsr #13
40
41 ldr r1, =0x3ff
42
43 and r3, r1, r0, lsr #3 @ NumWays - 1
44 add r2, r2, #1 @ NumSets
45
46 and r0, r0, #0x7
47 add r0, r0, #4 @ SetShift
48
49 clz r1, r3 @ WayShift
50 add r4, r3, #1 @ NumWays
511: sub r2, r2, #1 @ NumSets--
52 mov r3, r4 @ Temp = NumWays
532: subs r3, r3, #1 @ Temp--
54 mov r5, r3, lsl r1
55 mov r6, r2, lsl r0
56 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
57 mcr p15, 0, r5, c7, c6, 2
58 bgt 2b
59 cmp r2, #0
60 bgt 1b
61 dsb
62 isb
63 mov pc, lr
64ENDPROC(v7_invalidate_l1)
65
66#ifdef CONFIG_SMP
67ENTRY(v7_secondary_startup)
68 bl v7_invalidate_l1
69 b secondary_startup
70ENDPROC(v7_secondary_startup)
71#endif
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 00000000000..89493abd497
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/errno.h>
14#include <asm/cacheflush.h>
15#include <mach/common.h>
16
17int platform_cpu_kill(unsigned int cpu)
18{
19 return 1;
20}
21
22/*
23 * platform-specific code to shutdown a CPU
24 *
25 * Called with IRQs disabled
26 */
27void platform_cpu_die(unsigned int cpu)
28{
29 flush_cache_all();
30 imx_enable_cpu(cpu, false);
31 cpu_do_idle();
32
33 /* We should never return from idle */
34 panic("cpu %d unexpectedly exit from shutdown\n", cpu);
35}
36
37int platform_cpu_disable(unsigned int cpu)
38{
39 /*
40 * we don't allow CPU 0 to be shutdown (it is still too special
41 * e.g. clock tick interrupts)
42 */
43 return cpu == 0 ? -EPERM : 0;
44}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 00000000000..3a163515d41
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,35 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/clockchips.h>
15#include <linux/of_address.h>
16#include <linux/of_irq.h>
17#include <asm/smp_twd.h>
18
19/*
20 * Setup the local clock events for a CPU.
21 */
22int __cpuinit local_timer_setup(struct clock_event_device *evt)
23{
24 struct device_node *np;
25
26 np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
27 if (!twd_base) {
28 twd_base = of_iomap(np, 0);
29 WARN_ON(!twd_base);
30 }
31 evt->irq = irq_of_parse_and_map(np, 0);
32 twd_timer_setup(evt);
33
34 return 0;
35}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 00000000000..ab98c6fec9e
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/smp.h>
15#include <asm/page.h>
16#include <asm/smp_scu.h>
17#include <asm/hardware/gic.h>
18#include <asm/mach/map.h>
19#include <mach/common.h>
20#include <mach/hardware.h>
21
22static void __iomem *scu_base;
23
24static struct map_desc scu_io_desc __initdata = {
25 /* .virtual and .pfn are run-time assigned */
26 .length = SZ_4K,
27 .type = MT_DEVICE,
28};
29
30void __init imx_scu_map_io(void)
31{
32 unsigned long base;
33
34 /* Get SCU base */
35 asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
36
37 scu_io_desc.virtual = IMX_IO_P2V(base);
38 scu_io_desc.pfn = __phys_to_pfn(base);
39 iotable_init(&scu_io_desc, 1);
40
41 scu_base = IMX_IO_ADDRESS(base);
42}
43
44void __cpuinit platform_secondary_init(unsigned int cpu)
45{
46 /*
47 * if any interrupts are already enabled for the primary
48 * core (e.g. timer irq), then they will not have been enabled
49 * for us: do so
50 */
51 gic_secondary_init(0);
52}
53
54int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
55{
56 imx_set_cpu_jump(cpu, v7_secondary_startup);
57 imx_enable_cpu(cpu, true);
58 return 0;
59}
60
61/*
62 * Initialise the CPU possible map early - this describes the CPUs
63 * which may be present or become present in the system.
64 */
65void __init smp_init_cpus(void)
66{
67 int i, ncores;
68
69 ncores = scu_get_core_count(scu_base);
70
71 for (i = 0; i < ncores; i++)
72 set_cpu_possible(i, true);
73
74 set_smp_cross_call(gic_raise_softirq);
75}
76
77void imx_smp_prepare(void)
78{
79 scu_enable(scu_base);
80}
81
82void __init platform_smp_prepare_cpus(unsigned int max_cpus)
83{
84 imx_smp_prepare();
85}
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index c2258374488..6340df2284d 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -99,4 +99,9 @@ void gic_handle_irq(struct pt_regs *);
99#define imx53_handle_irq tzic_handle_irq 99#define imx53_handle_irq tzic_handle_irq
100#define imx6q_handle_irq gic_handle_irq 100#define imx6q_handle_irq gic_handle_irq
101 101
102extern void imx_enable_cpu(int cpu, bool enable);
103extern void imx_set_cpu_jump(int cpu, void *jump_addr);
104#ifdef CONFIG_SMP
105extern void v7_secondary_startup(void);
106#endif
102#endif 107#endif