Changelog:
V3: * Added patch : "ARM: exynos: cpuidle: Disable cpuidle for 5440" * Removed patch : "ARM: exynos: config: Enable cpuidle" * Removed default ARM_EXYNOS4210_CPUIDLE=y * Added comment about bug fix side effect 'for_each_possible_cpu' V2: * Added comment in changelog for calls order (5/17) * Call the powerdown only for cpu0 in the pm notifier * Set the pm notifier for all boards
V1: initial post
This patchset relies on the cpm_pm notifier to initiate the powerdown sequence operations from pm.c instead cpuidle.c. Thus the cpuidle driver is no longer dependent from arch specific code as everything is called from the pm.c file.
The patchset applies on top of linux-samsung/for-next.
Tested on exynos4: 4210 Tested on exynos5: 5250 (without AFTR)
Daniel Lezcano (17): ARM: exynos: cpuidle: Prevent forward declaration ARM: exynos: cpuidle: use cpuidle_register ARM: exynos: cpuidle: change function name prefix ARM: exynos: cpuidle: encapsulate register access inside a function ARM: exynos: cpuidle: Move some code inside the idle_finisher ARM: exynos: cpuidle: Fix S5P_WAKEUP_STAT call ARM: exynos: cpuidle: Use the cpu_pm notifier ARM: exynos: cpuidle: Move scu_enable in the cpu_pm notifier ARM: exynos: cpuidle: Remove ifdef for scu_enable ARM: exynos: cpuidle: Move exynos_set_wakeupmask in the cpu_pm notifier ARM: exynos: cpuidle: Move the power sequence call in the cpu_pm notifier ARM: exynos: cpuidle: Move S5P_CHECK_AFTR in a header ARM: exynos: cpuidle: Move clock setup to pm.c ARM: exynos: cpuidle: Move the boot vector in pm.c ARM: exynos: cpuidle: Disable cpuidle for 5440 ARM: exynos: cpuidle: Pass the AFTR callback to the platform_data ARM: exynos: cpuidle: Move the driver to drivers/cpuidle directory
arch/arm/mach-exynos/Makefile | 1 - arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/cpuidle.c | 255 -------------------------------------- arch/arm/mach-exynos/exynos.c | 8 +- arch/arm/mach-exynos/pm.c | 177 +++++++++++++++++++++----- arch/arm/mach-exynos/pmu.c | 6 + arch/arm/mach-exynos/regs-pmu.h | 20 +++ drivers/cpuidle/Kconfig.arm | 6 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-exynos.c | 97 +++++++++++++++ 10 files changed, 285 insertions(+), 287 deletions(-) delete mode 100644 arch/arm/mach-exynos/cpuidle.c create mode 100644 drivers/cpuidle/cpuidle-exynos.c
Move the structure below the 'exynos4_enter_lowpower' function so no more need of forward declaration.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index b530231..9623a05 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -59,30 +59,8 @@ #define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
-static int exynos4_enter_lowpower(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index); - static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-static struct cpuidle_driver exynos4_idle_driver = { - .name = "exynos4_idle", - .owner = THIS_MODULE, - .states = { - [0] = ARM_CPUIDLE_WFI_STATE, - [1] = { - .enter = exynos4_enter_lowpower, - .exit_latency = 300, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "C1", - .desc = "ARM power down", - }, - }, - .state_count = 2, - .safe_state_index = 0, -}; - /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ static void exynos4_set_wakeupmask(void) { @@ -213,6 +191,24 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); }
+static struct cpuidle_driver exynos4_idle_driver = { + .name = "exynos4_idle", + .owner = THIS_MODULE, + .states = { + [0] = ARM_CPUIDLE_WFI_STATE, + [1] = { + .enter = exynos4_enter_lowpower, + .exit_latency = 300, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "C1", + .desc = "ARM power down", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + static int exynos_cpuidle_probe(struct platform_device *pdev) { int cpu_id, ret;
Use the cpuidle generic function 'cpuidle_register'. That saves us from some extra lines of code and unneeded variables.
A side effect of this change is a bug fix where before the cpuidle driver was registered for each_online_cpu and now it is for each_possible_cpu.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 9623a05..b7cd75b 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -59,8 +59,6 @@ #define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device); - /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ static void exynos4_set_wakeupmask(void) { @@ -211,8 +209,7 @@ static struct cpuidle_driver exynos4_idle_driver = {
static int exynos_cpuidle_probe(struct platform_device *pdev) { - int cpu_id, ret; - struct cpuidle_device *device; + int ret;
if (soc_is_exynos5250()) exynos5_core_down_clk(); @@ -220,23 +217,12 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) if (soc_is_exynos5440()) exynos4_idle_driver.state_count = 1;
- ret = cpuidle_register_driver(&exynos4_idle_driver); + ret = cpuidle_register(&exynos4_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n"); return ret; }
- for_each_online_cpu(cpu_id) { - device = &per_cpu(exynos4_cpuidle_device, cpu_id); - device->cpu = cpu_id; - - ret = cpuidle_register_device(device); - if (ret) { - dev_err(&pdev->dev, "failed to register cpuidle device\n"); - return ret; - } - } - return 0; }
The driver was initially written for exynos4 but the driver is used also for exynos5.
Change the function prefix name exynos4 -> exynos
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index b7cd75b..16e3325 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -60,7 +60,7 @@ #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ -static void exynos4_set_wakeupmask(void) +static void exynos_set_wakeupmask(void) { __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK); } @@ -91,13 +91,13 @@ static int idle_finisher(unsigned long flags) return 1; }
-static int exynos4_enter_core0_aftr(struct cpuidle_device *dev, +static int exynos_enter_core0_aftr(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { unsigned long tmp;
- exynos4_set_wakeupmask(); + exynos_set_wakeupmask();
/* Set value of power down register for aftr mode */ exynos_sys_powerdown_conf(SYS_AFTR); @@ -141,7 +141,7 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev, return index; }
-static int exynos4_enter_lowpower(struct cpuidle_device *dev, +static int exynos_enter_lowpower(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { @@ -154,7 +154,7 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev, if (new_index == 0) return arm_cpuidle_simple_enter(dev, drv, new_index); else - return exynos4_enter_core0_aftr(dev, drv, new_index); + return exynos_enter_core0_aftr(dev, drv, new_index); }
static void __init exynos5_core_down_clk(void) @@ -189,13 +189,13 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); }
-static struct cpuidle_driver exynos4_idle_driver = { - .name = "exynos4_idle", +static struct cpuidle_driver exynos_idle_driver = { + .name = "exynos_idle", .owner = THIS_MODULE, .states = { [0] = ARM_CPUIDLE_WFI_STATE, [1] = { - .enter = exynos4_enter_lowpower, + .enter = exynos_enter_lowpower, .exit_latency = 300, .target_residency = 100000, .flags = CPUIDLE_FLAG_TIME_VALID, @@ -215,9 +215,9 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) exynos5_core_down_clk();
if (soc_is_exynos5440()) - exynos4_idle_driver.state_count = 1; + exynos_idle_driver.state_count = 1;
- ret = cpuidle_register(&exynos4_idle_driver, NULL); + ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n"); return ret;
That makes the code cleaner and encapsulted. The function will be reused in the next patch.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/pm.c | 65 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 24 deletions(-)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 15af0ce..adfdf4b 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -103,6 +103,42 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) /* 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 @@ -162,17 +198,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; } @@ -196,19 +223,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 */
Move the code around to differentiate different section of code and prepare it to be factored out in the next patches.
The call order changed but hat doesn't have a side effect because they are independent. The important call is cpu_do_idle() which must be done the last.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 16e3325..cdfb1ae 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -87,7 +87,16 @@ static void restore_cpu_arch_register(void)
static int idle_finisher(unsigned long flags) { + exynos_set_wakeupmask(); + + __raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR); + __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG); + + /* Set value of power down register for aftr mode */ + exynos_sys_powerdown_conf(SYS_AFTR); + cpu_do_idle(); + return 1; }
@@ -97,14 +106,6 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, { unsigned long tmp;
- exynos_set_wakeupmask(); - - /* Set value of power down register for aftr mode */ - exynos_sys_powerdown_conf(SYS_AFTR); - - __raw_writel(virt_to_phys(exynos_cpu_resume), REG_DIRECTGO_ADDR); - __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG); - save_cpu_arch_register();
/* Setting Central Sequence Register for power down mode */
This function should be called only when the powerdown sequence fails.
Even if the current code does not hurt, by moving this line, we have the same code than the one in pm.c.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index cdfb1ae..6663349 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -134,11 +134,10 @@ static int exynos_enter_core0_aftr(struct cpuidle_device *dev, 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); }
- /* Clear wakeup state register */ - __raw_writel(0x0, S5P_WAKEUP_STAT); - return index; }
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 daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 24 ------------------------ arch/arm/mach-exynos/pm.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 6663349..7f1f4ef 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -65,26 +65,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(); @@ -106,8 +86,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; @@ -122,8 +100,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 adfdf4b..67d75fe 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/suspend.h> #include <linux/syscore_ops.h> +#include <linux/cpu_pm.h> #include <linux/io.h> #include <linux/irqchip/arm-gic.h> #include <linux/err.h> @@ -321,10 +322,38 @@ 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;
We make the cpuidle code less arch dependent.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 6 ------ arch/arm/mach-exynos/pm.c | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 7f1f4ef..ce31004 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -18,7 +18,6 @@ #include <linux/platform_device.h>
#include <asm/proc-fns.h> -#include <asm/smp_scu.h> #include <asm/suspend.h> #include <asm/unified.h> #include <asm/cpuidle.h> @@ -93,11 +92,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 67d75fe..aba577f 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -336,6 +336,10 @@ 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;
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 daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index aba577f..9773a00 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -244,7 +244,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: @@ -336,10 +336,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;
Let's encapsulate more the PM code inside the PM file by moving the 'exynos_set_wakeupmask' function inside the pm.c and the call in the cpu_pm notifier.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 7 ------- arch/arm/mach-exynos/pm.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index ce31004..01444ed 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -58,15 +58,8 @@ #define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
-/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ -static void exynos_set_wakeupmask(void) -{ - __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK); -} - static int idle_finisher(unsigned long flags) { - exynos_set_wakeupmask();
__raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR); __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG); diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 9773a00..c8b3dc4 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -322,6 +322,12 @@ static const struct platform_suspend_ops exynos_suspend_ops = { .valid = suspend_valid_only_mem, };
+/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ +static void exynos_set_wakeupmask(void) +{ + __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK); +} + static int exynos_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v) { @@ -331,6 +337,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, case CPU_PM_ENTER: if (cpu == 0) { exynos_cpu_save_register(); + exynos_set_wakeupmask(); } break;
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
Let's encapsulate more the PM code inside the PM file by moving the 'exynos_set_wakeupmask' function inside the pm.c and the call in the cpu_pm notifier.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/cpuidle.c | 7 ------- arch/arm/mach-exynos/pm.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index ce31004..01444ed 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -58,15 +58,8 @@ #define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
-/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ -static void exynos_set_wakeupmask(void) -{
- __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
-}
static int idle_finisher(unsigned long flags) {
exynos_set_wakeupmask();
__raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR); __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 9773a00..c8b3dc4 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -322,6 +322,12 @@ static const struct platform_suspend_ops exynos_suspend_ops = { .valid = suspend_valid_only_mem, };
+/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ +static void exynos_set_wakeupmask(void) +{
- __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
+}
- static int exynos_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v) {
@@ -331,6 +337,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, case CPU_PM_ENTER: if (cpu == 0) { exynos_cpu_save_register();
exynos_set_wakeupmask();
I'm not sure about this change.
Wake-up mask depends heavily on lower power state being entered, so CPU idle driver should be able to specify what mask to set. Of course currently the only state that requires this mask to be set is AFTR, but there are more states, such as LPA, which may need different value.
Best regards, Tomasz
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 daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 21 --------------------- arch/arm/mach-exynos/pm.c | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 01444ed..81d7197 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -76,31 +76,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 c8b3dc4..0e73591 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -184,15 +184,19 @@ 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;
/* Setting SEQ_OPTION register */
@@ -205,7 +209,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;
@@ -222,9 +226,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();
@@ -336,6 +348,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, switch (cmd) { case CPU_PM_ENTER: if (cpu == 0) { + exynos_pm_central_suspend(); exynos_cpu_save_register(); exynos_set_wakeupmask(); } @@ -346,6 +359,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; }
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
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 daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/cpuidle.c | 21 --------------------- arch/arm/mach-exynos/pm.c | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 25 deletions(-)
[snip]
-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;
Shouldn't exynos_pm_central_suspend() be called here in place of the code being moved to that function?
Best regards, Tomasz
On 04/09/2014 02:17 PM, Tomasz Figa wrote:
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
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 daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/cpuidle.c | 21 --------------------- arch/arm/mach-exynos/pm.c | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 25 deletions(-)
[snip]
-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;
Shouldn't exynos_pm_central_suspend() be called here in place of the code being moved to that function?
Right. Good catch !
Thanks
-- Daniel
Move the S5P_CHECK_AFTR definition to the header it belongs to.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 2 -- arch/arm/mach-exynos/regs-pmu.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 81d7197..cd27dbf 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -37,8 +37,6 @@ S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
-#define S5P_CHECK_AFTR 0xFCBA0D10 - #define EXYNOS5_PWR_CTRL1 (S5P_VA_CMU + 0x01020) #define EXYNOS5_PWR_CTRL2 (S5P_VA_CMU + 0x01024)
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 4f6a256..09c43c3 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -120,6 +120,7 @@ #define S5P_INT_LOCAL_PWR_EN 0x7
#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_AFTR 0xFCBA0D10
/* Only for EXYNOS4210 */ #define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
Move the S5P_CHECK_AFTR definition to the header it belongs to.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/cpuidle.c | 2 -- arch/arm/mach-exynos/regs-pmu.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 81d7197..cd27dbf 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -37,8 +37,6 @@ S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
-#define S5P_CHECK_AFTR 0xFCBA0D10
- #define EXYNOS5_PWR_CTRL1 (S5P_VA_CMU + 0x01020) #define EXYNOS5_PWR_CTRL2 (S5P_VA_CMU + 0x01024)
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 4f6a256..09c43c3 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -120,6 +120,7 @@ #define S5P_INT_LOCAL_PWR_EN 0x7
#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_AFTR 0xFCBA0D10
This is not really a PMU-specific value. It is not a part of the hardware programming interface, but rather a part of the kernel-bootloader ABI used to handle wake-up from low power states. Same applies to S5P_CHECK_SLEEP.
I believe the proper place for such definitions would be the source file using it, which after patch 14/17 would be pm.c.
Best regards, Tomasz
One more step is moving the clock ratio setting at idle time in pm.c
The macro names have been changed to be consistent with the other macros name in the file.
Note, the clock divider was working only when cpuidle was enabled because it was in its init routine. With this change, the clock divider is set in the pm's init routine, so it will also operate when the cpuidle driver is not set, which is good.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 54 --------------------------------------- arch/arm/mach-exynos/pm.c | 35 +++++++++++++++++++++++++ arch/arm/mach-exynos/regs-pmu.h | 19 ++++++++++++++ 3 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index cd27dbf..44d169b 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -37,25 +37,6 @@ S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \ (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
-#define EXYNOS5_PWR_CTRL1 (S5P_VA_CMU + 0x01020) -#define EXYNOS5_PWR_CTRL2 (S5P_VA_CMU + 0x01024) - -#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28) -#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16) -#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9) -#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8) -#define PWR_CTRL1_USE_CORE1_WFE (1 << 5) -#define PWR_CTRL1_USE_CORE0_WFE (1 << 4) -#define PWR_CTRL1_USE_CORE1_WFI (1 << 1) -#define PWR_CTRL1_USE_CORE0_WFI (1 << 0) - -#define PWR_CTRL2_DIV2_UP_EN (1 << 25) -#define PWR_CTRL2_DIV1_UP_EN (1 << 24) -#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16) -#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8) -#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) -#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0) - static int idle_finisher(unsigned long flags) {
@@ -97,38 +78,6 @@ static int exynos_enter_lowpower(struct cpuidle_device *dev, return exynos_enter_core0_aftr(dev, drv, new_index); }
-static void __init exynos5_core_down_clk(void) -{ - unsigned int tmp; - - /* - * Enable arm clock down (in idle) and set arm divider - * ratios in WFI/WFE state. - */ - tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \ - PWR_CTRL1_CORE1_DOWN_RATIO | \ - PWR_CTRL1_DIV2_DOWN_EN | \ - PWR_CTRL1_DIV1_DOWN_EN | \ - PWR_CTRL1_USE_CORE1_WFE | \ - PWR_CTRL1_USE_CORE0_WFE | \ - PWR_CTRL1_USE_CORE1_WFI | \ - PWR_CTRL1_USE_CORE0_WFI; - __raw_writel(tmp, EXYNOS5_PWR_CTRL1); - - /* - * Enable arm clock up (on exiting idle). Set arm divider - * ratios when not in idle along with the standby duration - * ratios. - */ - tmp = PWR_CTRL2_DIV2_UP_EN | \ - PWR_CTRL2_DIV1_UP_EN | \ - PWR_CTRL2_DUR_STANDBY2_VAL | \ - PWR_CTRL2_DUR_STANDBY1_VAL | \ - PWR_CTRL2_CORE2_UP_RATIO | \ - PWR_CTRL2_CORE1_UP_RATIO; - __raw_writel(tmp, EXYNOS5_PWR_CTRL2); -} - static struct cpuidle_driver exynos_idle_driver = { .name = "exynos_idle", .owner = THIS_MODULE, @@ -151,9 +100,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret;
- if (soc_is_exynos5250()) - exynos5_core_down_clk(); - if (soc_is_exynos5440()) exynos_idle_driver.state_count = 1;
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 0e73591..90fb692 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -140,6 +140,38 @@ static void exynos_cpu_restore_register(void) : "cc"); }
+static void __init exynos5_core_down_clk(void) +{ + unsigned int tmp; + + /* + * Enable arm clock down (in idle) and set arm divider + * ratios in WFI/WFE state. + */ + tmp = EXYNOS5_PWR_CTRL1_CORE2_DOWN_RATIO | \ + EXYNOS5_PWR_CTRL1_CORE1_DOWN_RATIO | \ + EXYNOS5_PWR_CTRL1_DIV2_DOWN_EN | \ + EXYNOS5_PWR_CTRL1_DIV1_DOWN_EN | \ + EXYNOS5_PWR_CTRL1_USE_CORE1_WFE | \ + EXYNOS5_PWR_CTRL1_USE_CORE0_WFE | \ + EXYNOS5_PWR_CTRL1_USE_CORE1_WFI | \ + EXYNOS5_PWR_CTRL1_USE_CORE0_WFI; + __raw_writel(tmp, EXYNOS5_PWR_CTRL1); + + /* + * Enable arm clock up (on exiting idle). Set arm divider + * ratios when not in idle along with the standby duration + * ratios. + */ + tmp = EXYNOS5_PWR_CTRL2_DIV2_UP_EN | \ + EXYNOS5_PWR_CTRL2_DIV1_UP_EN | \ + EXYNOS5_PWR_CTRL2_DUR_STANDBY2_VAL | \ + EXYNOS5_PWR_CTRL2_DUR_STANDBY1_VAL | \ + EXYNOS5_PWR_CTRL2_CORE2_UP_RATIO | \ + EXYNOS5_PWR_CTRL2_CORE1_UP_RATIO; + __raw_writel(tmp, EXYNOS5_PWR_CTRL2); +} + static int exynos_cpu_suspend(unsigned long arg) { #ifdef CONFIG_CACHE_L2X0 @@ -256,6 +288,9 @@ static void exynos_pm_resume(void)
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
+ if (soc_is_exynos5250()) + exynos5_core_down_clk(); + if (!soc_is_exynos5250()) scu_enable(S5P_VA_SCU);
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 09c43c3..ba5f038 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -314,4 +314,23 @@
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
+#define EXYNOS5_PWR_CTRL1 (S5P_VA_CMU + 0x01020) +#define EXYNOS5_PWR_CTRL2 (S5P_VA_CMU + 0x01024) + +#define EXYNOS5_PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28) +#define EXYNOS5_PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16) +#define EXYNOS5_PWR_CTRL1_DIV2_DOWN_EN (1 << 9) +#define EXYNOS5_PWR_CTRL1_DIV1_DOWN_EN (1 << 8) +#define EXYNOS5_PWR_CTRL1_USE_CORE1_WFE (1 << 5) +#define EXYNOS5_PWR_CTRL1_USE_CORE0_WFE (1 << 4) +#define EXYNOS5_PWR_CTRL1_USE_CORE1_WFI (1 << 1) +#define EXYNOS5_PWR_CTRL1_USE_CORE0_WFI (1 << 0) + +#define EXYNOS5_PWR_CTRL2_DIV2_UP_EN (1 << 25) +#define EXYNOS5_PWR_CTRL2_DIV1_UP_EN (1 << 24) +#define EXYNOS5_PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16) +#define EXYNOS5_PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8) +#define EXYNOS5_PWR_CTRL2_CORE2_UP_RATIO (1 << 4) +#define EXYNOS5_PWR_CTRL2_CORE1_UP_RATIO (1 << 0) + #endif /* __ASM_ARCH_REGS_PMU_H */
As usual, move the boot vector setting in the pm.c file and use the cpu_pm notifier to set it up.
Remove the unused headers.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/cpuidle.c | 23 ----------------------- arch/arm/mach-exynos/pm.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 44d169b..4b94181 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -8,46 +8,23 @@ * published by the Free Software Foundation. */
-#include <linux/kernel.h> -#include <linux/init.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/time.h> #include <linux/platform_device.h>
#include <asm/proc-fns.h> #include <asm/suspend.h> -#include <asm/unified.h> #include <asm/cpuidle.h>
#include <plat/cpu.h> -#include <plat/pm.h> - -#include <mach/map.h>
#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))
static int idle_finisher(unsigned long flags) { - - __raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR); - __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG); - /* Set value of power down register for aftr mode */ exynos_sys_powerdown_conf(SYS_AFTR); - cpu_do_idle(); - return 1; }
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 90fb692..e4ecd8c 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -172,6 +172,20 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); }
+#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)) + +static void exynos_cpu_set_boot_vector(void) +{ + __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR); + __raw_writel(S5P_CHECK_AFTR, EXYNOS_BOOT_VECTOR_FLAG); +} + static int exynos_cpu_suspend(unsigned long arg) { #ifdef CONFIG_CACHE_L2X0 @@ -387,6 +401,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, exynos_cpu_save_register(); exynos_set_wakeupmask(); } + exynos_cpu_set_boot_vector(); break;
case CPU_PM_EXIT:
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
As usual, move the boot vector setting in the pm.c file and use the cpu_pm notifier to set it up.
Remove the unused headers.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/cpuidle.c | 23 ----------------------- arch/arm/mach-exynos/pm.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 44d169b..4b94181 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -8,46 +8,23 @@
- published by the Free Software Foundation.
*/
-#include <linux/kernel.h> -#include <linux/init.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/time.h> #include <linux/platform_device.h>
#include <asm/proc-fns.h> #include <asm/suspend.h> -#include <asm/unified.h> #include <asm/cpuidle.h>
#include <plat/cpu.h> -#include <plat/pm.h>
-#include <mach/map.h>
#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))
static int idle_finisher(unsigned long flags) {
__raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR);
__raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
/* Set value of power down register for aftr mode */ exynos_sys_powerdown_conf(SYS_AFTR);
cpu_do_idle();
return 1; }
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 90fb692..e4ecd8c 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -172,6 +172,20 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); }
+#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))
+static void exynos_cpu_set_boot_vector(void) +{
- __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
- __raw_writel(S5P_CHECK_AFTR, EXYNOS_BOOT_VECTOR_FLAG);
S5P_CHECK_AFTR is a value specific for AFTR state. I wonder if it wouldn't be desired to let the cpuidle driver somehow affect the value written here.
+}
- static int exynos_cpu_suspend(unsigned long arg) { #ifdef CONFIG_CACHE_L2X0
@@ -387,6 +401,7 @@ static int exynos_cpu_pm_notifier(struct notifier_block *self, exynos_cpu_save_register(); exynos_set_wakeupmask(); }
exynos_cpu_set_boot_vector();
Why this is outside of the if above? Should this really be called for all CPUs?
Best regards, Tomasz
There is no point to register the cpuidle driver for the 5440 as it has only one WFI state which is the default idle function when the cpuidle driver is disabled.
By disabling cpuidle we prevent to enter to the governor computation for nothing, thus saving a lot of processing time.
The only drawback is the statistic via sysfs on this state which is lost but it is meaningless and it could be retrieved from the ftrace easily.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- arch/arm/mach-exynos/cpuidle.c | 5 ----- arch/arm/mach-exynos/exynos.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 4b94181..a1f111e 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -16,8 +16,6 @@ #include <asm/suspend.h> #include <asm/cpuidle.h>
-#include <plat/cpu.h> - #include "common.h"
static int idle_finisher(unsigned long flags) @@ -77,9 +75,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret;
- if (soc_is_exynos5440()) - exynos_idle_driver.state_count = 1; - ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n"); diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b567361..fe8dac8 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -227,6 +227,9 @@ static struct platform_device exynos_cpuidle = {
void __init exynos_cpuidle_init(void) { + if (soc_is_exynos5440()) + return; + platform_device_register(&exynos_cpuidle); }
On Tue, Apr 8, 2014 at 5:49 PM, Daniel Lezcano daniel.lezcano@linaro.orgwrote:
There is no point to register the cpuidle driver for the 5440 as it has only one WFI state which is the default idle function when the cpuidle driver is disabled.
By disabling cpuidle we prevent to enter to the governor computation for nothing, thus saving a lot of processing time.
The only drawback is the statistic via sysfs on this state which is lost but it is meaningless and it could be retrieved from the ftrace easily.
So for the future, you'll only merge platform drivers that enable something more than WFI?
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org
In that case, Acked-by: Amit Kucheria amit.kucheria@linaro.org
arch/arm/mach-exynos/cpuidle.c | 5 ----- arch/arm/mach-exynos/exynos.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 4b94181..a1f111e 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -16,8 +16,6 @@ #include <asm/suspend.h> #include <asm/cpuidle.h>
-#include <plat/cpu.h>
#include "common.h"
static int idle_finisher(unsigned long flags) @@ -77,9 +75,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret;
if (soc_is_exynos5440())
exynos_idle_driver.state_count = 1;
ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n");
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b567361..fe8dac8 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -227,6 +227,9 @@ static struct platform_device exynos_cpuidle = {
void __init exynos_cpuidle_init(void) {
if (soc_is_exynos5440())
return;
platform_device_register(&exynos_cpuidle);
}
-- 1.7.9.5
linaro-kernel mailing list linaro-kernel@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-kernel
On 04/08/2014 02:51 PM, Amit Kucheria wrote:
On Tue, Apr 8, 2014 at 5:49 PM, Daniel Lezcano <daniel.lezcano@linaro.org mailto:daniel.lezcano@linaro.org> wrote:
There is no point to register the cpuidle driver for the 5440 as it has only one WFI state which is the default idle function when the cpuidle driver is disabled. By disabling cpuidle we prevent to enter to the governor computation for nothing, thus saving a lot of processing time. The only drawback is the statistic via sysfs on this state which is lost but it is meaningless and it could be retrieved from the ftrace easily.
So for the future, you'll only merge platform drivers that enable something more than WFI?
Well, I already picked up a driver with only WFI because I knew the next idle states were in preparation. But adding a cpuidle driver just for WFI is no sense and if, for a reason I missed, it is really needed, I guess a generic WFI cpuidle driver for all platforms would be make much more sense.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org <mailto:daniel.lezcano@linaro.org>>
In that case, Acked-by: Amit Kucheria <amit.kucheria@linaro.org mailto:amit.kucheria@linaro.org>
--- arch/arm/mach-exynos/cpuidle.c | 5 ----- arch/arm/mach-exynos/exynos.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 4b94181..a1f111e 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -16,8 +16,6 @@ #include <asm/suspend.h> #include <asm/cpuidle.h> -#include <plat/cpu.h> - #include "common.h" static int idle_finisher(unsigned long flags) @@ -77,9 +75,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret; - if (soc_is_exynos5440()) - exynos_idle_driver.state_count = 1; - ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n"); diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b567361..fe8dac8 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -227,6 +227,9 @@ static struct platform_device exynos_cpuidle = { void __init exynos_cpuidle_init(void) { + if (soc_is_exynos5440()) + return; + platform_device_register(&exynos_cpuidle); } -- 1.7.9.5 _______________________________________________ linaro-kernel mailing list linaro-kernel@lists.linaro.org <mailto:linaro-kernel@lists.linaro.org> http://lists.linaro.org/mailman/listinfo/linaro-kernel
On Tue, 8 Apr 2014, Daniel Lezcano wrote:
On 04/08/2014 02:51 PM, Amit Kucheria wrote:
On Tue, Apr 8, 2014 at 5:49 PM, Daniel Lezcano <daniel.lezcano@linaro.org mailto:daniel.lezcano@linaro.org> wrote:
There is no point to register the cpuidle driver for the 5440 as it has only one WFI state which is the default idle function when the cpuidle driver is disabled. By disabling cpuidle we prevent to enter to the governor computation for nothing, thus saving a lot of processing time. The only drawback is the statistic via sysfs on this state which is lost but it is meaningless and it could be retrieved from the ftrace easily.
So for the future, you'll only merge platform drivers that enable something more than WFI?
Well, I already picked up a driver with only WFI because I knew the next idle states were in preparation. But adding a cpuidle driver just for WFI is no sense and if, for a reason I missed, it is really needed, I guess a generic WFI cpuidle driver for all platforms would be make much more sense.
Better relegate WFI-only configurations to arch_cpu_idle().
Nicolas
No more dependency on the arch code. The platform_data field is used to set the PM callback as the other cpuidle drivers.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/cpuidle.c | 6 ++++-- arch/arm/mach-exynos/exynos.c | 5 +++-- arch/arm/mach-exynos/pmu.c | 6 ++++++ 4 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 9ef3f83..7d9432e 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -62,5 +62,6 @@ struct exynos_pmu_conf { };
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); +extern void exynos_sys_powerdown_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 a1f111e..25d2fad 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -16,12 +16,12 @@ #include <asm/suspend.h> #include <asm/cpuidle.h>
-#include "common.h" +static void (*exynos_aftr)(void);
static int idle_finisher(unsigned long flags) { /* Set value of power down register for aftr mode */ - exynos_sys_powerdown_conf(SYS_AFTR); + exynos_aftr(); cpu_do_idle(); return 1; } @@ -75,6 +75,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret;
+ exynos_aftr = (void *)(pdev->dev.platform_data); + ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n"); diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index fe8dac8..a7ab561 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -221,8 +221,9 @@ void exynos_restart(enum reboot_mode mode, const char *cmd) }
static struct platform_device exynos_cpuidle = { - .name = "exynos_cpuidle", - .id = -1, + .name = "exynos_cpuidle", + .dev.platform_data = exynos_sys_powerdown_aftr, + .id = -1, };
void __init exynos_cpuidle_init(void) diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 05c7ce1..fd1ae22 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -389,6 +389,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) } }
+/* Set value of power down register for aftr mode */ +void exynos_sys_powerdown_aftr(void) +{ + exynos_sys_powerdown_conf(SYS_AFTR); +} + static int __init exynos_pmu_init(void) { unsigned int value;
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
No more dependency on the arch code. The platform_data field is used to set the PM callback as the other cpuidle drivers.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/cpuidle.c | 6 ++++-- arch/arm/mach-exynos/exynos.c | 5 +++-- arch/arm/mach-exynos/pmu.c | 6 ++++++ 4 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 9ef3f83..7d9432e 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -62,5 +62,6 @@ struct exynos_pmu_conf { };
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); +extern void exynos_sys_powerdown_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 a1f111e..25d2fad 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -16,12 +16,12 @@ #include <asm/suspend.h> #include <asm/cpuidle.h>
-#include "common.h" +static void (*exynos_aftr)(void);
static int idle_finisher(unsigned long flags) { /* Set value of power down register for aftr mode */
- exynos_sys_powerdown_conf(SYS_AFTR);
- exynos_aftr(); cpu_do_idle(); return 1; }
@@ -75,6 +75,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) { int ret;
- exynos_aftr = (void *)(pdev->dev.platform_data);
- ret = cpuidle_register(&exynos_idle_driver, NULL); if (ret) { dev_err(&pdev->dev, "failed to register cpuidle driver\n");
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index fe8dac8..a7ab561 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -221,8 +221,9 @@ void exynos_restart(enum reboot_mode mode, const char *cmd) }
static struct platform_device exynos_cpuidle = {
- .name = "exynos_cpuidle",
- .id = -1,
.name = "exynos_cpuidle",
.dev.platform_data = exynos_sys_powerdown_aftr,
.id = -1, };
void __init exynos_cpuidle_init(void)
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 05c7ce1..fd1ae22 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -389,6 +389,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) } }
+/* Set value of power down register for aftr mode */ +void exynos_sys_powerdown_aftr(void) +{
- exynos_sys_powerdown_conf(SYS_AFTR);
I wonder if this callback wouldn't be more appropriate for setting idle mode specific things like wake-up mask and boot flag.
Best regards, Tomasz
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Reviewed-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com --- arch/arm/mach-exynos/Makefile | 1 - drivers/cpuidle/Kconfig.arm | 6 ++++++ drivers/cpuidle/Makefile | 1 + .../cpuidle.c => drivers/cpuidle/cpuidle-exynos.c | 0 4 files changed, 7 insertions(+), 1 deletion(-) rename arch/arm/mach-exynos/cpuidle.c => drivers/cpuidle/cpuidle-exynos.c (100%)
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index a656dbe..21bd364 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_ARCH_EXYNOS) += exynos.o
obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_EXYNOS) += pmu.o
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index d988948..364c984 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -44,3 +44,9 @@ config ARM_AT91_CPUIDLE depends on ARCH_AT91 help Select this to enable cpuidle for AT91 processors + +config ARM_EXYNOS_CPUIDLE + bool "Cpu Idle Driver for the Exynos processors" + depends on ARCH_EXYNOS + help + Select this to enable cpuidle for Exynos processors diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index f71ae1b..0d1540a 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o +obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o
############################################################################### # POWERPC drivers diff --git a/arch/arm/mach-exynos/cpuidle.c b/drivers/cpuidle/cpuidle-exynos.c similarity index 100% rename from arch/arm/mach-exynos/cpuidle.c rename to drivers/cpuidle/cpuidle-exynos.c
Hi Daniel,
On 08.04.2014 14:19, Daniel Lezcano wrote:
Changelog:
V3:
- Added patch : "ARM: exynos: cpuidle: Disable cpuidle for 5440"
- Removed patch : "ARM: exynos: config: Enable cpuidle"
- Removed default ARM_EXYNOS4210_CPUIDLE=y
- Added comment about bug fix side effect 'for_each_possible_cpu'
V2:
- Added comment in changelog for calls order (5/17)
- Call the powerdown only for cpu0 in the pm notifier
- Set the pm notifier for all boards
V1: initial post
This patchset relies on the cpm_pm notifier to initiate the powerdown sequence operations from pm.c instead cpuidle.c. Thus the cpuidle driver is no longer dependent from arch specific code as everything is called from the pm.c file.
The patchset applies on top of linux-samsung/for-next.
Tested on exynos4: 4210 Tested on exynos5: 5250 (without AFTR)
Daniel Lezcano (17): ARM: exynos: cpuidle: Prevent forward declaration ARM: exynos: cpuidle: use cpuidle_register ARM: exynos: cpuidle: change function name prefix ARM: exynos: cpuidle: encapsulate register access inside a function ARM: exynos: cpuidle: Move some code inside the idle_finisher ARM: exynos: cpuidle: Fix S5P_WAKEUP_STAT call ARM: exynos: cpuidle: Use the cpu_pm notifier ARM: exynos: cpuidle: Move scu_enable in the cpu_pm notifier ARM: exynos: cpuidle: Remove ifdef for scu_enable ARM: exynos: cpuidle: Move exynos_set_wakeupmask in the cpu_pm notifier ARM: exynos: cpuidle: Move the power sequence call in the cpu_pm notifier ARM: exynos: cpuidle: Move S5P_CHECK_AFTR in a header ARM: exynos: cpuidle: Move clock setup to pm.c ARM: exynos: cpuidle: Move the boot vector in pm.c ARM: exynos: cpuidle: Disable cpuidle for 5440 ARM: exynos: cpuidle: Pass the AFTR callback to the platform_data ARM: exynos: cpuidle: Move the driver to drivers/cpuidle directory
arch/arm/mach-exynos/Makefile | 1 - arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/cpuidle.c | 255 -------------------------------------- arch/arm/mach-exynos/exynos.c | 8 +- arch/arm/mach-exynos/pm.c | 177 +++++++++++++++++++++----- arch/arm/mach-exynos/pmu.c | 6 + arch/arm/mach-exynos/regs-pmu.h | 20 +++ drivers/cpuidle/Kconfig.arm | 6 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-exynos.c | 97 +++++++++++++++ 10 files changed, 285 insertions(+), 287 deletions(-) delete mode 100644 arch/arm/mach-exynos/cpuidle.c create mode 100644 drivers/cpuidle/cpuidle-exynos.c
For all patches except 10-12, 14 and 16:
Reviewed-by: Tomasz Figa t.figa@samsung.com
-- Best regards, Tomasz
linaro-kernel@lists.linaro.org