X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=arch%2Farm%2Fmach-omap2%2Fpm34xx.c;h=abea9e984104c0b307b3501dd2933f39fd96791c;hp=4889a08881e74f788ff47bada0e063177463dc70;hb=2d5f8c7b94bfcaf494ec3c2bbc0adf8eb7b4b0eb;hpb=c432db279f4f03bf6a315bc2138ac3a15717e6bb diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 4889a08881e7..abea9e984104 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -100,19 +100,19 @@ static void omap3_enable_io_chain(void) omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, PM_WKEN); - /* Do a readback to assure write has been done */ - omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); - while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) & + while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) & OMAP3430_ST_IO_CHAIN_MASK)) { timeout++; - if (timeout > 1000) { + if (timeout > 100) { pr_err("Wake up daisy chain activation failed.\n"); return; } - omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, - WKUP_MOD, PM_WKEN); + udelay(1); } + + omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD, + PM_WKST); } static void omap3_disable_io_chain(void) @@ -335,7 +335,7 @@ void omap_sram_idle(void) int per_next_state = PWRDM_POWER_ON; int core_next_state = PWRDM_POWER_ON; int per_going_off; - int core_prev_state, per_prev_state; + int per_prev_state; u32 sdrc_pwr = 0; mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); @@ -435,19 +435,25 @@ void omap_sram_idle(void) sdrc_write_reg(sdrc_pwr, SDRC_POWER); /* CORE */ + if (core_next_state < PWRDM_POWER_ON && + pwrdm_read_prev_pwrst(core_pwrdm) == PWRDM_POWER_OFF) { + omap3_core_restore_context(); + omap3_cm_restore_context(); + omap3_sram_restore_context(); + omap2_sms_restore_context(); + } else { + /* + * In off-mode resume path above, omap3_core_restore_context + * also handles the INTC autoidle restore done here so limit + * this to non-off mode resume paths so we don't do it twice. + */ + omap3_intc_resume_idle(); + } if (core_next_state < PWRDM_POWER_ON) { - core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm); - if (core_prev_state == PWRDM_POWER_OFF) { - omap3_core_restore_context(); - omap3_cm_restore_context(); - omap3_sram_restore_context(); - omap2_sms_restore_context(); - } omap_uart_resume_idle(0); omap_uart_resume_idle(1); pwrdm_post_transition(core_pwrdm); } - omap3_intc_resume_idle(); /* PER */ if (per_next_state < PWRDM_POWER_ON) { @@ -497,6 +503,15 @@ out: local_irq_enable(); } +void omap3_pm_alow_pmic_idle(int allow) +{ + /* enable sys_clkreq signalling on RET */ + omap2_prm_rmw_mod_reg_bits((OMAP3430_AUTO_OFF_MASK | OMAP3430_AUTO_RET_MASK + | OMAP3430_AUTO_SLEEP_MASK), allow ? OMAP3430_AUTO_RET_MASK : 0, + OMAP3430_GR_MOD, OMAP3_PRM_VOLTCTRL_OFFSET); +} +EXPORT_SYMBOL(omap3_pm_alow_pmic_idle); + #ifdef CONFIG_SUSPEND static int omap3_pm_suspend(void) { @@ -659,6 +674,9 @@ static void __init prcm_setup_regs(void) OMAP3630_EN_UART4_MASK : 0; u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ? OMAP3630_GRPSEL_UART4_MASK : 0; +#ifdef CONFIG_OMAP3_DISABLE_UART4 + omap3630_en_uart4_mask = omap3630_grpsel_uart4_mask = 0; +#endif /* XXX This should be handled by hwmod code or SCM init code */ omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG); @@ -733,10 +751,7 @@ static void __init prcm_setup_regs(void) omap3_iva_idle(); omap3_d2d_idle(); - /* enable sys_clkreq signalling */ - omap2_prm_rmw_mod_reg_bits((OMAP3430_AUTO_OFF_MASK | OMAP3430_AUTO_RET_MASK - | OMAP3430_AUTO_SLEEP_MASK), OMAP3430_AUTO_RET_MASK, - OMAP3430_GR_MOD, OMAP3_PRM_VOLTCTRL_OFFSET); + omap3_pm_alow_pmic_idle(1); } void omap3_pm_off_mode_enable(int enable) @@ -756,6 +771,9 @@ void omap3_pm_off_mode_enable(int enable) pwrst->next_state = PWRDM_POWER_RET; pr_warn("%s: Core OFF disabled due to errata i583\n", __func__); + } else if (enable < 3 && pwrst->pwrdm == per_pwrdm) { + /* pandora hack */ + pwrst->next_state = PWRDM_POWER_RET; } else { pwrst->next_state = state; } @@ -804,6 +822,29 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) if (pwrdm_has_hdwr_sar(pwrdm)) pwrdm_enable_hdwr_sar(pwrdm); + /* pandora OFF hacks, notes for missing: + * - core_pwrdm - loses GPIO state?! + * - per_pwrdm - must keep RET because of GPIOs + * - neon_pwrdm - depends on mpu_pwrdm + * - mpu_pwrdm - sometimes hangs? + * notes for enabled: + * - usbhost_pwrdm - does driver reload + reinit anyway, no runtime PM + * - sgx_pwrdm - only OFF is supported + * - dss_pwrdm - works, needs working context_loss counter + * - cam_pwrdm - not used + * - iva2_pwrdm - c64_tools reprograms with direct reg hits anyway + */ + if ( pwrdm == pwrdm_lookup("usbhost_pwrdm") + || pwrdm == pwrdm_lookup("sgx_pwrdm") + || pwrdm == pwrdm_lookup("cam_pwrdm") + || pwrdm == pwrdm_lookup("iva2_pwrdm") + ) + pwrst->next_state = PWRDM_POWER_OFF; + + /* on OMAP3, at least on ES2.1, DSS drains more in OFF than in RET?? */ + else if (cpu_is_omap3630() && pwrdm == pwrdm_lookup("dss_pwrdm")) + pwrst->next_state = PWRDM_POWER_OFF; + return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); }