extern void exynos4_secondary_startup(void);
 
+/*
+ * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
+ * during hot-(un)plugging CPUx.
+ *
+ * The feature can be cleared safely during first boot of secondary CPU.
+ *
+ * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
+ * down a CPU so the CPU idle clock down feature could properly detect global
+ * idle state when CPUx is off.
+ */
+static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
+{
+       if (soc_is_exynos4()) {
+               unsigned int tmp;
+
+               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));
+       }
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
-static inline void cpu_leave_lowpower(void)
+static inline void cpu_leave_lowpower(u32 core_id)
 {
        unsigned int v;
 
          : "=&r" (v)
          : "Ir" (CR_C), "Ir" (0x40)
          : "cc");
+
+        exynos_set_delayed_reset_assertion(core_id, false);
 }
 
 static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
                /* Turn the CPU off on next WFI instruction. */
                exynos_cpu_power_down(core_id);
 
+               /*
+                * Exynos4 SoCs require setting
+                * USE_DELAYED_RESET_ASSERTION so the CPU idle
+                * clock down feature could properly detect
+                * global idle state when CPUx is off.
+                */
+               exynos_set_delayed_reset_assertion(core_id, true);
+
                wfi();
 
                if (pen_release == core_id) {
                udelay(10);
        }
 
+       /* No harm if this is called during first boot of secondary CPU */
+       exynos_set_delayed_reset_assertion(core_id, false);
+
        /*
         * now the secondary core is starting up let it run its
         * calibrations, then wait for it to finish
 static void exynos_cpu_die(unsigned int cpu)
 {
        int spurious = 0;
+       u32 mpidr = cpu_logical_map(cpu);
+       u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 
        v7_exit_coherency_flush(louis);
 
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
-       cpu_leave_lowpower();
+       cpu_leave_lowpower(core_id);
 
        if (spurious)
                pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 
 
 #define S5P_USE_STANDBY_WFI0                   (1 << 16)
 #define S5P_USE_STANDBY_WFE0                   (1 << 24)
+#define S5P_USE_DELAYED_RESET_ASSERTION                BIT(12)
 
 #define EXYNOS_SWRESET                         0x0400
 #define EXYNOS5440_SWRESET                     0x00C4
                        (EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
 #define EXYNOS_ARM_CORE_STATUS(_nr)            \
                        (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
+#define EXYNOS_ARM_CORE_OPTION(_nr)            \
+                       (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x8)
 
 #define EXYNOS_ARM_COMMON_CONFIGURATION                0x2500
 #define EXYNOS_COMMON_CONFIGURATION(_nr)       \