Thara Gopinath <th...@ti.com> writes:

> This patch adds Open SWitch Retention (OSWR) support for
> MPU/CORE domains in Cpuidle. In addition to the normal
> power domain retention(Closed SWitch retention) in OSWR,
> the powerdomain logic is turned OFF. Power domain memory
> banks can be chosen to be retained or turned off. In this
> implementation both MPU and Core domain memory banks are
> turned off during OSWR.
> This patch also adds counters ret_logic_off_counter and
> ret_mem_off_counter for each power domain. This keeps track
> of power domain logic and memory off during powerdomain
> retention. These counters together with the retention counter
> can be used to find out whether a power domain has entered
> OSWR or not. In case of OSWR both the retention counter and
> ret_logic_off_counter will get incremented. ret_mem_off_counter
> will get incremented if memory bank off during retention
> is implemented. In this implementation in case of core or mpu
> domain entering OSWR all three flags will be incremented. In
> case of normal retention or CSWR only the retention counter
> will be incremented
>
> To support this feature two new C states are being added to
> the existing C states which makes the new states look like below.
>
>         C1 - MPU WFI + Core active
>         C2 - MPU WFI + Core inactive
>         C3 - MPU CSWR + Core inactive
>         C4 - MPU OFF + Core inactive
>         C5 - MPU CSWR + Core CSWR
>         C6 - MPU OFF + Core CSWR
>         C7 - MPU OSWR + CORE OSWR (New State)
>         C8 - MPU OFF + CORE OSWR  (New State)
>         C9 - MPU OFF + CORE OFF
>
> Signed-off-by: Thara Gopinath <th...@ti.com>
> ---
>  arch/arm/mach-omap2/board-3430sdp.c           |    4 +
>  arch/arm/mach-omap2/cpuidle34xx.c             |  129 
> +++++++++++++++++++++++--
>  arch/arm/mach-omap2/pm-debug.c                |    3 +
>  arch/arm/mach-omap2/pm34xx.c                  |   55 +++++++++--
>  arch/arm/mach-omap2/powerdomain.c             |   13 +++
>  arch/arm/mach-omap2/sleep34xx.S               |    4 +
>  arch/arm/plat-omap/include/plat/powerdomain.h |    2 +
>  7 files changed, 194 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-3430sdp.c 
> b/arch/arm/mach-omap2/board-3430sdp.c
> index 7d68445..071cf22 100644
> --- a/arch/arm/mach-omap2/board-3430sdp.c
> +++ b/arch/arm/mach-omap2/board-3430sdp.c
> @@ -72,6 +72,10 @@ static struct cpuidle_params omap3_cpuidle_params_table[] 
> = {
>       /* C6 */
>       {1, 3000, 8500, 15000},
>       /* C7 */
> +     {1, 4000, 10000, 150000},
> +     /* C8 */
> +     {1, 8000, 25000, 250000},
> +     /* C9 */
>       {1, 10000, 30000, 300000},
>  };
>  
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
> b/arch/arm/mach-omap2/cpuidle34xx.c
> index 1cfa5a6..419f683 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -36,14 +36,16 @@
>  
>  #ifdef CONFIG_CPU_IDLE
>  
> -#define OMAP3_MAX_STATES 7
> +#define OMAP3_MAX_STATES 9
>  #define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */
>  #define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */
>  #define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */
>  #define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */
> -#define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */
> -#define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */
> -#define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */
> +#define OMAP3_STATE_C5 4 /* C5 - MPU CSWR + Core CSWR */
> +#define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core CSWR */
> +#define OMAP3_STATE_C7 6 /* C7 - MPU OSWR + Core OSWR */
> +#define OMAP3_STATE_C8 7 /* C8 - MPU OFF + Core OSWR */
> +#define OMAP3_STATE_C9 8 /* C9 - MPU OFF + CORE OFF */
>  
>  struct omap3_processor_cx {
>       u8 valid;
> @@ -52,6 +54,11 @@ struct omap3_processor_cx {
>       u32 wakeup_latency;
>       u32 mpu_state;
>       u32 core_state;
> +     u32 mpu_logicl1_ret_state;
> +     u32 mpu_l2cache_ret_state;
> +     u32 core_logic_state;
> +     u32 core_mem1_ret_state;
> +     u32 core_mem2_ret_state;
>       u32 threshold;
>       u32 flags;
>  };
> @@ -81,6 +88,10 @@ static struct cpuidle_params cpuidle_params_table[] = {
>       /* C6 */
>       {1, 3000, 8500, 15000},
>       /* C7 */
> +     {1, 4000, 10000, 150000},
> +     /* C8 */
> +     {1, 8000, 25000, 250000},
> +     /* C9 */
>       {1, 10000, 30000, 300000},
>  };
>  
> @@ -119,6 +130,11 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>       struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
>       struct timespec ts_preidle, ts_postidle, ts_idle;
>       u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
> +     u32 mpu_logicl1_ret_state = cx->mpu_logicl1_ret_state;
> +     u32 mpu_l2cache_ret_state = cx->mpu_l2cache_ret_state;
> +     u32 core_logic_state = cx->core_logic_state;
> +     u32 core_mem1_ret_state = cx->core_mem1_ret_state;
> +     u32 core_mem2_ret_state = cx->core_mem2_ret_state;
>  
>       current_cx_state = *cx;
>  
> @@ -135,6 +151,20 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>                       core_state = PWRDM_POWER_RET;
>       }
>  
> +     /* For any state above inactive set the logic and memory retention
> +      * bits in case the powerdomain enters retention
> +      */
> +     if (mpu_state <= PWRDM_POWER_RET) {
> +             pwrdm_set_logic_retst(mpu_pd, mpu_logicl1_ret_state);
> +             pwrdm_set_mem_retst(mpu_pd, 0, mpu_l2cache_ret_state);
> +     }
> +
> +     if (core_state <= PWRDM_POWER_RET) {
> +             pwrdm_set_logic_retst(core_pd, core_logic_state);
> +             pwrdm_set_mem_retst(core_pd, 0, core_mem1_ret_state);
> +             pwrdm_set_mem_retst(core_pd, 1, core_mem2_ret_state);
> +     }
> +
>       pwrdm_set_next_pwrst(mpu_pd, mpu_state);
>       pwrdm_set_next_pwrst(core_pd, core_state);
>  
> @@ -217,7 +247,7 @@ void omap3_pm_init_cpuidle(struct cpuidle_params 
> *cpuidle_board_params)
>   *   C3 . MPU CSWR + Core inactive
>   *   C4 . MPU OFF + Core inactive
>   *   C5 . MPU CSWR + Core CSWR
> - *   C6 . MPU OFF + Core CSWR
> + *   C6 . MPU OFF + Core OSWR
>   *   C7 . MPU OFF + Core OFF
>   */
>  void omap_init_power_states(void)
> @@ -262,6 +292,10 @@ void omap_init_power_states(void)
>                       cpuidle_params_table[OMAP3_STATE_C3].threshold;
>       omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
> +     omap3_power_states[OMAP3_STATE_C3].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C3].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
>                               CPUIDLE_FLAG_CHECK_BM;
>  
> @@ -277,6 +311,10 @@ void omap_init_power_states(void)
>                       cpuidle_params_table[OMAP3_STATE_C4].threshold;
>       omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
>       omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
> +     omap3_power_states[OMAP3_STATE_C4].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C4].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
>                               CPUIDLE_FLAG_CHECK_BM;
>  
> @@ -292,6 +330,15 @@ void omap_init_power_states(void)
>                       cpuidle_params_table[OMAP3_STATE_C5].threshold;
>       omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C5].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C5].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C5].core_logic_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C5].core_mem1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C5].core_mem2_ret_state =
> +                             PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
>                               CPUIDLE_FLAG_CHECK_BM;
>  
> @@ -307,10 +354,19 @@ void omap_init_power_states(void)
>                       cpuidle_params_table[OMAP3_STATE_C6].threshold;
>       omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF;
>       omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C6].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C6].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C6].core_logic_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C6].core_mem1_ret_state =
> +                             PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C6].core_mem2_ret_state =
> +                             PWRDM_POWER_RET;
>       omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
>                               CPUIDLE_FLAG_CHECK_BM;
>  
> -     /* C7 . MPU OFF + Core OFF */
> +     /* C7 . MPU OSWR + Core OSWR */
>       omap3_power_states[OMAP3_STATE_C7].valid =
>                       cpuidle_params_table[OMAP3_STATE_C7].valid;
>       omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7;
> @@ -320,10 +376,67 @@ void omap_init_power_states(void)
>                       cpuidle_params_table[OMAP3_STATE_C7].wake_latency;
>       omap3_power_states[OMAP3_STATE_C7].threshold =
>                       cpuidle_params_table[OMAP3_STATE_C7].threshold;
> -     omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF;
> -     omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C7].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C7].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C7].core_logic_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C7].core_mem1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C7].core_mem2_ret_state =
> +                             PWRDM_POWER_OFF;
>       omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
>                               CPUIDLE_FLAG_CHECK_BM;
> +
> +     /* C8 . MPU OFF + Core OSWR */
> +     omap3_power_states[OMAP3_STATE_C8].valid =
> +                     cpuidle_params_table[OMAP3_STATE_C8].valid;
> +     omap3_power_states[OMAP3_STATE_C8].type = OMAP3_STATE_C8;
> +     omap3_power_states[OMAP3_STATE_C8].sleep_latency =
> +                     cpuidle_params_table[OMAP3_STATE_C8].sleep_latency;
> +     omap3_power_states[OMAP3_STATE_C8].wakeup_latency =
> +                     cpuidle_params_table[OMAP3_STATE_C8].wake_latency;
> +     omap3_power_states[OMAP3_STATE_C8].threshold =
> +                     cpuidle_params_table[OMAP3_STATE_C8].threshold;
> +     omap3_power_states[OMAP3_STATE_C8].mpu_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].core_state = PWRDM_POWER_RET;
> +     omap3_power_states[OMAP3_STATE_C8].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].core_logic_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].core_mem1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].core_mem2_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C8].flags = CPUIDLE_FLAG_TIME_VALID |
> +                             CPUIDLE_FLAG_CHECK_BM;
> +
> +     /* C9 . MPU OFF + Core OFF */
> +     omap3_power_states[OMAP3_STATE_C9].valid =
> +                     cpuidle_params_table[OMAP3_STATE_C9].valid;
> +     omap3_power_states[OMAP3_STATE_C9].type = OMAP3_STATE_C9;
> +     omap3_power_states[OMAP3_STATE_C9].sleep_latency =
> +                     cpuidle_params_table[OMAP3_STATE_C9].sleep_latency;
> +     omap3_power_states[OMAP3_STATE_C9].wakeup_latency =
> +                     cpuidle_params_table[OMAP3_STATE_C9].wake_latency;
> +     omap3_power_states[OMAP3_STATE_C9].threshold =
> +                     cpuidle_params_table[OMAP3_STATE_C9].threshold;
> +     omap3_power_states[OMAP3_STATE_C9].mpu_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].core_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].mpu_logicl1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].mpu_l2cache_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].core_logic_state = PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].core_mem1_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].core_mem2_ret_state =
> +                             PWRDM_POWER_OFF;
> +     omap3_power_states[OMAP3_STATE_C9].flags = CPUIDLE_FLAG_TIME_VALID |
> +                             CPUIDLE_FLAG_CHECK_BM;
>  }
>  
>  struct cpuidle_driver omap3_idle_driver = {
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index 85a8c6e..035cfa7 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -385,6 +385,9 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
> *pwrdm, void *user)
>       for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
>               seq_printf(s, ",%s:%d", pwrdm_state_names[i],
>                       pwrdm->state_counter[i]);
> +     seq_printf(s, ",RET-LOGIC-OFF:%d,RET-MEM-OFF:%d",
> +                     pwrdm->ret_logic_off_counter,
> +                     pwrdm->ret_mem_off_counter);
>  
>       seq_printf(s, "\n");
>  
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 6e6d954..bfdcac2 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -384,7 +384,8 @@ void omap_sram_idle(void)
>       int mpu_next_state = PWRDM_POWER_ON;
>       int per_next_state = PWRDM_POWER_ON;
>       int core_next_state = PWRDM_POWER_ON;
> -     int core_prev_state, per_prev_state;
> +     int mpu_prev_state, core_prev_state, per_prev_state;
> +     int mpu_logic_state, mpu_mem_state, core_logic_state;
>       u32 sdrc_pwr = 0;
>       int per_state_modified = 0;
>  
> @@ -397,12 +398,25 @@ void omap_sram_idle(void)
>       pwrdm_clear_all_prev_pwrst(per_pwrdm);
>  
>       mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
> +     mpu_logic_state = pwrdm_read_next_logic_pwrst(mpu_pwrdm);
> +     mpu_mem_state = pwrdm_read_next_mem_pwrst(mpu_pwrdm, 0);
> +
>       switch (mpu_next_state) {
>       case PWRDM_POWER_ON:
> -     case PWRDM_POWER_RET:
>               /* No need to save context */
>               save_state = 0;
>               break;
> +     case PWRDM_POWER_RET:
> +             if (!mpu_logic_state && !mpu_mem_state)
> +                     save_state = 3;
> +             else if (!mpu_mem_state)
> +                     save_state = 2;
> +             else if (!mpu_logic_state)
> +                     save_state = 1;
> +             else
> +                     /* No need to save context */
> +                     save_state = 0;
> +             break;
>       case PWRDM_POWER_OFF:
>               save_state = 3;
>               break;
> @@ -421,6 +435,8 @@ void omap_sram_idle(void)
>       /* PER */
>       per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
>       core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
> +     core_logic_state = pwrdm_read_next_logic_pwrst(core_pwrdm);
> +
>       if (per_next_state < PWRDM_POWER_ON) {
>               omap2_gpio_prepare_for_idle(per_next_state);
>               if (per_next_state == PWRDM_POWER_OFF) {
> @@ -448,8 +464,8 @@ void omap_sram_idle(void)
>  
>       /* CORE */
>       if (core_next_state < PWRDM_POWER_ON) {
> -             omap_uart_prepare_idle(0, core_next_state);
> -             omap_uart_prepare_idle(1, core_next_state);
> +             omap_uart_prepare_idle(0, core_next_state & core_logic_state);
> +             omap_uart_prepare_idle(1, core_next_state & core_logic_state);

Hmm this (core_next_state & core_logic_state) bitwise AND logic isn't
terribly clear at first glance (at least to me) as it assumes that the
off value is zero.

For readability, I think we need something like:

    uart_power_state = ((core_next_state == PWRDM_POWER_OFF) ||
                        (core_logic_state == PWRDM_POWER_OFF))
    [...]
    omap_uart_prepare_idle(x, uart_power_state);
    
>               if (core_next_state == PWRDM_POWER_OFF) {
>                       u32 voltctrl = OMAP3430_AUTO_OFF;
>  
> @@ -460,6 +476,20 @@ void omap_sram_idle(void)
>                                            OMAP3_PRM_VOLTCTRL_OFFSET);
>                       omap3_core_save_context(PWRDM_POWER_OFF);
>                       omap3_prcm_save_context();
> +             } else if ((core_next_state == PWRDM_POWER_RET) &&
> +                             (core_logic_state == PWRDM_POWER_OFF)) {
> +                     /* Disable DPLL4 autoidle bit so that register
> +                      * contents match with that stored in the
> +                      * scratchpad. If this is not done rom code
> +                      * enters into some wrong path while coming
> +                      * out of coreOSWR and causes a crash.
> +                      */
> +                     cm_rmw_mod_reg_bits(OMAP3430_AUTO_PERIPH_DPLL_MASK,
> +                                             0x0, PLL_MOD, CM_AUTOIDLE);
> +                     omap3_core_save_context(PWRDM_POWER_RET);
> +                     prm_set_mod_reg_bits(OMAP3430_AUTO_RET,
> +                                             OMAP3430_GR_MOD,
> +                                             OMAP3_PRM_VOLTCTRL_OFFSET);
>               } else if (core_next_state == PWRDM_POWER_RET) {
>                       prm_set_mod_reg_bits(OMAP3430_AUTO_RET,
>                                               OMAP3430_GR_MOD,
> @@ -502,18 +532,27 @@ void omap_sram_idle(void)
>           core_next_state == PWRDM_POWER_OFF)
>               sdrc_write_reg(sdrc_pwr, SDRC_POWER);
>  
> +     mpu_prev_state = pwrdm_read_prev_pwrst(mpu_pwrdm);
>       /* Restore table entry modified during MMU restoration */
> -     if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
> +     if (((mpu_prev_state == PWRDM_POWER_RET) &&
> +                     (pwrdm_read_prev_logic_pwrst(mpu_pwrdm) ==
> +                      PWRDM_POWER_OFF)) || (mpu_prev_state ==
> +                      PWRDM_POWER_OFF))

minor: for consistency with below checks for CORE, check for OFF
first, then for RET/OSWR.

>               restore_table_entry();
>  
>       /* CORE */
>       if (core_next_state < PWRDM_POWER_ON) {
>               core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
> -             if (core_prev_state == PWRDM_POWER_OFF) {
> +             if ((core_prev_state == PWRDM_POWER_OFF) ||
> +                             (core_prev_state == PWRDM_POWER_RET &&
> +                             pwrdm_read_prev_logic_pwrst(core_pwrdm) ==
> +                             PWRDM_POWER_OFF)) {
>                       omap3_core_restore_context(core_prev_state);
> -                     omap3_prcm_restore_context();
> +                     if (core_prev_state == PWRDM_POWER_OFF) {
> +                             omap3_prcm_restore_context();
> +                             omap2_sms_restore_context();
> +                     }
>                       omap3_sram_restore_context();
> -                     omap2_sms_restore_context();
>                       /*
>                        * Errata 1.164 fix : OTG autoidle can prevent
>                        * sleep
> diff --git a/arch/arm/mach-omap2/powerdomain.c 
> b/arch/arm/mach-omap2/powerdomain.c
> index 06bf290..ef9f1bb 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -126,6 +126,16 @@ static int _pwrdm_state_switch(struct powerdomain 
> *pwrdm, int flag)
>               prev = pwrdm_read_prev_pwrst(pwrdm);
>               if (pwrdm->state != prev)
>                       pwrdm->state_counter[prev]++;
> +             if (prev == PWRDM_POWER_RET) {
> +                     if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
> +                                     (pwrdm_read_prev_logic_pwrst(pwrdm) ==
> +                                      PWRDM_POWER_OFF))
> +                             pwrdm->ret_logic_off_counter++;
> +                     if ((pwrdm->pwrsts_mem_ret[0] == PWRSTS_OFF_RET) &&
> +                                     (pwrdm_read_prev_mem_pwrst(pwrdm, 0) ==
> +                                     PWRDM_POWER_OFF))
> +                             pwrdm->ret_mem_off_counter++;
> +             }
>               break;
>       default:
>               return -EINVAL;
> @@ -161,6 +171,9 @@ static __init void _pwrdm_setup(struct powerdomain *pwrdm)
>       for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
>               pwrdm->state_counter[i] = 0;
>  
> +     pwrdm->ret_logic_off_counter = 0;
> +     pwrdm->ret_mem_off_counter = 0;
> +
>       pwrdm_wait_transition(pwrdm);
>       pwrdm->state = pwrdm_read_pwrst(pwrdm);
>       pwrdm->state_counter[pwrdm->state] = 1;
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
> index 69521be..1d88ef3 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -256,8 +256,12 @@ restore:
>       and     r2, r2, #0x3
>       cmp     r2, #0x0        @ Check if target power state was OFF or RET
>          moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
> +     beq     restore_from_off
> +     cmp     r2, #0x1
> +     moveq   r9, #0x3
>       movne   r9, #0x1        @ Only L1 and L2 lost => avoid L2 invalidation
>       bne     logic_l1_restore
> +restore_from_off:
>       ldr     r0, control_stat
>       ldr     r1, [r0]
>       and     r1, #0x700
> diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h 
> b/arch/arm/plat-omap/include/plat/powerdomain.h
> index 7576559..405ccd6 100644
> --- a/arch/arm/plat-omap/include/plat/powerdomain.h
> +++ b/arch/arm/plat-omap/include/plat/powerdomain.h
> @@ -124,6 +124,8 @@ struct powerdomain {
>  
>       int state;
>       unsigned state_counter[PWRDM_MAX_PWRSTS];
> +     unsigned ret_logic_off_counter;
> +     unsigned ret_mem_off_counter;
>  
>  #ifdef CONFIG_PM_DEBUG
>       s64 timer;
> -- 
> 1.5.6.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to