diff options
| -rw-r--r-- | arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 | ||||
| -rw-r--r-- | arch/arm/boot/dts/exynos5800-peach-pi.dts | 1 | ||||
| -rw-r--r-- | arch/arm/mach-exynos/common.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-exynos/exynos.c | 27 | ||||
| -rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 39 | ||||
| -rw-r--r-- | arch/arm/mach-exynos/pm_domains.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-exynos/suspend.c | 7 |
7 files changed, 41 insertions, 40 deletions
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 0788d08fb43e..146e71118a72 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts | |||
| @@ -711,6 +711,7 @@ | |||
| 711 | num-slots = <1>; | 711 | num-slots = <1>; |
| 712 | broken-cd; | 712 | broken-cd; |
| 713 | cap-sdio-irq; | 713 | cap-sdio-irq; |
| 714 | keep-power-in-suspend; | ||
| 714 | card-detect-delay = <200>; | 715 | card-detect-delay = <200>; |
| 715 | clock-frequency = <400000000>; | 716 | clock-frequency = <400000000>; |
| 716 | samsung,dw-mshc-ciu-div = <1>; | 717 | samsung,dw-mshc-ciu-div = <1>; |
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 412f41d62686..02eb8b15374f 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts | |||
| @@ -674,6 +674,7 @@ | |||
| 674 | num-slots = <1>; | 674 | num-slots = <1>; |
| 675 | broken-cd; | 675 | broken-cd; |
| 676 | cap-sdio-irq; | 676 | cap-sdio-irq; |
| 677 | keep-power-in-suspend; | ||
| 677 | card-detect-delay = <200>; | 678 | card-detect-delay = <200>; |
| 678 | clock-frequency = <400000000>; | 679 | clock-frequency = <400000000>; |
| 679 | samsung,dw-mshc-ciu-div = <1>; | 680 | samsung,dw-mshc-ciu-div = <1>; |
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index acd5b560b728..5f5cd562c593 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h | |||
| @@ -159,6 +159,8 @@ extern void exynos_enter_aftr(void); | |||
| 159 | 159 | ||
| 160 | extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data; | 160 | extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data; |
| 161 | 161 | ||
| 162 | extern void exynos_set_delayed_reset_assertion(bool enable); | ||
| 163 | |||
| 162 | extern void s5p_init_cpu(void __iomem *cpuid_addr); | 164 | extern void s5p_init_cpu(void __iomem *cpuid_addr); |
| 163 | extern unsigned int samsung_rev(void); | 165 | extern unsigned int samsung_rev(void); |
| 164 | extern void __iomem *cpu_boot_reg_base(void); | 166 | 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 bcde0dd668df..5917a30eee33 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
| @@ -167,6 +167,33 @@ static void __init exynos_init_io(void) | |||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | /* | 169 | /* |
| 170 | * Set or clear the USE_DELAYED_RESET_ASSERTION option. Used by smp code | ||
| 171 | * and suspend. | ||
| 172 | * | ||
| 173 | * This is necessary only on Exynos4 SoCs. When system is running | ||
| 174 | * USE_DELAYED_RESET_ASSERTION should be set so the ARM CLK clock down | ||
| 175 | * feature could properly detect global idle state when secondary CPU is | ||
| 176 | * powered down. | ||
| 177 | * | ||
| 178 | * However this should not be set when such system is going into suspend. | ||
| 179 | */ | ||
| 180 | void exynos_set_delayed_reset_assertion(bool enable) | ||
| 181 | { | ||
| 182 | if (of_machine_is_compatible("samsung,exynos4")) { | ||
| 183 | unsigned int tmp, core_id; | ||
| 184 | |||
| 185 | for (core_id = 0; core_id < num_possible_cpus(); core_id++) { | ||
| 186 | tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id)); | ||
| 187 | if (enable) | ||
| 188 | tmp |= S5P_USE_DELAYED_RESET_ASSERTION; | ||
| 189 | else | ||
| 190 | tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION); | ||
| 191 | pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id)); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 170 | * Apparently, these SoCs are not able to wake-up from suspend using | 197 | * Apparently, these SoCs are not able to wake-up from suspend using |
| 171 | * the PMU. Too bad. Should they suddenly become capable of such a | 198 | * the PMU. Too bad. Should they suddenly become capable of such a |
| 172 | * feat, the matches below should be moved to suspend.c. | 199 | * feat, the matches below should be moved to suspend.c. |
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index ebd135bb0995..a825bca2a2b6 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c | |||
| @@ -34,30 +34,6 @@ | |||
| 34 | 34 | ||
| 35 | extern void exynos4_secondary_startup(void); | 35 | extern void exynos4_secondary_startup(void); |
| 36 | 36 | ||
| 37 | /* | ||
| 38 | * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs | ||
| 39 | * during hot-(un)plugging CPUx. | ||
| 40 | * | ||
| 41 | * The feature can be cleared safely during first boot of secondary CPU. | ||
| 42 | * | ||
| 43 | * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering | ||
| 44 | * down a CPU so the CPU idle clock down feature could properly detect global | ||
| 45 | * idle state when CPUx is off. | ||
| 46 | */ | ||
| 47 | static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable) | ||
| 48 | { | ||
| 49 | if (soc_is_exynos4()) { | ||
| 50 | unsigned int tmp; | ||
| 51 | |||
| 52 | tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id)); | ||
| 53 | if (enable) | ||
| 54 | tmp |= S5P_USE_DELAYED_RESET_ASSERTION; | ||
| 55 | else | ||
| 56 | tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION); | ||
| 57 | pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id)); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | #ifdef CONFIG_HOTPLUG_CPU | 37 | #ifdef CONFIG_HOTPLUG_CPU |
| 62 | static inline void cpu_leave_lowpower(u32 core_id) | 38 | static inline void cpu_leave_lowpower(u32 core_id) |
| 63 | { | 39 | { |
| @@ -73,8 +49,6 @@ static inline void cpu_leave_lowpower(u32 core_id) | |||
| 73 | : "=&r" (v) | 49 | : "=&r" (v) |
| 74 | : "Ir" (CR_C), "Ir" (0x40) | 50 | : "Ir" (CR_C), "Ir" (0x40) |
| 75 | : "cc"); | 51 | : "cc"); |
| 76 | |||
| 77 | exynos_set_delayed_reset_assertion(core_id, false); | ||
| 78 | } | 52 | } |
| 79 | 53 | ||
| 80 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | 54 | 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) | |||
| 87 | /* Turn the CPU off on next WFI instruction. */ | 61 | /* Turn the CPU off on next WFI instruction. */ |
| 88 | exynos_cpu_power_down(core_id); | 62 | exynos_cpu_power_down(core_id); |
| 89 | 63 | ||
| 90 | /* | ||
| 91 | * Exynos4 SoCs require setting | ||
| 92 | * USE_DELAYED_RESET_ASSERTION so the CPU idle | ||
| 93 | * clock down feature could properly detect | ||
| 94 | * global idle state when CPUx is off. | ||
| 95 | */ | ||
| 96 | exynos_set_delayed_reset_assertion(core_id, true); | ||
| 97 | |||
| 98 | wfi(); | 64 | wfi(); |
| 99 | 65 | ||
| 100 | if (pen_release == core_id) { | 66 | if (pen_release == core_id) { |
| @@ -371,9 +337,6 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
| 371 | udelay(10); | 337 | udelay(10); |
| 372 | } | 338 | } |
| 373 | 339 | ||
| 374 | /* No harm if this is called during first boot of secondary CPU */ | ||
| 375 | exynos_set_delayed_reset_assertion(core_id, false); | ||
| 376 | |||
| 377 | /* | 340 | /* |
| 378 | * now the secondary core is starting up let it run its | 341 | * now the secondary core is starting up let it run its |
| 379 | * calibrations, then wait for it to finish | 342 | * calibrations, then wait for it to finish |
| @@ -420,6 +383,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | |||
| 420 | 383 | ||
| 421 | exynos_sysram_init(); | 384 | exynos_sysram_init(); |
| 422 | 385 | ||
| 386 | exynos_set_delayed_reset_assertion(true); | ||
| 387 | |||
| 423 | if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) | 388 | if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) |
| 424 | scu_enable(scu_base_addr()); | 389 | scu_enable(scu_base_addr()); |
| 425 | 390 | ||
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index cbe56b35aea0..a9686535f9ed 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c | |||
| @@ -188,7 +188,7 @@ no_clk: | |||
| 188 | args.np = np; | 188 | args.np = np; |
| 189 | args.args_count = 0; | 189 | args.args_count = 0; |
| 190 | child_domain = of_genpd_get_from_provider(&args); | 190 | child_domain = of_genpd_get_from_provider(&args); |
| 191 | if (!child_domain) | 191 | if (IS_ERR(child_domain)) |
| 192 | continue; | 192 | continue; |
| 193 | 193 | ||
| 194 | if (of_parse_phandle_with_args(np, "power-domains", | 194 | if (of_parse_phandle_with_args(np, "power-domains", |
| @@ -196,7 +196,7 @@ no_clk: | |||
| 196 | continue; | 196 | continue; |
| 197 | 197 | ||
| 198 | parent_domain = of_genpd_get_from_provider(&args); | 198 | parent_domain = of_genpd_get_from_provider(&args); |
| 199 | if (!parent_domain) | 199 | if (IS_ERR(parent_domain)) |
| 200 | continue; | 200 | continue; |
| 201 | 201 | ||
| 202 | if (pm_genpd_add_subdomain(parent_domain, child_domain)) | 202 | if (pm_genpd_add_subdomain(parent_domain, child_domain)) |
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 3e6aea7f83af..c0b6dccbf7bd 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c | |||
| @@ -342,6 +342,8 @@ static void exynos_pm_enter_sleep_mode(void) | |||
| 342 | 342 | ||
| 343 | static void exynos_pm_prepare(void) | 343 | static void exynos_pm_prepare(void) |
| 344 | { | 344 | { |
| 345 | exynos_set_delayed_reset_assertion(false); | ||
| 346 | |||
| 345 | /* Set wake-up mask registers */ | 347 | /* Set wake-up mask registers */ |
| 346 | exynos_pm_set_wakeup_mask(); | 348 | exynos_pm_set_wakeup_mask(); |
| 347 | 349 | ||
| @@ -482,6 +484,7 @@ early_wakeup: | |||
| 482 | 484 | ||
| 483 | /* Clear SLEEP mode set in INFORM1 */ | 485 | /* Clear SLEEP mode set in INFORM1 */ |
| 484 | pmu_raw_writel(0x0, S5P_INFORM1); | 486 | pmu_raw_writel(0x0, S5P_INFORM1); |
| 487 | exynos_set_delayed_reset_assertion(true); | ||
| 485 | } | 488 | } |
| 486 | 489 | ||
| 487 | static void exynos3250_pm_resume(void) | 490 | static void exynos3250_pm_resume(void) |
| @@ -723,8 +726,10 @@ void __init exynos_pm_init(void) | |||
| 723 | return; | 726 | return; |
| 724 | } | 727 | } |
| 725 | 728 | ||
| 726 | if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) | 729 | if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) { |
| 727 | pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); | 730 | pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); |
| 731 | return; | ||
| 732 | } | ||
| 728 | 733 | ||
| 729 | pm_data = (const struct exynos_pm_data *) match->data; | 734 | pm_data = (const struct exynos_pm_data *) match->data; |
| 730 | 735 | ||
