Commit a8ae645c authored by Eduardo Valentin's avatar Eduardo Valentin Committed by Paul Walmsley

OMAP3: PM: Do not rely on ROM code to restore CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL

As per OMAP3 erratum (i671), ROM code adds extra latencies while
restoring CM_AUTOIDLE_PLL register, if AUTO_PERIPH_DPLL is equal to 1.

This patch stores 0's in scratchpad content area corresponding to
AUTO_PERIPH_DPLL, to prevent ROM code to try to lock per DPLL, since
it won't respect proper programing scheme.

This register is then stored in prcm context. The saving and restore
is now done by kernel side.

Here follow the erratum description

DESCRIPTION

After OFF mode transition, among many restorations, the ROM Code restores the
CM_AUTOIDLE_PLL register, and after that, it tries to relock the PER DPLL.

In case the restoration data stored in scratchpad memory contains a field
CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL = 1, then the way the ROM Code restores and
locks the PER DPLL does not respect the PER DPLL programming scheme.

In that case, the DPLL might not lock. Meanwhile, when trying to lock the PER
DPLL, the ROM Code does not hang. Only extra latencies are introduced at
wake-up.

WORKAROUND

When saving the context-restore structure in scratchpad memory, in order to
respect the PER DPLL programming scheme, it is advised to store 0 in the
CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL field of the saved structure.

After wake-up, the application should store in CM_AUTOIDLE_PLL register the
right desired value.
Signed-off-by: default avatarEduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
parent 8bc2e98b
...@@ -247,6 +247,7 @@ struct omap3_cm_regs { ...@@ -247,6 +247,7 @@ struct omap3_cm_regs {
u32 per_cm_clksel; u32 per_cm_clksel;
u32 emu_cm_clksel; u32 emu_cm_clksel;
u32 emu_cm_clkstctrl; u32 emu_cm_clkstctrl;
u32 pll_cm_autoidle;
u32 pll_cm_autoidle2; u32 pll_cm_autoidle2;
u32 pll_cm_clksel4; u32 pll_cm_clksel4;
u32 pll_cm_clksel5; u32 pll_cm_clksel5;
...@@ -319,6 +320,15 @@ void omap3_cm_save_context(void) ...@@ -319,6 +320,15 @@ void omap3_cm_save_context(void)
omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1); omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
cm_context.emu_cm_clkstctrl = cm_context.emu_cm_clkstctrl =
omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL); omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
/*
* As per erratum i671, ROM code does not respect the PER DPLL
* programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
* In this case, even though this register has been saved in
* scratchpad contents, we need to restore AUTO_PERIPH_DPLL
* by ourselves. So, we need to save it anyway.
*/
cm_context.pll_cm_autoidle =
omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
cm_context.pll_cm_autoidle2 = cm_context.pll_cm_autoidle2 =
omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2); omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
cm_context.pll_cm_clksel4 = cm_context.pll_cm_clksel4 =
...@@ -441,6 +451,13 @@ void omap3_cm_restore_context(void) ...@@ -441,6 +451,13 @@ void omap3_cm_restore_context(void)
CM_CLKSEL1); CM_CLKSEL1);
omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD, omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
OMAP2_CM_CLKSTCTRL); OMAP2_CM_CLKSTCTRL);
/*
* As per erratum i671, ROM code does not respect the PER DPLL
* programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
* In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
*/
omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
CM_AUTOIDLE);
omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD, omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
CM_AUTOIDLE2); CM_AUTOIDLE2);
omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD, omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
......
...@@ -316,8 +316,14 @@ void omap3_save_scratchpad_contents(void) ...@@ -316,8 +316,14 @@ void omap3_save_scratchpad_contents(void)
omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL); omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
prcm_block_contents.cm_clken_pll = prcm_block_contents.cm_clken_pll =
omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN); omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
/*
* As per erratum i671, ROM code does not respect the PER DPLL
* programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
* Then, in anycase, clear these bits to avoid extra latencies.
*/
prcm_block_contents.cm_autoidle_pll = prcm_block_contents.cm_autoidle_pll =
omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
~OMAP3430_AUTO_PERIPH_DPLL_MASK;
prcm_block_contents.cm_clksel1_pll = prcm_block_contents.cm_clksel1_pll =
omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL); omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
prcm_block_contents.cm_clksel2_pll = prcm_block_contents.cm_clksel2_pll =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment