diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap-hotplug.c')
-rw-r--r-- | arch/arm/mach-omap2/omap-hotplug.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index 4976b93..f69cd5c 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c @@ -19,7 +19,13 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> + #include <mach/omap4-common.h> +#include <mach/omap-wakeupgen.h> + +#include "powerdomain.h" +#include "clockdomain.h" int platform_cpu_kill(unsigned int cpu) { @@ -32,6 +38,12 @@ int platform_cpu_kill(unsigned int cpu) */ void platform_cpu_die(unsigned int cpu) { + unsigned int this_cpu; + static struct clockdomain *cpu1_clkdm; + + if (!cpu1_clkdm) + cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); + flush_cache_all(); dsb(); @@ -39,18 +51,26 @@ void platform_cpu_die(unsigned int cpu) * we're ready for shutdown now, so do it */ if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) - printk(KERN_CRIT "Secure clear status failed\n"); + pr_err("Secure clear status failed\n"); for (;;) { /* - * Execute WFI + * Enter into low power state + * clear all interrupt wakeup sources */ - do_wfi(); - - if (omap_read_auxcoreboot0() == cpu) { + omap_wakeupgen_irqmask_all(cpu, 1); + gic_cpu_disable(); + omap4_enter_lowpower(cpu, PWRDM_POWER_OFF); + this_cpu = hard_smp_processor_id(); + if (omap_read_auxcoreboot0() == this_cpu) { /* * OK, proper wakeup, we're done */ + omap_wakeupgen_irqmask_all(this_cpu, 0); + gic_cpu_enable(); + + /* Restore clockdomain to hardware supervised */ + clkdm_allow_idle(cpu1_clkdm); break; } pr_debug("CPU%u: spurious wakeup call\n", cpu); |