ARM: EXYNOS: Fix failed second suspend on Exynos4
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-exynos / exynos.c
index f44c2e05c82e36ae3598ebf7ffe60e54a14235cc..c3bfbba3006d8fbd51c328b8c964434bf6fa1ea3 100644 (file)
@@ -166,6 +166,33 @@ static void __init exynos_init_io(void)
        exynos_map_io();
 }
 
+/*
+ * Set or clear the USE_DELAYED_RESET_ASSERTION option. Used by smp code
+ * and suspend.
+ *
+ * This is necessary only on Exynos4 SoCs. When system is running
+ * USE_DELAYED_RESET_ASSERTION should be set so the ARM CLK clock down
+ * feature could properly detect global idle state when secondary CPU is
+ * powered down.
+ *
+ * However this should not be set when such system is going into suspend.
+ */
+void exynos_set_delayed_reset_assertion(bool enable)
+{
+       if (soc_is_exynos4()) {
+               unsigned int tmp, core_id;
+
+               for (core_id = 0; core_id < num_possible_cpus(); core_id++) {
+                       tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
+                       if (enable)
+                               tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
+                       else
+                               tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
+                       pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
+               }
+       }
+}
+
 /*
  * Apparently, these SoCs are not able to wake-up from suspend using
  * the PMU. Too bad. Should they suddenly become capable of such a
@@ -206,7 +233,7 @@ static void __init exynos_dt_machine_init(void)
        if (!IS_ENABLED(CONFIG_SMP))
                exynos_sysram_init();
 
-#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
+#if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
        if (of_machine_is_compatible("samsung,exynos4210"))
                exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
 #endif
@@ -214,6 +241,7 @@ static void __init exynos_dt_machine_init(void)
            of_machine_is_compatible("samsung,exynos4212") ||
            (of_machine_is_compatible("samsung,exynos4412") &&
             of_machine_is_compatible("samsung,trats2")) ||
+           of_machine_is_compatible("samsung,exynos3250") ||
            of_machine_is_compatible("samsung,exynos5250"))
                platform_device_register(&exynos_cpuidle);