summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/gpcv2.c37
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()) {