@@ -23,6 +23,7 @@
#include <mach/omap-wakeupgen.h>
#include "powerdomain.h"
+#include "clockdomain.h"
int platform_cpu_kill(unsigned int cpu)
{
@@ -36,6 +37,11 @@ int platform_cpu_kill(unsigned int cpu)
void platform_cpu_die(unsigned int cpu)
{
unsigned int this_cpu;
+ static struct clockdomain *cpu1_clkdm;
+
+ /* To avoid cpu1 clockdomain lookup every time */
+ if (!cpu1_clkdm)
+ cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
flush_cache_all();
dsb();
@@ -59,6 +65,9 @@ void platform_cpu_die(unsigned int cpu)
* OK, proper wakeup, we're done
*/
omap_wakeupgen_irqmask_all(this_cpu, 0);
+
+ /* Restore clockdomain to hardware supervised */
+ clkdm_allow_idle(cpu1_clkdm);
break;
}
pr_debug("CPU%u: spurious wakeup call\n", cpu);
@@ -25,6 +25,8 @@
#include <mach/hardware.h>
#include <mach/omap4-common.h>
+#include "clockdomain.h"
+
/* SCU base address */
void __iomem *scu_base;
@@ -48,6 +50,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
+ static struct clockdomain *cpu1_clkdm;
+ static bool booted;
/*
* Set synchronisation state between this boot processor
* and the secondary one
@@ -63,7 +67,28 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
omap_modify_auxcoreboot0(0x200, 0xfffffdff);
flush_cache_all();
smp_wmb();
- smp_cross_call(cpumask_of(cpu), 1);
+
+ /* To avoid cpu1 clockdomain lookup every time */
+ if (!cpu1_clkdm)
+ cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
+
+ /*
+ * The SGI(Software Generated Interrupts) are not wakeup capable
+ * from low power states. This is known limitation on OMAP4 and
+ * needs to be worked around by using software forced clockdomain
+ * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
+ * software force wakeup. After the wakeup, CPU1 restores its
+ * clockdomain hardware supervised mode.
+ * More details can be found in OMAP4430 TRM - Version J
+ * Section :
+ * 4.3.4.2 Power States of CPU0 and CPU1
+ */
+ if (booted) {
+ clkdm_wakeup(cpu1_clkdm);
+ } else {
+ dsb_sev();
+ booted = true;
+ }
/*
* Now the secondary core is starting up let it run its