Hi Krzysztof, I tested this patch for suspend-to-ram on Exynos4412-based trats2 board. When I tested suspend-to-ram repetitively, I faced on hang issue of suspend-to-ram for Exynos4 as before. Could you send .config file for test? Thanks, Chanwoo Choi On 02/18/2015 07:45 PM, Krzysztof Kozlowski wrote: > On Exynos4412 boards (Trats2, Odroid U3) after enabling L2 cache in > 56b60b8bce4a ("ARM: 8265/1: dts: exynos4: Add nodes for L2 cache > controller") the second suspend to RAM failed. First suspend worked fine > but the next one hang just after powering down of secondary CPUs (system > consumed energy as it would be running but was not responsive). > > The issue was caused by enabling delayed reset assertion for CPU0 just > after issuing power down of cores. This was introduced for Exynos4 in > 13cfa6c4f7fa ("ARM: EXYNOS: Fix CPU idle clock down after CPU off"). > > The whole behavior is not well documented but after checking with vendor > code this should be done like this (on Exynos4): > 1. Enable delayed reset assertion when system is running (for all CPUs). > 2. Disable delayed reset assertion before suspending the system. > This can be done after powering off secondary CPUs. > 3. Re-enable the delayed reset assertion when system is resumed. > > Signed-off-by: Krzysztof Kozlowski <k.kozlowski@xxxxxxxxxxx> > Fixes: 13cfa6c4f7fa ("ARM: EXYNOS: Fix CPU idle clock down after CPU off") > Cc: <stable@xxxxxxxxxxxxxxx> > --- > arch/arm/mach-exynos/common.h | 2 ++ > arch/arm/mach-exynos/exynos.c | 27 +++++++++++++++++++++++++++ > arch/arm/mach-exynos/platsmp.c | 39 ++------------------------------------- > arch/arm/mach-exynos/suspend.c | 3 +++ > 4 files changed, 34 insertions(+), 37 deletions(-) > > diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h > index f70eca7ee705..0ef8d4b47102 100644 > --- a/arch/arm/mach-exynos/common.h > +++ b/arch/arm/mach-exynos/common.h > @@ -153,6 +153,8 @@ extern void exynos_enter_aftr(void); > > extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data; > > +extern void exynos_set_delayed_reset_assertion(bool enable); > + > extern void s5p_init_cpu(void __iomem *cpuid_addr); > extern unsigned int samsung_rev(void); > extern void __iomem *cpu_boot_reg_base(void); > diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c > index 2013f73797ed..e2f46295eed7 100644 > --- a/arch/arm/mach-exynos/exynos.c > +++ b/arch/arm/mach-exynos/exynos.c > @@ -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)); > + } > + } > +} > + > static const struct of_device_id exynos_dt_pmu_match[] = { > { .compatible = "samsung,exynos3250-pmu" }, > { .compatible = "samsung,exynos4210-pmu" }, > diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c > index 3f32c47a6d74..19d5c87c842c 100644 > --- a/arch/arm/mach-exynos/platsmp.c > +++ b/arch/arm/mach-exynos/platsmp.c > @@ -34,30 +34,6 @@ > > 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(u32 core_id) > { > @@ -73,8 +49,6 @@ static inline void cpu_leave_lowpower(u32 core_id) > : "=&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) > @@ -87,14 +61,6 @@ 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) { > @@ -355,9 +321,6 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) > 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 > @@ -404,6 +367,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) > > exynos_sysram_init(); > > + exynos_set_delayed_reset_assertion(true); > + > if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) > scu_enable(scu_base_addr()); > > diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c > index 666ec3e5b03f..d4da035cc88a 100644 > --- a/arch/arm/mach-exynos/suspend.c > +++ b/arch/arm/mach-exynos/suspend.c > @@ -235,6 +235,8 @@ static void exynos_pm_enter_sleep_mode(void) > > static void exynos_pm_prepare(void) > { > + exynos_set_delayed_reset_assertion(false); > + > /* Set wake-up mask registers */ > exynos_pm_set_wakeup_mask(); > > @@ -383,6 +385,7 @@ early_wakeup: > > /* Clear SLEEP mode set in INFORM1 */ > pmu_raw_writel(0x0, S5P_INFORM1); > + exynos_set_delayed_reset_assertion(true); > } > > static void exynos3250_pm_resume(void) > -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html