aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEduardo Valentin <eduardo.valentin@ti.com>2011-04-13 11:21:07 -0400
committerPaul Walmsley <paul@pwsan.com>2011-04-20 14:43:56 -0400
commita8ae645c014bc01090367de84f7601ad11628971 (patch)
tree4bcc02380c30f59695593ce088acdc81047cd825
parent8bc2e98bcb280009cb0f85ce64e5f79b1669f9ff (diff)
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: Eduardo Valentin <eduardo.valentin@ti.com> Signed-off-by: Paul Walmsley <paul@pwsan.com>
-rw-r--r--arch/arm/mach-omap2/cm2xxx_3xxx.c17
-rw-r--r--arch/arm/mach-omap2/control.c8
2 files changed, 24 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
index 9d0dec806e92..38830d8d4783 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -247,6 +247,7 @@ struct omap3_cm_regs {
247 u32 per_cm_clksel; 247 u32 per_cm_clksel;
248 u32 emu_cm_clksel; 248 u32 emu_cm_clksel;
249 u32 emu_cm_clkstctrl; 249 u32 emu_cm_clkstctrl;
250 u32 pll_cm_autoidle;
250 u32 pll_cm_autoidle2; 251 u32 pll_cm_autoidle2;
251 u32 pll_cm_clksel4; 252 u32 pll_cm_clksel4;
252 u32 pll_cm_clksel5; 253 u32 pll_cm_clksel5;
@@ -319,6 +320,15 @@ void omap3_cm_save_context(void)
319 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1); 320 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
320 cm_context.emu_cm_clkstctrl = 321 cm_context.emu_cm_clkstctrl =
321 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL); 322 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
323 /*
324 * As per erratum i671, ROM code does not respect the PER DPLL
325 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
326 * In this case, even though this register has been saved in
327 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
328 * by ourselves. So, we need to save it anyway.
329 */
330 cm_context.pll_cm_autoidle =
331 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
322 cm_context.pll_cm_autoidle2 = 332 cm_context.pll_cm_autoidle2 =
323 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2); 333 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
324 cm_context.pll_cm_clksel4 = 334 cm_context.pll_cm_clksel4 =
@@ -441,6 +451,13 @@ void omap3_cm_restore_context(void)
441 CM_CLKSEL1); 451 CM_CLKSEL1);
442 omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD, 452 omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
443 OMAP2_CM_CLKSTCTRL); 453 OMAP2_CM_CLKSTCTRL);
454 /*
455 * As per erratum i671, ROM code does not respect the PER DPLL
456 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
457 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
458 */
459 omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
460 CM_AUTOIDLE);
444 omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD, 461 omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
445 CM_AUTOIDLE2); 462 CM_AUTOIDLE2);
446 omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD, 463 omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index df0c75c31998..da53ba3917ca 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -316,8 +316,14 @@ void omap3_save_scratchpad_contents(void)
316 omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL); 316 omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
317 prcm_block_contents.cm_clken_pll = 317 prcm_block_contents.cm_clken_pll =
318 omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN); 318 omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
319 /*
320 * As per erratum i671, ROM code does not respect the PER DPLL
321 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
322 * Then, in anycase, clear these bits to avoid extra latencies.
323 */
319 prcm_block_contents.cm_autoidle_pll = 324 prcm_block_contents.cm_autoidle_pll =
320 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); 325 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
326 ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
321 prcm_block_contents.cm_clksel1_pll = 327 prcm_block_contents.cm_clksel1_pll =
322 omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL); 328 omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
323 prcm_block_contents.cm_clksel2_pll = 329 prcm_block_contents.cm_clksel2_pll =