diff options
-rw-r--r-- | arch/arm/mach-imx/gpcv2.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/arch/arm/mach-imx/gpcv2.c b/arch/arm/mach-imx/gpcv2.c index e11c03b4d294..c6c4e60ef213 100644 --- a/arch/arm/mach-imx/gpcv2.c +++ b/arch/arm/mach-imx/gpcv2.c @@ -171,13 +171,28 @@ void imx_gpcv2_set_lpm_mode(u32 cpu, enum mxc_cpu_pwr_mode mode) val2 &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); + /* + * GPC: When improper low-power sequence is used, + * the SoC enters low power mode before the ARM core executes WFI. + * + * Software workaround: + * 1) Software should trigger IRQ #32 (IOMUX) to be always pending + * by setting IOMUX_GPR1_IRQ. + * 2) Software should then unmask IRQ #32 in GPC before setting GPC + * Low-Power mode. + * 3) Software should mask IRQ #32 right after GPC Low-Power mode + * is set. + */ + iomuxc_irq_desc = irq_to_desc(32); switch (mode) { case WAIT_CLOCKED: + imx_gpcv2_irq_unmask(&iomuxc_irq_desc->irq_data); break; case WAIT_UNCLOCKED: val1 |= A7_LPM_WAIT << BP_LPCR_A7_BSC_LPM0; val1 &= ~BM_LPCR_A7_BSC_CPU_CLK_ON_LPM; + imx_gpcv2_irq_mask(&iomuxc_irq_desc->irq_data); break; case STOP_POWER_OFF: val1 |= A7_LPM_STOP << BP_LPCR_A7_BSC_LPM0; @@ -187,27 +202,13 @@ void imx_gpcv2_set_lpm_mode(u32 cpu, enum mxc_cpu_pwr_mode mode) val2 |= BM_SLPCR_SBYOS; val2 |= BM_SLPCR_VSTBY; val2 |= BM_SLPCR_BYPASS_PMIC_READY; + imx_gpcv2_irq_mask(&iomuxc_irq_desc->irq_data); break; default: return; } - /* - * GPC: When improper low-power sequence is used, - * the SoC enters low power mode before the ARM core executes WFI. - * - * Software workaround: - * 1) Software should trigger IRQ #32 (IOMUX) to be always pending - * by setting IOMUX_GPR1_IRQ. - * 2) Software should then unmask IRQ #32 in GPC before setting GPC - * Low-Power mode. - * 3) Software should mask IRQ #32 right after GPC Low-Power mode - * is set. - */ - iomuxc_irq_desc = irq_to_desc(32); - imx_gpcv2_irq_unmask(&iomuxc_irq_desc->irq_data); writel_relaxed(val1, gpc_base + GPC_LPCR_A7_BSC); writel_relaxed(val2, gpc_base + GPC_SLPCR); - imx_gpcv2_irq_mask(&iomuxc_irq_desc->irq_data); spin_unlock_irqrestore(&gpcv2_lock, flags); } @@ -506,6 +507,12 @@ void __init imx_gpcv2_init(void) writel_relaxed(~0, gpc_base + GPC_IMR1_CORE0 + i * 4); writel_relaxed(~0, gpc_base + GPC_IMR1_CORE1 + i * 4); } + /* + * Due to hardware design requirement, need to make sure GPR + * interrupt(#32) is unmasked during RUN mode to avoid entering + * DSM by mistake. + */ + writel_relaxed(~0x1, gpc_base + GPC_IMR1_CORE0); /* Read supported wakeup source in M/F domain */ if (cpu_is_imx7d()) { |