diff options
Diffstat (limited to 'arch/arm')
-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) |