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.kozlow...@samsung.com>
> Fixes: 13cfa6c4f7fa ("ARM: EXYNOS: Fix CPU idle clock down after CPU off")
> Cc: <sta...@vger.kernel.org>
> ---
>  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 linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to