[PATCH 1/1] omap3: Save and restore CM_AUTOIDLE_PLL across off mode
Paul Walmsley
paul at pwsan.com
Fri Mar 4 17:46:29 EST 2011
Hello Sanjeev,
On Thu, 10 Feb 2011, Sanjeev Premi wrote:
> As per commit "bb33cc58", ROM code is expected to restore
> context related to CORE domain. As part of this change,
> CM_AUTOIDLE_PLL is neither saved nor restored.
... by Linux.
> This results in loosing the value of AUTO_PERIPH_DPLL.
A few questions:
- Is ROM code supposed to restore this register?
- Is there a documented list of which registers/bitfields the ROM code
will and won't restore?
- Are the entire contents of the register lost, or just AUTO_PERIPH_DPLL?
> The concern of setting the AUTOIDLE flag before the DPLL
> is locked seems valid. Hence, the restoration of this
> register is delayed until after the context of PER
> domain is restored.
Could you explain a little more about this? Is there a hardware
limitation where AUTO_PERIPH_DPLL shouldn't be set unless the DPLL is
locked?
>
> The patch has been verified on OMAP3EVM by checking value
> of CM_AUTOIDLE_PLL register across the suspend/resume
> sequence (using devmem) with flags sleep_while_idle and
> enable_off_mode set to 1.
>
> Signed-off-by: Sanjeev Premi <premi at ti.com>
> ---
> arch/arm/mach-omap2/cm2xxx_3xxx.c | 13 +++++++++++++
> arch/arm/mach-omap2/pm34xx.c | 25 ++++++++++++++++++++++++-
> 2 files changed, 37 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
> index 96954aa..a775d8a 100644
> --- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
> @@ -178,6 +178,7 @@ struct omap3_cm_regs {
> u32 per_cm_clksel;
> u32 emu_cm_clksel;
> u32 emu_cm_clkstctrl;
> + u32 pll_cm_autoidle;
> u32 pll_cm_autoidle2;
> u32 pll_cm_clksel4;
> u32 pll_cm_clksel5;
> @@ -250,6 +251,8 @@ void omap3_cm_save_context(void)
> omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
> cm_context.emu_cm_clkstctrl =
> omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
> + cm_context.pll_cm_autoidle =
> + omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
> cm_context.pll_cm_autoidle2 =
> omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
> cm_context.pll_cm_clksel4 =
> @@ -468,4 +471,14 @@ void omap3_cm_restore_context(void)
> omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
> OMAP3_CM_CLKOUT_CTRL_OFFSET);
> }
> +
> +
> +/**
> + * Returns the value corresponding to CM_AUTOIDLE_PLL from the most recent
> + * context saved before entering the OFF mode.
> + */
> +u32 stored_cm_autoidle_pll(void)
> +{
> + return cm_context.pll_cm_autoidle;
> +}
> #endif
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 8bb85fb..25bd230 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -91,6 +91,8 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
> static struct powerdomain *core_pwrdm, *per_pwrdm;
> static struct powerdomain *cam_pwrdm;
>
> +extern u32 stored_cm_autoidle_pll(void);
> +
> static inline void omap3_per_save_context(void)
> {
> omap_gpio_save_context();
> @@ -163,6 +165,25 @@ static void omap3_core_restore_context(void)
> omap_dma_global_context_restore();
> }
>
> +/**
> + * Restore the contents of CM_AUTOIDLE_PLL register.
> + *
> + * The implementation below restores AUTO_CORE_DPLL as 'good' redundancy.
I don't understand this part. Are the entire contents of the register
lost, or just the AUTO_PERIPH_DPLL field?
> + */
> +static void pll_mod_restore_autoidle(void)
> +{
> + u32 ctx = stored_cm_autoidle_pll();
> + u32 val = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
> +
> + if (ctx & OMAP3430_AUTO_CORE_DPLL_MASK)
> + val |= ctx & OMAP3430_AUTO_CORE_DPLL_MASK;
> +
> + if (ctx & OMAP3430_AUTO_PERIPH_DPLL_MASK)
> + val |= ctx & OMAP3430_AUTO_PERIPH_DPLL_MASK;
> +
> + omap2_cm_write_mod_reg(val, PLL_MOD, CM_AUTOIDLE);
> +}
> +
> /*
> * FIXME: This function should be called before entering off-mode after
> * OMAP3 secure services have been accessed. Currently it is only called
> @@ -488,8 +509,10 @@ void omap_sram_idle(void)
> if (per_next_state < PWRDM_POWER_ON) {
> per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
> omap2_gpio_resume_after_idle();
> - if (per_prev_state == PWRDM_POWER_OFF)
> + if (per_prev_state == PWRDM_POWER_OFF) {
> omap3_per_restore_context();
> + pll_mod_restore_autoidle();
> + }
> omap_uart_resume_idle(2);
> omap_uart_resume_idle(3);
> }
> --
> 1.7.2.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
- Paul
More information about the linux-arm-kernel
mailing list