diff options
author | Anson Huang <b20788@freescale.com> | 2012-05-23 15:13:03 +0800 |
---|---|---|
committer | Anson Huang <b20788@freescale.com> | 2012-05-23 15:46:16 +0800 |
commit | 106a5d89b9eb144b36a5ea636482b7fb30f6147c (patch) | |
tree | aa803c77795b8471b929a215acbf9a0c6820e752 /arch/arm/mach-mx6/plat_hotplug.c | |
parent | 77e21b5b743b914d3dbbf29bda8f33b839d4b615 (diff) |
ENGR00180495 [mx6]Fix suspend/resume issue caused by hotplug
When we kill a secondary cpu, we need to wait for it
die, then kill it from hardware setting. And to avoid
the cache unalign issue, we use hardware register to
send flag to inform main cpu to kill secondary cpu.
Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6/plat_hotplug.c')
-rw-r--r-- | arch/arm/mach-mx6/plat_hotplug.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/arm/mach-mx6/plat_hotplug.c b/arch/arm/mach-mx6/plat_hotplug.c index 67847655dc86..20a33329f472 100644 --- a/arch/arm/mach-mx6/plat_hotplug.c +++ b/arch/arm/mach-mx6/plat_hotplug.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/smp.h> +#include <linux/delay.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <linux/io.h> @@ -27,12 +28,21 @@ #include <asm/cacheflush.h> extern unsigned int num_cpu_idle_lock; +void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR); int platform_cpu_kill(unsigned int cpu) { - void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR); unsigned int val; + val = jiffies; + /* wait secondary cpu to die, timeout is 50ms */ + while (__raw_readl(src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4) == 0) { + if (time_after(jiffies, (unsigned long)(val + HZ / 20))) { + printk(KERN_WARNING "cpu %d: cpu could not die\n", cpu); + break; + } + } + /* * we're ready for shutdown now, so do it */ @@ -51,6 +61,7 @@ int platform_cpu_kill(unsigned int cpu) } } + __raw_writel(0x0, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4); return 1; } @@ -81,12 +92,23 @@ void platform_cpu_die(unsigned int cpu) : "=&r" (v) : "r" (0), "Ir" (CR_C), "Ir" (0x40) : "cc"); - /* tell cpu0 to kill me */ + /* Tell cpu0 to kill this core, as this core's cache is + already disabled, and we want to set a flag to tell cpu0 + to kill this core, so I write the flag to this core's SRC + parameter register, after cpu0 kill this core, it will + clear this register. */ + + __raw_writel(0x1, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4); + for (;;) { /* * Execute WFI */ - cpu_do_idle(); + asm(".word 0xe320f003\n" + : + : + : "memory", "cc"); + printk(KERN_ERR "cpu %d wake up from wfi !!!\n", cpu); } asm volatile( " mrc p15, 0, %0, c1, c0, 0\n" /* Enable D cache in SCTLR */ @@ -98,6 +120,7 @@ void platform_cpu_die(unsigned int cpu) : "=&r" (v) : "Ir" (CR_C), "Ir" (0x40) : "cc"); + __raw_writel(0x0, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4); } int platform_cpu_disable(unsigned int cpu) |