"ext Tero Kristo" <tero.kristo@xxxxxxxxx> writes: > CPU-idle has a possibility of working now, also added full PRCM register dump > into pm-debug. > > Signed-off-by: Tero Kristo <tero.kristo@xxxxxxxxx> > --- > arch/arm/mach-omap2/cpuidle34xx.c | 30 ------------------------- > arch/arm/mach-omap2/pm-debug.c | 17 ++++++++++---- > arch/arm/mach-omap2/pm34xx.c | 43 +++++++++++++++++++++++++++--------- > 3 files changed, 44 insertions(+), 46 deletions(-) > mode change 100644 => 100755 arch/arm/mach-omap2/pm-debug.c > > diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c > index 7af8653..9e65631 100755 > --- a/arch/arm/mach-omap2/cpuidle34xx.c > +++ b/arch/arm/mach-omap2/cpuidle34xx.c > @@ -461,10 +461,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev, > per_pwrst = pwrdm_read_pwrst(per_pd); > neon_pwrst = pwrdm_read_pwrst(neon_pd); > > - /* Do this before any changes to PRCM registers */ > - if (cx->core_state == PWRDM_POWER_OFF) > - omap3_save_prcm_ctx(); > - > /* Program MPU to target state */ > if (cx->mpu_state < PWRDM_POWER_ON) { > if (neon_pwrst == PWRDM_POWER_ON) { > @@ -478,17 +474,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev, > > /* Program CORE and PER to target state */ > if (cx->core_state < PWRDM_POWER_ON) { > - if (per_pwrst == PWRDM_POWER_ON) { > - omap2_gpio_prepare_for_retention(); > - if (clocks_off_while_idle) { > - omap3_save_per_ctx(); > - per_gpio_clk_disable(); > - omap_save_uart_ctx(2); > - omap_serial_enable_clocks(0, 2); > - } > - } > - if (cx->core_state == PWRDM_POWER_OFF) > - omap3_save_core_ctx(); > pwrdm_set_next_pwrst(core_pd, cx->core_state); > } This will leave cx->core_state to its previous value in case of ON state. So just pwrdm_set_next_pwrst(core_pd, cx->core_state) without if is better. > > @@ -510,22 +495,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, > } > > if (cx->core_state < PWRDM_POWER_ON) { > - if ((cx->core_state == PWRDM_POWER_OFF) > - && (pwrdm_read_prev_pwrst(core_pd) == PWRDM_POWER_OFF)) { > - omap3_restore_core_ctx(); > - omap3_restore_prcm_ctx(); > - omap3_restore_sram_ctx(); > - } > pwrdm_set_next_pwrst(core_pd, PWRDM_POWER_ON); > - if (per_pwrst == PWRDM_POWER_ON) { > - if (clocks_off_while_idle) { > - omap_serial_enable_clocks(1, 2); > - omap_restore_uart_ctx(2); > - per_gpio_clk_enable(); > - omap3_restore_per_ctx(); > - } > - omap2_gpio_resume_after_retention(); > - } > } > > pr_debug("MPU prev st:%x,NEON prev st:%x\n", > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c > old mode 100644 > new mode 100755 > index b6f8621..f35b082 > --- a/arch/arm/mach-omap2/pm-debug.c > +++ b/arch/arm/mach-omap2/pm-debug.c > @@ -182,26 +182,33 @@ struct pm_module_def { > #define MOD_PRM 1 > > static const struct pm_module_def pm_dbg_reg_modules[] = { > + { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c }, > { "OCP", MOD_CM, OCP_MOD, 0, 0x10 }, > { "MPU", MOD_CM, MPU_MOD, 4, 0x4c }, > { "CORE", MOD_CM, CORE_MOD, 0, 0x4c }, > - { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 }, > + { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c }, > { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 }, > - { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 }, > { "CCR", MOD_CM, PLL_MOD, 0, 0x70 }, > { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c }, > + { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c }, > { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c }, > + { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 }, > + { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 }, > { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c }, > > - { "OCP", MOD_PRM, OCP_MOD, 0x1c }, > + { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc }, > + { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c }, > { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 }, > { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 }, > - { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 }, > + { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 }, > { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 }, > - { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 }, > { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 }, > { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 }, > + { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 }, > { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 }, > + { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 }, > + { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 }, > + { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 }, > { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 }, > { "", 0, 0, 0, 0 }, > }; > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c > index c4afa7d..3c62b68 100755 > --- a/arch/arm/mach-omap2/pm34xx.c > +++ b/arch/arm/mach-omap2/pm34xx.c > @@ -75,6 +75,8 @@ void (*_omap_sram_idle)(u32 *addr, int save_state); > static void (*saved_idle)(void); > > static struct powerdomain *mpu_pwrdm; > +static struct powerdomain *core_pwrdm; > +static struct powerdomain *per_pwrdm; > > /* XXX This is for gpio fclk hack. Will be removed as gpio driver > * handles fcks correctly */ > @@ -235,6 +237,8 @@ void omap_sram_idle(void) > /* save_state = 2 => Only L2 lost */ > /* save_state = 3 => L1, L2 and logic lost */ > int save_state = 0, mpu_next_state; > + int save_core; > + int save_per; > > if (!_omap_sram_idle) > return; > @@ -255,17 +259,26 @@ void omap_sram_idle(void) > return; > } > > - omap3_save_core_ctx(); > - omap3_save_prcm_ctx(); > + save_core = (pwrdm_read_next_pwrst(core_pwrdm) == PWRDM_POWER_OFF); > + save_per = (pwrdm_read_next_pwrst(per_pwrdm) == > PWRDM_POWER_OFF); Just read next states here. > + > + if (save_core) { > + omap3_save_core_ctx(); > + omap3_save_prcm_ctx(); > + } And do this if core next_st < PWRDM_POWER_ON > + > + if (save_per) > + omap3_save_per_ctx(); And same here. Additionally, do this only if core next_st < PWRDM_POWER_ON. > > - omap3_save_per_ctx(); > omap2_gpio_prepare_for_retention(); > > /* XXX This is for gpio fclk hack. Will be removed as gpio driver > * handqles fcks correctly */ > per_gpio_clk_disable(); > > - omap_save_uart_ctx(); > + if (save_per) > + omap_save_uart_ctx(); Again, do this only if core next_st < PWRDM_POWER_ON and per next_st == PWRDM_POWER_OFF. > + > omap_serial_enable_clocks(0); Consider Rajendras idea to do this only if needed. > > *(scratchpad_restore_addr) = restore_pointer_address; > @@ -277,19 +290,24 @@ void omap_sram_idle(void) > if (pwrdm_read_prev_pwrst(mpu_pwrdm) == 0x0) > restore_table_entry(); > > - omap3_restore_prcm_ctx(); > - omap3_restore_sram_ctx(); > - omap3_restore_core_ctx(); > + if (save_core) { > + omap3_restore_prcm_ctx(); > + omap3_restore_sram_ctx(); > + omap3_restore_core_ctx(); > + } > > omap_serial_enable_clocks(1); /* Causes crash with CORE off */ > > - omap_restore_uart_ctx(); > + if (save_per) > + omap_restore_uart_ctx(); > > /* XXX This is for gpio fclk hack. Will be removed as gpio driver > * handles fcks correctly */ > > per_gpio_clk_enable(); > - omap3_restore_per_ctx(); > + > + if (save_per) > + omap3_restore_per_ctx(); > > omap2_gpio_resume_after_retention(); Same comments to restore part as before wfi. I think you should look at what Rajendra has done (logic in omap3_enter_idle). You might also want to look at previous discussion related to this. Something like this: void omap_sram_idle(void) { /* Variable to tell what needs to be saved and restored * in omap_sram_idle*/ /* save_state = 0 => Nothing to save and restored */ /* save_state = 1 => Only L1 and logic lost */ /* save_state = 2 => Only L2 lost */ /* save_state = 3 => L1, L2 and logic lost */ int save_state = 0; int mpu_next_state = PWRDM_POWER_ON, core_next_state = PWRDM_POWER_ON, per_next_state = PWRDM_POWER_ON; int neon_state; if (!_omap_sram_idle) return; mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); switch (mpu_next_state) { case PWRDM_POWER_ON: case PWRDM_POWER_RET: /* No need to save context */ save_state = 0; break; case PWRDM_POWER_OFF: save_state = 3; break; default: /* Invalid state */ printk(KERN_ERR "Invalid mpu state in sram_idle\n"); return; } pm_dbg_pre_suspend(); /* NEON control */ if (mpu_next_state < PWRDM_POWER_ON) { neon_state = pwrdm_read_pwrst(neon_pwrdm); if (neon_state == PWRDM_POWER_ON) pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state); } /* CORE & PER */ core_next_state = pwrdm_read_next_pwrst(core_pwrdm); if (core_next_state < PWRDM_POWER_ON) { /* PER changes only with core */ per_next_state = pwrdm_read_next_pwrst(per_pwrdm); if (per_next_state < PWRDM_POWER_ON) { if (per_next_state == PWRDM_POWER_OFF) { omap3_save_per_ctx(); /* This would be actually more effective */ /* omap_save_uart_ctx(2); */ } if (clocks_off_while_idle) per_gpio_clk_disable(); /* This would be actually more effective */ /* omap_serial_enable_clocks(0, 2); */ } if (core_next_state == PWRDM_POWER_OFF) { omap3_save_core_ctx(); omap3_save_prcm_ctx(); /* omap_save_uart_ctx(2); */ /* omap_save_uart_ctx(2); */ } if (core_next_state == PWRDM_POWER_OFF || per_next_state == PWRDM_POWER_OFF) omap_save_uart_ctx(); if (clocks_off_while_idle) omap_serial_enable_clocks(0); /* omap_serial_enable_clocks(0, 2); */ /* omap_serial_enable_clocks(0, 2); */ } /* Is this related to per transition or transition in general? */ omap2_gpio_prepare_for_retention(); *(scratchpad_restore_addr) = restore_pointer_address; _omap_sram_idle(context_mem, save_state); *(scratchpad_restore_addr) = 0x0; if (pwrdm_read_prev_pwrst(mpu_pwrdm) == 0x0) restore_table_entry(); if (core_next_state < PWRDM_POWER_ON) { if (core_next_state == PWRDM_POWER_OFF) { omap3_restore_core_ctx(); omap3_restore_sram_ctx(); omap3_restore_prcm_ctx(); /* omap_restore_uart_ctx(0); */ /* omap_restore_uart_ctx(1); */ } if (per_next_state < PWRDM_POWER_ON) { if (per_next_state == PWRDM_POWER_OFF) { omap3_restore_per_ctx(); /* This would be actually more effective */ /* omap_restore_uart_ctx(2); */ } if (clocks_off_while_idle) { per_gpio_clk_enable(); /* This would be actually more effective */ /* omap_serial_enable_clocks(0, 2); */ } } if (core_next_state == PWRDM_POWER_OFF || per_next_state == PWRDM_POWER_OFF) omap_restore_uart_ctx(); if (clocks_off_while_idle) omap_serial_enable_clocks(1); /* omap_serial_enable_clocks(1, 0); */ /* omap_serial_enable_clocks(1, 1); */ } omap2_gpio_resume_after_retention(); pm_dbg_post_suspend(); } > } > @@ -718,10 +736,13 @@ int __init omap3_pm_init(void) > } > > mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); > + core_pwrdm = pwrdm_lookup("core_pwrdm"); > + per_pwrdm = pwrdm_lookup("per_pwrdm"); > neon_pwrdm = pwrdm_lookup("neon_pwrdm"); > > - if (mpu_pwrdm == NULL || neon_pwrdm == NULL) { > - printk(KERN_ERR "Failed to get mpu_pwrdm or neon_pwrdm\n"); > + if (mpu_pwrdm == NULL || neon_pwrdm == NULL || per_pwrdm == NULL || > + core_pwrdm == NULL) { > + printk(KERN_ERR "Failed to get pwrdm pointers\n"); Neon handling is missing. > goto err2; > } > > -- > 1.5.4.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- Jouni Högander -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html