From: shawn.guo@linaro.org (Shawn Guo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 4/6] arm/imx6q: add smp and cpu hotplug support
Date: Tue, 6 Sep 2011 17:58:38 +0800 [thread overview]
Message-ID: <1315303120-24203-5-git-send-email-shawn.guo@linaro.org> (raw)
In-Reply-To: <1315303120-24203-1-git-send-email-shawn.guo@linaro.org>
It adds smp and cpu hotplug support for imx6q.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/Makefile | 4 ++
arch/arm/mach-imx/head-v7.S | 75 +++++++++++++++++++++++++++
arch/arm/mach-imx/hotplug.c | 44 ++++++++++++++++
arch/arm/mach-imx/localtimer.c | 64 +++++++++++++++++++++++
arch/arm/mach-imx/platsmp.c | 86 +++++++++++++++++++++++++++++++
arch/arm/plat-mxc/include/mach/common.h | 3 +
7 files changed, 277 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-imx/head-v7.S
create mode 100644 arch/arm/mach-imx/hotplug.c
create mode 100644 arch/arm/mach-imx/localtimer.c
create mode 100644 arch/arm/mach-imx/platsmp.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 30f2868..13e0301 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -72,6 +72,7 @@ config SOC_IMX6Q
bool
select ARM_GIC
select CPU_V7
+ select HAVE_ARM_SCU
select HAVE_IMX_GPC
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 8c21fda..d46b2e7 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -66,4 +66,8 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+obj-$(CONFIG_CPU_V7) += head-v7.o
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(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 0000000..001ff9e
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ .section ".text.head", "ax"
+ __CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor. We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+ mov r0, #0
+ mcr p15, 2, r0, c0, c0, 0
+ mrc p15, 1, r0, c0, c0, 0
+
+ ldr r1, =0x7fff
+ and r2, r1, r0, lsr #13
+
+ ldr r1, =0x3ff
+
+ and r3, r1, r0, lsr #3 @ NumWays - 1
+ add r2, r2, #1 @ NumSets
+
+ and r0, r0, #0x7
+ add r0, r0, #4 @ SetShift
+
+ clz r1, r3 @ WayShift
+ add r4, r3, #1 @ NumWays
+1: sub r2, r2, #1 @ NumSets--
+ mov r3, r4 @ Temp = NumWays
+2: subs r3, r3, #1 @ Temp--
+ mov r5, r3, lsl r1
+ mov r6, r2, lsl r0
+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+ mcr p15, 0, r5, c7, c6, 2
+ bgt 2b
+ cmp r2, #0
+ bgt 1b
+ dsb
+ isb
+ mov pc, lr
+ENDPROC(v7_invalidate_l1)
+
+ENTRY(v7_cpu_resume)
+ bl v7_invalidate_l1
+ b cpu_resume
+ENDPROC(v7_cpu_resume)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 0000000..89493ab
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later@the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <mach/common.h>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ flush_cache_all();
+ imx_enable_cpu(cpu, false);
+ cpu_do_idle();
+
+ /* We should never return from idle */
+ panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 0000000..2b0f351
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+#include <asm/hardware/gic.h>
+
+static u32 twd_saved_regs[4];
+static int twd_irq;
+
+/*
+ * Resuming from ARM Dormant/Shutdown mode, the boot procedure will
+ * re-setup local timer for secondary cores. For primary core, it
+ * has to take care of itself with the following pair of functions
+ * during suspend/resume.
+ */
+void imx_local_timer_pre_suspend(void)
+{
+ twd_saved_regs[0] = __raw_readl(twd_base + TWD_TIMER_LOAD);
+ twd_saved_regs[1] = __raw_readl(twd_base + TWD_TIMER_COUNTER);
+ twd_saved_regs[2] = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+ twd_saved_regs[3] = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
+}
+
+void imx_local_timer_post_resume(void)
+{
+ __raw_writel(twd_saved_regs[0], twd_base + TWD_TIMER_LOAD);
+ __raw_writel(twd_saved_regs[1], twd_base + TWD_TIMER_COUNTER);
+ __raw_writel(twd_saved_regs[2], twd_base + TWD_TIMER_CONTROL);
+ __raw_writel(twd_saved_regs[3], twd_base + TWD_TIMER_INTSTAT);
+
+ gic_enable_ppi(twd_irq);
+}
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+ if (!twd_base) {
+ twd_base = of_iomap(np, 0);
+ WARN_ON(!twd_base);
+ }
+ twd_irq = irq_of_parse_and_map(np, 0);
+ evt->irq = twd_irq;
+ twd_timer_setup(evt);
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 0000000..2352caf
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+
+extern void v7_secondary_startup(void);
+
+#define IMX_SCU_VIRT_BASE 0xf4a00000
+
+static void __iomem *scu_base = ((void __iomem *)(IMX_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+ .virtual = IMX_SCU_VIRT_BASE,
+ .pfn = 0, /* run-time */
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ imx_set_cpu_jump(cpu, v7_secondary_startup);
+ imx_enable_cpu(cpu, true);
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ int i, ncores;
+
+ ncores = scu_get_core_count(scu_base);
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+ scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ imx_smp_prepare();
+}
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 4e3d978..73da910 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -72,4 +72,7 @@ extern void mxc_arch_reset_init(void __iomem *);
extern void mx51_efikamx_reset(void);
extern int mx53_revision(void);
extern int mx53_display_revision(void);
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
#endif
--
1.7.4.1
next prev parent reply other threads:[~2011-09-06 9:58 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-06 9:58 [PATCH 0/6] add initial imx6q support Shawn Guo
2011-09-06 9:58 ` [PATCH 1/6] arm/imx6q: add device tree source Shawn Guo
2011-09-06 18:31 ` Arnd Bergmann
2011-09-07 11:16 ` Shawn Guo
2011-09-06 9:58 ` [PATCH 2/6] arm/imx6q: add core definitions and low-level debug uart Shawn Guo
2011-09-06 18:39 ` Arnd Bergmann
2011-09-07 8:50 ` Shawn Guo
2011-09-06 20:25 ` Uwe Kleine-König
2011-09-07 11:00 ` Shawn Guo
2011-09-07 12:36 ` Uwe Kleine-König
2011-09-07 14:23 ` Russell King - ARM Linux
2011-09-07 15:36 ` Nicolas Pitre
2011-09-08 14:56 ` Arnd Bergmann
2011-09-09 17:28 ` Tony Lindgren
2011-09-12 2:30 ` Shawn Guo
2011-09-12 7:41 ` Uwe Kleine-König
2011-09-12 8:43 ` Shawn Guo
2011-09-12 8:44 ` Sascha Hauer
2011-09-12 11:36 ` Shawn Guo
2011-09-12 14:14 ` Russell King - ARM Linux
2011-09-17 11:59 ` Russell King - ARM Linux
2011-09-15 1:24 ` Shawn Guo
2011-09-06 9:58 ` [PATCH 3/6] arm/imx6q: add core drivers clock, gpc, mmdc and src Shawn Guo
2011-09-06 19:14 ` Arnd Bergmann
2011-09-07 6:05 ` Shawn Guo
2011-09-07 7:56 ` Arnd Bergmann
2011-09-12 16:12 ` Shawn Guo
2011-09-12 19:40 ` Grant Likely
2011-09-12 20:28 ` Arnd Bergmann
2011-09-12 21:04 ` Grant Likely
2011-09-13 0:07 ` Shawn Guo
2011-09-07 12:43 ` Barry Song
2011-09-08 6:48 ` Shawn Guo
2011-09-11 2:28 ` Barry Song
2011-09-12 19:16 ` Grant Likely
2011-09-12 9:46 ` Sascha Hauer
2011-09-12 11:49 ` Shawn Guo
2011-09-12 12:36 ` Uwe Kleine-König
2011-09-12 12:40 ` Arnd Bergmann
2011-09-12 14:27 ` Shawn Guo
2011-09-15 1:26 ` Shawn Guo
2011-09-06 9:58 ` Shawn Guo [this message]
2011-09-06 18:53 ` [PATCH 4/6] arm/imx6q: add smp and cpu hotplug support Arnd Bergmann
2011-09-07 4:41 ` Shawn Guo
2011-09-07 5:08 ` Shilimkar, Santosh
2011-09-07 7:46 ` Shawn Guo
2011-09-06 9:58 ` [PATCH 5/6] arm/imx6q: add device tree machine support Shawn Guo
2011-09-06 18:55 ` Arnd Bergmann
2011-09-07 3:07 ` Shawn Guo
2011-09-07 7:26 ` Arnd Bergmann
2011-09-06 9:58 ` [PATCH 6/6] arm/imx6q: add suspend/resume support Shawn Guo
2011-09-06 18:56 ` Arnd Bergmann
2011-09-07 13:50 ` Barry Song
2011-09-08 6:23 ` Shawn Guo
2011-09-08 7:47 ` Russell King - ARM Linux
2011-09-08 15:22 ` Shawn Guo
2011-09-08 16:24 ` Russell King - ARM Linux
2011-09-08 17:09 ` Lorenzo Pieralisi
2011-09-09 7:40 ` Shawn Guo
2011-09-09 6:31 ` Barry Song
2011-09-09 7:32 ` Shawn Guo
2011-09-09 8:15 ` Russell King - ARM Linux
2011-09-09 10:15 ` Shawn Guo
2011-09-09 18:47 ` Russell King - ARM Linux
2011-09-06 18:28 ` [PATCH 0/6] add initial imx6q support Arnd Bergmann
2011-09-06 19:42 ` Uwe Kleine-König
2011-09-07 2:55 ` Shawn Guo
2011-09-07 9:39 ` Arnd Bergmann
2011-09-07 2:51 ` Shawn Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1315303120-24203-5-git-send-email-shawn.guo@linaro.org \
--to=shawn.guo@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).