From d3af6976a24f8cebef23e72ade6d91ddd781c12b Mon Sep 17 00:00:00 2001 From: Leela Krishna Amudala Date: Fri, 16 May 2014 04:23:24 +0900 Subject: ARM: EXYNOS: Add generic cpu power control functions for exynos SoCs Add generic cpu power control functions for exynos based SoCS for cpu power up/down and to know the cpu status. Signed-off-by: Leela Krishna Amudala Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 15af0ceb0a66..cbfe23598236 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -100,6 +100,42 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) return -ENOENT; } +/** + * exynos_core_power_down : power down the specified cpu + * @cpu : the cpu to power down + * + * Power down the specified cpu. The sequence must be finished by a + * call to cpu_do_idle() + * + */ +void exynos_cpu_power_down(int cpu) +{ + __raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); +} + +/** + * exynos_cpu_power_up : power up the specified cpu + * @cpu : the cpu to power up + * + * Power up the specified cpu + */ +void exynos_cpu_power_up(int cpu) +{ + __raw_writel(S5P_CORE_LOCAL_PWR_EN, + EXYNOS_ARM_CORE_CONFIGURATION(cpu)); +} + +/** + * exynos_cpu_power_state : returns the power state of the cpu + * @cpu : the cpu to retrieve the power state from + * + */ +int exynos_cpu_power_state(int cpu) +{ + return (__raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) & + S5P_CORE_LOCAL_PWR_EN); +} + /* For Cortex-A9 Diagnostic and Power control register */ static unsigned int save_arm_register[2]; -- cgit v1.2.3 From 096d21c6ebd01b3440d1e6063e646d9db8e31ac9 Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Fri, 16 May 2014 04:23:26 +0900 Subject: ARM: EXYNOS: Add generic cluster power control functions Add generic cluster power control functions for exynos based SoCS for cluster power up/down and to know the cluster status. Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 3 +++ arch/arm/mach-exynos/pm.c | 30 ++++++++++++++++++++++++++++++ arch/arm/mach-exynos/regs-pmu.h | 6 ++++++ 3 files changed, 39 insertions(+) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 4d815a511bc1..7876ed04b7a5 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -66,5 +66,8 @@ extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); extern void exynos_cpu_power_down(int cpu); extern void exynos_cpu_power_up(int cpu); extern int exynos_cpu_power_state(int cpu); +extern void exynos_cluster_power_down(int cluster); +extern void exynos_cluster_power_up(int cluster); +extern int exynos_cluster_power_state(int cluster); #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index cbfe23598236..3f2ae864582e 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -136,6 +136,36 @@ int exynos_cpu_power_state(int cpu) S5P_CORE_LOCAL_PWR_EN); } +/** + * exynos_cluster_power_down : power down the specified cluster + * @cluster : the cluster to power down + */ +void exynos_cluster_power_down(int cluster) +{ + __raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster)); +} + +/** + * exynos_cluster_power_up : power up the specified cluster + * @cluster : the cluster to power up + */ +void exynos_cluster_power_up(int cluster) +{ + __raw_writel(S5P_CORE_LOCAL_PWR_EN, + EXYNOS_COMMON_CONFIGURATION(cluster)); +} + +/** + * exynos_cluster_power_state : returns the power state of the cluster + * @cluster : the cluster to retrieve the power state from + * + */ +int exynos_cluster_power_state(int cluster) +{ + return (__raw_readl(EXYNOS_COMMON_STATUS(cluster)) & + S5P_CORE_LOCAL_PWR_EN); +} + /* For Cortex-A9 Diagnostic and Power control register */ static unsigned int save_arm_register[2]; diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 98fb8d8715e6..f6b68a327586 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -111,6 +111,12 @@ #define EXYNOS_ARM_CORE_STATUS(_nr) \ (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4) +#define EXYNOS_ARM_COMMON_CONFIGURATION S5P_PMUREG(0x2500) +#define EXYNOS_COMMON_CONFIGURATION(_nr) \ + (EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr))) +#define EXYNOS_COMMON_STATUS(_nr) \ + (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4) + #define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028) #define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108) #define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128) -- cgit v1.2.3 From 4b245edc99f056f05a61cb2b1fd4604875cf8eab Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:12:00 +0900 Subject: ARM: EXYNOS: Remove unnecessary inclusion of cpu.h Exynos specific macros and declarations have been moved to mach-exynos. Inclusion of plat/cpu.h is no more necessary. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 1 - arch/arm/mach-exynos/exynos.c | 2 -- arch/arm/mach-exynos/firmware.c | 3 +-- arch/arm/mach-exynos/hotplug.c | 2 -- arch/arm/mach-exynos/platsmp.c | 2 -- arch/arm/mach-exynos/pm.c | 1 - arch/arm/mach-exynos/pmu.c | 2 -- 7 files changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index c57cae0e8779..3dd385ebf195 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index eb1a431a894a..59aab756702e 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -26,8 +26,6 @@ #include #include -#include - #include "common.h" #include "mfc.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index aa01c4222b40..f6cb510aee85 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -18,8 +18,7 @@ #include -#include - +#include "common.h" #include "smc.h" static int exynos_do_idle(void) diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 9ca692d2744e..3cab3f506689 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -19,8 +19,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 03e5e9f94705..c28cdb1c82cd 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -26,8 +26,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 15af0ceb0a66..ca672e24b5cd 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 05c7ce15322a..fb0deda3b3a4 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -13,8 +13,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" -- cgit v1.2.3 From 309e08c4ca5446ab9f3e8c17581e5515855d339d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:43:27 +0900 Subject: ARM: EXYNOS: Encapsulate register access inside a function for pm That makes the code cleaner and encapsulted. The function will be reused in the next patch. Signed-off-by: Daniel Lezcano Reviewed-by: Viresh Kumar Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm.c | 65 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 24 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 3f2ae864582e..86a46607969f 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -169,6 +169,42 @@ int exynos_cluster_power_state(int cluster) /* For Cortex-A9 Diagnostic and Power control register */ static unsigned int save_arm_register[2]; +static void exynos_cpu_save_register(void) +{ + unsigned long tmp; + + /* Save Power control register */ + asm ("mrc p15, 0, %0, c15, c0, 0" + : "=r" (tmp) : : "cc"); + + save_arm_register[0] = tmp; + + /* Save Diagnostic register */ + asm ("mrc p15, 0, %0, c15, c0, 1" + : "=r" (tmp) : : "cc"); + + save_arm_register[1] = tmp; +} + +static void exynos_cpu_restore_register(void) +{ + unsigned long tmp; + + /* Restore Power control register */ + tmp = save_arm_register[0]; + + asm volatile ("mcr p15, 0, %0, c15, c0, 0" + : : "r" (tmp) + : "cc"); + + /* Restore Diagnostic register */ + tmp = save_arm_register[1]; + + asm volatile ("mcr p15, 0, %0, c15, c0, 1" + : : "r" (tmp) + : "cc"); +} + static int exynos_cpu_suspend(unsigned long arg) { #ifdef CONFIG_CACHE_L2X0 @@ -228,17 +264,8 @@ static int exynos_pm_suspend(void) tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0); __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); - if (!soc_is_exynos5250()) { - /* Save Power control register */ - asm ("mrc p15, 0, %0, c15, c0, 0" - : "=r" (tmp) : : "cc"); - save_arm_register[0] = tmp; - - /* Save Diagnostic register */ - asm ("mrc p15, 0, %0, c15, c0, 1" - : "=r" (tmp) : : "cc"); - save_arm_register[1] = tmp; - } + if (!soc_is_exynos5250()) + exynos_cpu_save_register(); return 0; } @@ -262,19 +289,9 @@ static void exynos_pm_resume(void) /* No need to perform below restore code */ goto early_wakeup; } - if (!soc_is_exynos5250()) { - /* Restore Power control register */ - tmp = save_arm_register[0]; - asm volatile ("mcr p15, 0, %0, c15, c0, 0" - : : "r" (tmp) - : "cc"); - - /* Restore Diagnostic register */ - tmp = save_arm_register[1]; - asm volatile ("mcr p15, 0, %0, c15, c0, 1" - : : "r" (tmp) - : "cc"); - } + + if (!soc_is_exynos5250()) + exynos_cpu_restore_register(); /* For release retention */ -- cgit v1.2.3 From 85f9f90808b4437bbdff1dff2c80663dae57ab51 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:43:27 +0900 Subject: ARM: EXYNOS: Use the cpu_pm notifier for pm Use the cpu_pm_enter/exit notifier to group some pm code inside the pm file. The save and restore code is duplicated across pm.c and cpuidle.c. By using the cpu_pm notifier, we can factor out the routine. Signed-off-by: Daniel Lezcano Reviewed-by: Viresh Kumar Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 24 ------------------------ arch/arm/mach-exynos/pm.c | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 24 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 87f9f129883d..7a2d01bbef6b 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -47,26 +47,6 @@ static void exynos_set_wakeupmask(void) __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK); } -static unsigned int g_pwr_ctrl, g_diag_reg; - -static void save_cpu_arch_register(void) -{ - /*read power control register*/ - asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc"); - /*read diagnostic register*/ - asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc"); - return; -} - -static void restore_cpu_arch_register(void) -{ - /*write power control register*/ - asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc"); - /*write diagnostic register*/ - asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc"); - return; -} - static int idle_finisher(unsigned long flags) { exynos_set_wakeupmask(); @@ -88,8 +68,6 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, { unsigned long tmp; - save_cpu_arch_register(); - /* Setting Central Sequence Register for power down mode */ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); tmp &= ~S5P_CENTRAL_LOWPWR_CFG; @@ -104,8 +82,6 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, #endif cpu_pm_exit(); - restore_cpu_arch_register(); - /* * If PMU failed while entering sleep mode, WFI will be * ignored by PMU and then exiting cpu_do_idle(). diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 86a46607969f..3eb80cd4607d 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -387,10 +388,36 @@ static const struct platform_suspend_ops exynos_suspend_ops = { .valid = suspend_valid_only_mem, }; +static int exynos_cpu_pm_notifier(struct notifier_block *self, + unsigned long cmd, void *v) +{ + int cpu = smp_processor_id(); + + switch (cmd) { + case CPU_PM_ENTER: + if (cpu == 0) + exynos_cpu_save_register(); + break; + + case CPU_PM_EXIT: + if (cpu == 0) + exynos_cpu_restore_register(); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block exynos_cpu_pm_notifier_block = { + .notifier_call = exynos_cpu_pm_notifier, +}; + void __init exynos_pm_init(void) { u32 tmp; + cpu_pm_register_notifier(&exynos_cpu_pm_notifier_block); + /* Platform-specific GIC callback */ gic_arch_extn.irq_set_wake = exynos_irq_set_wake; -- cgit v1.2.3 From 795537daae8a14dd05923ee78b687a821460d4f1 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:50:16 +0900 Subject: ARM: EXYNOS: Move scu_enable in the cpu_pm notifier We make the cpuidle code less arch dependent. Signed-off-by: Daniel Lezcano Reviewed-by: Viresh Kumar Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 6 ------ arch/arm/mach-exynos/pm.c | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 7a2d01bbef6b..bf1bf87af00e 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -75,11 +74,6 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, cpu_pm_enter(); cpu_suspend(0, idle_finisher); - -#ifdef CONFIG_SMP - if (!soc_is_exynos5250()) - scu_enable(S5P_VA_SCU); -#endif cpu_pm_exit(); /* diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 3eb80cd4607d..fb1d9160991a 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -400,8 +400,13 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, break; case CPU_PM_EXIT: - if (cpu == 0) + if (cpu == 0) { +#ifdef CONFIG_SMP + if (!soc_is_exynos5250()) + scu_enable(S5P_VA_SCU); +#endif exynos_cpu_restore_register(); + } break; } -- cgit v1.2.3 From 58afbc61a33928a764460bfa4ea85c9dbe9d0a77 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:53:26 +0900 Subject: ARM: EXYNOS: Remove ifdef for scu_enable in pm The scu_enable function is already a noop in the scu's header file is CONFIG_SMP=n, so no need to use these macros in the code. Signed-off-by: Daniel Lezcano Reviewed-by: Viresh Kumar Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index fb1d9160991a..24c638d2afd4 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -310,7 +310,7 @@ static void exynos_pm_resume(void) s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - if (IS_ENABLED(CONFIG_SMP) && !soc_is_exynos5250()) + if (!soc_is_exynos5250()) scu_enable(S5P_VA_SCU); early_wakeup: @@ -401,10 +401,8 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, case CPU_PM_EXIT: if (cpu == 0) { -#ifdef CONFIG_SMP if (!soc_is_exynos5250()) scu_enable(S5P_VA_SCU); -#endif exynos_cpu_restore_register(); } break; -- cgit v1.2.3 From 3681bafeb1e4781bdeaecd19aa8c9f6d0db90f6f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:53:00 +0900 Subject: ARM: EXYNOS: Move the AFTR state function into pm.c In order to remove depedency on pm code, let's move the 'exynos_enter_aftr' function into the pm.c file as well as the other helper functions. Signed-off-by: Daniel Lezcano Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/cpuidle.c | 29 ----------------------------- arch/arm/mach-exynos/pm.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 7876ed04b7a5..27c9abdeb79e 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -69,5 +69,6 @@ extern int exynos_cpu_power_state(int cpu); extern void exynos_cluster_power_down(int cluster); extern void exynos_cluster_power_up(int cluster); extern int exynos_cluster_power_state(int cluster); +extern void exynos_enter_aftr(void); #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index d8b80c053e42..eea3eb9cecef 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -31,35 +31,6 @@ #include "common.h" #include "regs-pmu.h" -#define REG_DIRECTGO_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \ - S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ - (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0)) -#define REG_DIRECTGO_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ - S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ - (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1)) - -#define S5P_CHECK_AFTR 0xFCBA0D10 - -/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ -static void exynos_set_wakeupmask(long mask) -{ - __raw_writel(mask, S5P_WAKEUP_MASK); -} - -static void exynos_cpu_set_boot_vector(long flags) -{ - __raw_writel(virt_to_phys(exynos_cpu_resume), REG_DIRECTGO_ADDR); - __raw_writel(flags, REG_DIRECTGO_FLAG); -} - -static void exynos_enter_aftr(void) -{ - exynos_set_wakeupmask(0x0000ff3e); - exynos_cpu_set_boot_vector(S5P_CHECK_AFTR); - /* Set value of power down register for aftr mode */ - exynos_sys_powerdown_conf(SYS_AFTR); -} - static int idle_finisher(unsigned long flags) { exynos_enter_aftr(); diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 24c638d2afd4..179f7e09e20d 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -167,6 +167,35 @@ int exynos_cluster_power_state(int cluster) S5P_CORE_LOCAL_PWR_EN); } +#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \ + S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ + (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0)) +#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ + S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ + (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1)) + +#define S5P_CHECK_AFTR 0xFCBA0D10 + +/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ +static void exynos_set_wakeupmask(long mask) +{ + __raw_writel(mask, S5P_WAKEUP_MASK); +} + +static void exynos_cpu_set_boot_vector(long flags) +{ + __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR); + __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG); +} + +void exynos_enter_aftr(void) +{ + exynos_set_wakeupmask(0x0000ff3e); + exynos_cpu_set_boot_vector(S5P_CHECK_AFTR); + /* Set value of power down register for aftr mode */ + exynos_sys_powerdown_conf(SYS_AFTR); +} + /* For Cortex-A9 Diagnostic and Power control register */ static unsigned int save_arm_register[2]; -- cgit v1.2.3 From 0ebc13e2a2353f76ecdca11cf4d49da0b4e77f09 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:55:12 +0900 Subject: ARM: EXYNOS: Move the power sequence call in the cpu_pm notifier The code to initiate and exit the powerdown sequence is the same in pm.c and cpuidle.c. Let's split the common part in the pm.c and reuse it from the cpu_pm notifier. That is one more step forward to make the cpuidle driver arch indenpendant. Signed-off-by: Daniel Lezcano Reviewed-by: Viresh Kumar Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 22 ---------------------- arch/arm/mach-exynos/pm.c | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 27 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index eea3eb9cecef..cac51d852605 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -29,7 +29,6 @@ #include #include "common.h" -#include "regs-pmu.h" static int idle_finisher(unsigned long flags) { @@ -43,31 +42,10 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - unsigned long tmp; - - /* Setting Central Sequence Register for power down mode */ - tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); - tmp &= ~S5P_CENTRAL_LOWPWR_CFG; - __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); - cpu_pm_enter(); cpu_suspend(0, idle_finisher); cpu_pm_exit(); - /* - * If PMU failed while entering sleep mode, WFI will be - * ignored by PMU and then exiting cpu_do_idle(). - * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically - * in this situation. - */ - tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); - if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) { - tmp |= S5P_CENTRAL_LOWPWR_CFG; - __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); - /* Clear wakeup state register */ - __raw_writel(0x0, S5P_WAKEUP_STAT); - } - return index; } diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 179f7e09e20d..8b268b5b42fa 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -279,15 +279,21 @@ static void exynos_pm_prepare(void) __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); } -static int exynos_pm_suspend(void) +static void exynos_pm_central_suspend(void) { unsigned long tmp; /* Setting Central Sequence Register for power down mode */ - tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); tmp &= ~S5P_CENTRAL_LOWPWR_CFG; __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); +} + +static int exynos_pm_suspend(void) +{ + unsigned long tmp; + + exynos_pm_central_suspend(); /* Setting SEQ_OPTION register */ @@ -300,7 +306,7 @@ static int exynos_pm_suspend(void) return 0; } -static void exynos_pm_resume(void) +static int exynos_pm_central_resume(void) { unsigned long tmp; @@ -317,9 +323,17 @@ static void exynos_pm_resume(void) /* clear the wakeup state register */ __raw_writel(0x0, S5P_WAKEUP_STAT); /* No need to perform below restore code */ - goto early_wakeup; + return -1; } + return 0; +} + +static void exynos_pm_resume(void) +{ + if (exynos_pm_central_resume()) + goto early_wakeup; + if (!soc_is_exynos5250()) exynos_cpu_restore_register(); @@ -424,8 +438,10 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, switch (cmd) { case CPU_PM_ENTER: - if (cpu == 0) + if (cpu == 0) { + exynos_pm_central_suspend(); exynos_cpu_save_register(); + } break; case CPU_PM_EXIT: @@ -433,6 +449,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, if (!soc_is_exynos5250()) scu_enable(S5P_VA_SCU); exynos_cpu_restore_register(); + exynos_pm_central_resume(); } break; } -- cgit v1.2.3 From e30b154bd2df3be95deda85ce5bc5a05a18896ef Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 9 May 2014 06:56:24 +0900 Subject: ARM: EXYNOS: Move S5P_CHECK_SLEEP into pm.c This macro is only used there. Signed-off-by: Daniel Lezcano Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm.c | 3 ++- arch/arm/mach-exynos/regs-pmu.h | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 8b268b5b42fa..f7b0b77582f6 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -174,7 +174,8 @@ int exynos_cluster_power_state(int cluster) S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1)) -#define S5P_CHECK_AFTR 0xFCBA0D10 +#define S5P_CHECK_AFTR 0xFCBA0D10 +#define S5P_CHECK_SLEEP 0x00000BAD /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ static void exynos_set_wakeupmask(long mask) diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 4179f6a6d595..1d13b08708f0 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -129,8 +129,6 @@ #define S5P_CORE_LOCAL_PWR_EN 0x3 #define S5P_INT_LOCAL_PWR_EN 0x7 -#define S5P_CHECK_SLEEP 0x00000BAD - /* Only for EXYNOS4210 */ #define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154) #define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174) -- cgit v1.2.3 From cd245f59aae5d6ef265f46aa6cea78354d61b629 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 26 May 2014 04:50:34 +0900 Subject: ARM: EXYNOS: Fix kernel panic when unplugging CPU1 on exynos A look at the code reveals use of S5P_VA_SYSRAM macro, in case of certain SoC revisions, which is not valid any longer, after SYSRAM started to be mapped dynamically. The new dynamic mapping is stored in sysram_base_addr variable, which is declared static in platsmp.c This fix makes sysram_base_addr non-static, declared it in common.h and used in pm.c instead of S5P_VA_SYSRAM. Suggested-by: Tomasz Figa Signed-off-by: Daniel Lezcano Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/platsmp.c | 2 +- arch/arm/mach-exynos/pm.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-exynos/pm.c') diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 27c9abdeb79e..5848d3cc29e9 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -19,6 +19,7 @@ void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1); struct map_desc; extern void __iomem *sysram_ns_base_addr; +extern void __iomem *sysram_base_addr; void exynos_init_io(void); void exynos_restart(enum reboot_mode mode, const char *cmd); void exynos_cpuidle_init(void); diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 78002c7344b3..9e5e230575dd 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -34,7 +34,7 @@ extern void exynos4_secondary_startup(void); -static void __iomem *sysram_base_addr; +void __iomem *sysram_base_addr; void __iomem *sysram_ns_base_addr; static void __init exynos_smp_prepare_sysram(void) diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index f7b0b77582f6..0d1a46e7b021 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -169,10 +169,10 @@ int exynos_cluster_power_state(int cluster) #define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \ S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ - (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0)) + (sysram_base_addr + 0x24) : S5P_INFORM0)) #define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ - (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1)) + (sysram_base_addr + 0x20) : S5P_INFORM1)) #define S5P_CHECK_AFTR 0xFCBA0D10 #define S5P_CHECK_SLEEP 0x00000BAD -- cgit v1.2.3