"ext Rajendra Nayak" <[EMAIL PROTECTED]> writes:

> Hi,
>
> The following patches define and enable all of the below mentioned C states 
> for OMAP3. 
> These are tested with a minimal kernel config on OMAP3430sdp as most drivers 
> today don't have context save/restore in place and
> some even lack aggresive clock handling. 
> These apply on top of the workaround patch set submitted by Jouni. 
> ([PATCH 0/6] 34XX: PM: Workarounds to get omap3 to retention 4th.)
>
> The following is neccessay even with a minimal config to achieve OFF.
>  $ echo 1 > /sys/power/sleep_while_idle
>  $ echo 1 > /sys/power/clocks_off_while_idle
>   
> The following C states are defined
> C0 - System executing code
> C1 - MPU WFI + Core active
> C2 - MPU CSWR + Core active
> C3 - MPU OFF + Core active
> C4 - MPU CSWR + Core CSWR
> C5 - MPU OFF + Core CSWR
> C6 - MPU OFF + Core OFF
>  
> regards,
> Rajendra

One more general comment on these patches as I looked at the code
after applying them.

Most of the code in omap3_enter_idle in cpuidle34xx.c could be shared
between suspend/pm_idle/cpuidle. I would do these changes to share
this code between these three things:

1. read mpu_pd pwrst, neon_pd pwrst, core_pd pwrst values in
   omap_sram_idle in pm34xx.c

2. Move all the logic from omap3_enter_idle to omap_sram_idle. Use
   values read in previous step to decide wether ctx savings/restores
   are needed, what should be written to neon_pd next_pwrst, wether
   omap2_gpio_prepare_for/resume_after_retention is needed, wether to
   disable/enable serial and gpio clocks.

Basically what is left into omap3_enter_idle is writing next pwrsts
and cpuidle related stuff, something like this:

static int omap3_enter_idle(struct cpuidle_device *dev,
                        struct cpuidle_state *state)
{
        struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
        struct timespec ts_preidle, ts_postidle, ts_idle;
        struct powerdomain *mpu_pd, *core_pd;

        current_cx_state = *cx;

        if (cx->type == OMAP3_STATE_C0) {
                /* Do nothing for C0, not even a wfi */
                return 0;
        }

        local_irq_disable();
        local_fiq_disable();

        /* Used to keep track of the total time in idle */
        getnstimeofday(&ts_preidle);

        if (cx->type > OMAP3_STATE_C1)
                sched_clock_idle_sleep_event(); /* about to enter deep idle */

        mpu_pd = pwrdm_lookup("mpu_pwrdm");
        core_pd = pwrdm_lookup("core_pwrdm");

        pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state);
        pwrdm_set_next_pwrst(core_pd, cx->core_state);

        if (omap_irq_pending())
                goto return_sleep_time;

        /* Execute ARM wfi */
        omap_sram_idle();

return_sleep_time:
        getnstimeofday(&ts_postidle);
        ts_idle = timespec_sub(ts_postidle, ts_preidle);

        if (cx->type > OMAP3_STATE_C1)
                sched_clock_idle_wakeup_event(timespec_to_ns(&ts_idle));

        local_irq_enable();
        local_fiq_disable();

        return (u32)timespec_to_ns(&ts_idle)/1000;
}

If this is not done, we need to copy paste code from omap3_enter_idle
into suspend code anyway if we want to use offmode in it. It would be
more nice to have one funcion with this logic shared between
suspend/pm_idle/cpuidle rather than two or even three copies of it.

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to