From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tero Kristo Subject: [PATCHv2 11/19] ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode Date: Mon, 14 May 2012 13:18:42 +0300 Message-ID: <1336990730-26892-12-git-send-email-t-kristo@ti.com> References: <1336990730-26892-1-git-send-email-t-kristo@ti.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from arroyo.ext.ti.com ([192.94.94.40]:38454 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755826Ab2ENKTi (ORCPT ); Mon, 14 May 2012 06:19:38 -0400 In-Reply-To: <1336990730-26892-1-git-send-email-t-kristo@ti.com> Sender: linux-omap-owner@vger.kernel.org List-Id: linux-omap@vger.kernel.org To: linux-omap@vger.kernel.org, khilman@ti.com, paul@pwsan.com Cc: linux-arm-kernel@lists.infradead.org, Rajendra Nayak , Santosh Shilimkar From: Rajendra Nayak 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 Signed-off-by: Santosh Shilimkar [t-kristo@ti.com: added omap4 pm errata support] Signed-off-by: Tero Kristo --- 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 From mboxrd@z Thu Jan 1 00:00:00 1970 From: t-kristo@ti.com (Tero Kristo) Date: Mon, 14 May 2012 13:18:42 +0300 Subject: [PATCHv2 11/19] ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode In-Reply-To: <1336990730-26892-1-git-send-email-t-kristo@ti.com> References: <1336990730-26892-1-git-send-email-t-kristo@ti.com> Message-ID: <1336990730-26892-12-git-send-email-t-kristo@ti.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: Rajendra Nayak 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 Signed-off-by: Santosh Shilimkar [t-kristo at ti.com: added omap4 pm errata support] Signed-off-by: Tero Kristo --- 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