[PATCH V3 2/5] ARM: tegra20: cpuidle: add powered-down state for secondary CPU

Joseph Lo josephl at nvidia.com
Mon Dec 17 22:06:45 EST 2012


On Tue, 2012-12-18 at 10:46 +0800, Colin Cross wrote:
> On Mon, Dec 17, 2012 at 6:30 PM, Joseph Lo <josephl at nvidia.com> wrote:
> > 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 <ccross at android.com>
> > Gary King <gking at nvidia.com>
> >
> > Signed-off-by: Joseph Lo <josephl at nvidia.com>
> > ---
> > 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. 

> > +
> > +       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




More information about the linux-arm-kernel mailing list