Re: [PATCH V3 2/5] ARM: tegra20: cpuidle: add powered-down state for secondary CPU
From: Joseph Lo <hidden>
Date: 2012-12-18 03:06:45
Also in:
linux-arm-kernel
On Tue, 2012-12-18 at 10:46 +0800, Colin Cross wrote:
On Mon, Dec 17, 2012 at 6:30 PM, Joseph Lo [off-list ref] wrote:quoted
The powered-down state of Tegra20 requires power gating both CPU cores. When the secondary CPU requests to enter powered-down state, it saves its own contexts and then enters WFI. The Tegra20 had a limition to power down both CPU cores. The secondary CPU must waits for CPU0 in powered-down state too. If the secondary CPU be woken up before CPU0 entering powered-down state, then it needs to restore its CPU states and waits for next chance. Be aware of that, you may see the legacy power state "LP2" in the code which is exactly the same meaning of "CPU power down". Based on the work by: Colin Cross [off-list ref] Gary King [off-list ref] Signed-off-by: Joseph Lo <redacted> --- V3: * dynamic checking of the number of the state counts * fix the code sequence for aborting cpu_suspend in tegra20_sleep_cpu_secondary_finish V2: * no change --- arch/arm/mach-tegra/cpuidle-tegra20.c | 94 ++++++++++++++++++++- arch/arm/mach-tegra/pm.c | 2 + arch/arm/mach-tegra/sleep-tegra20.S | 147 +++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/sleep.h | 23 +++++ 4 files changed, 261 insertions(+), 5 deletions(-)diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index d32e8b0..716aef3 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c +static int __cpuinit tegra20_idle_lp2(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; + bool entered_lp2 = false; + + local_fiq_disable(); + + tegra_set_cpu_in_lp2(cpu); + cpu_pm_enter();You must check the return value from cpu_pm_enter and synchronize and abort both cpus.
Please check the sequence in last patch. Although it used the API that be provided by patch 1 to check the pending sgi.
quoted
+ + if (cpu == 0) + cpu_do_idle(); + else + entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index); + + cpu_pm_exit(); + tegra_clear_cpu_in_lp2(cpu); + + local_fiq_enable(); + + smp_rmb(); + + return entered_lp2 ? index : 0; +} +#endif + int __init tegra20_cpuidle_init(void) { - int ret; + int ret, i; unsigned int cpu; struct cpuidle_device *dev; struct cpuidle_driver *drv = &tegra_idle_driver; + drv->state_count = sizeof(tegra_idle_states) / + sizeof(struct cpuidle_state); + for (i = 0; i < drv->state_count; i++) + memcpy(&drv->states[i], &tegra_idle_states[i], + sizeof(struct cpuidle_state)); + ret = cpuidle_register_driver(&tegra_idle_driver); if (ret) { pr_err("CPUidle driver registration failed\n");Is there a call to cpu_cluster_pm_enter/exit somewhere else?
Yes, there is. Please check the fuction "tegra_idle_lp2_last" in "pm.c", because it's a common code of "powered-down" idle state for CPU0 on Tegra20 & Tegra30. Thanks, Joseph