diff options
Diffstat (limited to 'arch/arm/mach-imx/hotplug.c')
| -rw-r--r-- | arch/arm/mach-imx/hotplug.c | 56 |
1 files changed, 21 insertions, 35 deletions
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 20ed2d56c1a..b35e99cc5e5 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -11,20 +11,16 @@ */ #include <linux/errno.h> -#include <asm/cacheflush.h> +#include <linux/jiffies.h> #include <asm/cp15.h> -#include <mach/common.h> +#include <asm/proc-fns.h> -int platform_cpu_kill(unsigned int cpu) -{ - return 1; -} +#include "common.h" static inline void cpu_enter_lowpower(void) { unsigned int v; - flush_cache_all(); asm volatile( "mcr p15, 0, %1, c7, c5, 0\n" " mcr p15, 0, %1, c7, c10, 4\n" @@ -42,43 +38,33 @@ static inline void cpu_enter_lowpower(void) : "cc"); } -static inline void cpu_leave_lowpower(void) -{ - unsigned int v; - - asm volatile( - "mrc p15, 0, %0, c1, c0, 0\n" - " orr %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 0\n" - " mrc p15, 0, %0, c1, c0, 1\n" - " orr %0, %0, %2\n" - " mcr p15, 0, %0, c1, c0, 1\n" - : "=&r" (v) - : "Ir" (CR_C), "Ir" (0x40) - : "cc"); -} - /* * platform-specific code to shutdown a CPU * * Called with IRQs disabled */ -void platform_cpu_die(unsigned int cpu) +void imx_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); - imx_enable_cpu(cpu, false); - cpu_do_idle(); - cpu_leave_lowpower(); + /* + * We use the cpu jumping argument register to sync with + * imx_cpu_kill() which is running on cpu0 and waiting for + * the register being cleared to kill the cpu. + */ + imx_set_cpu_arg(cpu, ~0); - /* We should never return from idle */ - panic("cpu %d unexpectedly exit from shutdown\n", cpu); + while (1) + cpu_do_idle(); } -int platform_cpu_disable(unsigned int cpu) +int imx_cpu_kill(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; + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (imx_get_cpu_arg(cpu) == 0) + if (time_after(jiffies, timeout)) + return 0; + imx_enable_cpu(cpu, false); + imx_set_cpu_arg(cpu, 0); + return 1; } |
