These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / arm / mach-exynos / pm.c
index cc75ab4..9c1506b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/firmware.h>
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
+#include <asm/cacheflush.h>
 
 #include <mach/map.h>
 
@@ -209,6 +210,8 @@ static int exynos_cpu0_enter_aftr(void)
                 * sequence, let's wait for one of these to happen
                 */
                while (exynos_cpu_power_state(1)) {
+                       unsigned long boot_addr;
+
                        /*
                         * The other cpu may skip idle and boot back
                         * up again
@@ -221,7 +224,11 @@ static int exynos_cpu0_enter_aftr(void)
                         * boot back up again, getting stuck in the
                         * boot rom code
                         */
-                       if (__raw_readl(cpu_boot_reg_base()) == 0)
+                       ret = exynos_get_boot_addr(1, &boot_addr);
+                       if (ret)
+                               goto fail;
+                       ret = -1;
+                       if (boot_addr == 0)
                                goto abort;
 
                        cpu_relax();
@@ -233,11 +240,14 @@ static int exynos_cpu0_enter_aftr(void)
 
 abort:
        if (cpu_online(1)) {
+               unsigned long boot_addr = virt_to_phys(exynos_cpu_resume);
+
                /*
                 * Set the boot vector to something non-zero
                 */
-               __raw_writel(virt_to_phys(exynos_cpu_resume),
-                            cpu_boot_reg_base());
+               ret = exynos_set_boot_addr(1, boot_addr);
+               if (ret)
+                       goto fail;
                dsb();
 
                /*
@@ -247,22 +257,42 @@ abort:
                while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN)
                        cpu_relax();
 
+               if (soc_is_exynos3250()) {
+                       while (!pmu_raw_readl(S5P_PMU_SPARE2) &&
+                              !atomic_read(&cpu1_wakeup))
+                               cpu_relax();
+
+                       if (!atomic_read(&cpu1_wakeup))
+                               exynos_core_restart(1);
+               }
+
                while (!atomic_read(&cpu1_wakeup)) {
+                       smp_rmb();
+
                        /*
                         * Poke cpu1 out of the boot rom
                         */
-                       __raw_writel(virt_to_phys(exynos_cpu_resume),
-                                    cpu_boot_reg_base());
 
-                       arch_send_wakeup_ipi_mask(cpumask_of(1));
+                       ret = exynos_set_boot_addr(1, boot_addr);
+                       if (ret)
+                               goto fail;
+
+                       call_firmware_op(cpu_boot, 1);
+
+                       if (soc_is_exynos3250())
+                               dsb_sev();
+                       else
+                               arch_send_wakeup_ipi_mask(cpumask_of(1));
                }
        }
-
+fail:
        return ret;
 }
 
 static int exynos_wfi_finisher(unsigned long flags)
 {
+       if (soc_is_exynos3250())
+               flush_cache_all();
        cpu_do_idle();
 
        return -1;
@@ -283,6 +313,9 @@ static int exynos_cpu1_powerdown(void)
         */
        exynos_cpu_power_down(1);
 
+       if (soc_is_exynos3250())
+               pmu_raw_writel(0, S5P_PMU_SPARE2);
+
        ret = cpu_suspend(0, exynos_wfi_finisher);
 
        cpu_pm_exit();
@@ -299,7 +332,9 @@ cpu1_aborted:
 
 static void exynos_pre_enter_aftr(void)
 {
-       __raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base());
+       unsigned long boot_addr = virt_to_phys(exynos_cpu_resume);
+
+       (void)exynos_set_boot_addr(1, boot_addr);
 }
 
 static void exynos_post_enter_aftr(void)