]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00180495 [mx6]Fix suspend/resume issue caused by hotplug
authorAnson Huang <b20788@freescale.com>
Wed, 23 May 2012 07:13:03 +0000 (15:13 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:11:57 +0000 (14:11 +0200)
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>
arch/arm/mach-mx6/plat_hotplug.c

index 67847655dc86a24b77ba79f4ee3a9bbf06fb3834..20a33329f472e2862912c95c8668ebcde0362371 100644 (file)
@@ -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>
 #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)