[PATCHv2 11/19] ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode

Tero Kristo t-kristo at ti.com
Mon May 14 06:18:42 EDT 2012


From: Rajendra Nayak <rnayak at ti.com>

On HS devices on the way out of MPU OSWR and OFF ROM code wrongly
overwrites the CM L3INSTR registers. So to avoid this, save them and
restore on the way out from MPU OSWR/OFF.

This errata applies to all HS/EMU versions of OMAP4.

Signed-off-by: Rajendra Nayak <rnayak at ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar at ti.com>
[t-kristo at ti.com: added omap4 pm errata support]
Signed-off-by: Tero Kristo <t-kristo at ti.com>
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   35 ++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/pm.h                  |    1 +
 arch/arm/mach-omap2/pm44xx.c              |    8 ++++++
 3 files changed, 43 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 73e45a5..f555ac2 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -95,6 +95,12 @@ static struct reg_tuple ivahd_reg[] = {
 	{.addr = OMAP4430_PM_IVAHD_PWRSTCTRL}
 };
 
+static struct reg_tuple l3instr_reg[] = {
+	{.addr = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL},
+	{.addr = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL},
+	{.addr = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL},
+};
+
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
  * used for OFF or DORMANT wakeup.
@@ -262,6 +268,28 @@ static inline void restore_ivahd_tesla_regs(void)
 		__raw_writel(ivahd_reg[i].val, ivahd_reg[i].addr);
 }
 
+static inline void save_l3instr_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_L3INSTR_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+		l3instr_reg[i].val = __raw_readl(l3instr_reg[i].addr);
+}
+
+static inline void restore_l3instr_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_L3INSTR_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+		__raw_writel(l3instr_reg[i].val, l3instr_reg[i].addr);
+}
+
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -321,13 +349,16 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 		omap4_cm_prepare_off();
 		omap4_dpll_prepare_off();
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 3;
 	} else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) {
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 2;
 	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 3;
 	}
 
@@ -352,8 +383,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
-	if (omap4_mpuss_read_prev_context_state())
+	if (omap4_mpuss_read_prev_context_state()) {
 		restore_ivahd_tesla_regs();
+		restore_l3instr_regs();
+	}
 
 	if (omap4_device_prev_state_off()) {
 		omap4_dpll_resume_off();
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index d2d468e..b971f6f 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -131,6 +131,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
 #define PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM	(1 << 0)
+#define PM_OMAP4_ROM_L3INSTR_ERRATUM		(1 << 1)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 extern u16 pm44xx_errata;
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 3870c08..8591df2 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -274,6 +274,14 @@ static int __init omap4_pm_init(void)
 	    omap_type() != OMAP2_DEVICE_TYPE_GP)
 		pm44xx_errata |= PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM;
 
+	/*
+	 * Similar to above errata, ROM code modifies L3INSTR clock
+	 * registers also and these must be saved / restored during
+	 * MPU OSWR / device off.
+	 */
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+		pm44xx_errata |= PM_OMAP4_ROM_L3INSTR_ERRATUM;
+
 #ifdef CONFIG_SUSPEND
 	omap_pm_suspend = omap4_pm_suspend;
 #endif
-- 
1.7.4.1




More information about the linux-arm-kernel mailing list