summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <Anson.Huang@nxp.com>2016-01-27 10:58:21 +0800
committerAnson Huang <Anson.Huang@nxp.com>2016-01-28 18:54:29 +0800
commit67785980f9df193fca36de91b6a008d5f2660394 (patch)
tree7ed4f892b4aade16cd7d307ac00790a9ee748994 /arch
parent52d262edd47acbf526f1be5281caa62c8d70827d (diff)
MLK-12262-5 ARM: imx: add RBC workaround for i.MX7D DSM
Same as low power idle, during GPC shutting down ARM core, interrupts must be hold until the process done, apply RBC workaround and disable GIC during GPC powering down ARM core. Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/pm-imx7.c5
-rw-r--r--arch/arm/mach-imx/suspend-imx7.S78
2 files changed, 76 insertions, 7 deletions
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c
index 6e40d40c9908..4ce9e6967f77 100644
--- a/arch/arm/mach-imx/pm-imx7.c
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -358,6 +358,7 @@ struct imx7_cpu_pm_info {
struct imx7_pm_base snvs_base;
struct imx7_pm_base anatop_base;
struct imx7_pm_base lpsr_base;
+ struct imx7_pm_base gic_base;
u32 ttbr1; /* Store TTBR1 */
u32 ddrc_num; /* Number of DDRC which need saved/restored. */
u32 ddrc_val[MX7_MAX_DDRC_NUM][2]; /* To save offset and value */
@@ -982,6 +983,10 @@ static int __init imx7_suspend_init(const struct imx7_pm_socdata *socdata)
lpsr_base = pm_info->lpsr_base.vbase = (void __iomem *)
IMX_IO_P2V(MX7D_LPSR_BASE_ADDR);
+ pm_info->gic_base.pbase = MX7D_GIC_BASE_ADDR;
+ pm_info->gic_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_GIC_BASE_ADDR);
+
pm_info->ddrc_num = socdata->ddrc_num;
ddrc_offset_array = socdata->ddrc_offset;
pm_info->ddrc_phy_num = socdata->ddrc_phy_num;
diff --git a/arch/arm/mach-imx/suspend-imx7.S b/arch/arm/mach-imx/suspend-imx7.S
index f4a48024ea98..df43ad4ec98b 100644
--- a/arch/arm/mach-imx/suspend-imx7.S
+++ b/arch/arm/mach-imx/suspend-imx7.S
@@ -66,13 +66,15 @@
#define PM_INFO_MX7_ANATOP_V_OFFSET 0x58
#define PM_INFO_MX7_LPSR_P_OFFSET 0x5c
#define PM_INFO_MX7_LPSR_V_OFFSET 0x60
-#define PM_INFO_MX7_TTBR1_V_OFFSET 0x64
-#define PM_INFO_DDRC_REG_NUM_OFFSET 0x68
-#define PM_INFO_DDRC_REG_OFFSET 0x6c
-#define PM_INFO_DDRC_VALUE_OFFSET 0x70
-#define PM_INFO_DDRC_PHY_REG_NUM_OFFSET 0x16c
-#define PM_INFO_DDRC_PHY_REG_OFFSET 0x170
-#define PM_INFO_DDRC_PHY_VALUE_OFFSET 0x174
+#define PM_INFO_MX7_GIC_DIST_P_OFFSET 0x64
+#define PM_INFO_MX7_GIC_DIST_V_OFFSET 0x68
+#define PM_INFO_MX7_TTBR1_V_OFFSET 0x6c
+#define PM_INFO_DDRC_REG_NUM_OFFSET 0x70
+#define PM_INFO_DDRC_REG_OFFSET 0x74
+#define PM_INFO_DDRC_VALUE_OFFSET 0x78
+#define PM_INFO_DDRC_PHY_REG_NUM_OFFSET 0x174
+#define PM_INFO_DDRC_PHY_REG_OFFSET 0x178
+#define PM_INFO_DDRC_PHY_VALUE_OFFSET 0x17c
#define MX7_SRC_GPR1 0x74
#define MX7_SRC_GPR2 0x78
@@ -90,6 +92,10 @@
#define DDRPHY_LP_CON0 0x18
#define CCM_SNVS_LPCG 0x250
+#define MX7D_GPC_IMR1 0x30
+#define MX7D_GPC_IMR2 0x34
+#define MX7D_GPC_IMR3 0x38
+#define MX7D_GPC_IMR4 0x3c
.align 3
@@ -566,6 +572,60 @@ ddr_only_self_refresh:
ddrc_enter_self_refresh
ddr_retention_enter_out:
+ ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r11]
+
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r4, [r11, #MX7D_GPC_IMR1]
+ ldr r5, [r11, #MX7D_GPC_IMR2]
+ ldr r6, [r11, #MX7D_GPC_IMR3]
+ ldr r7, [r11, #MX7D_GPC_IMR4]
+
+ ldr r8, =0xffffffff
+ str r8, [r11, #MX7D_GPC_IMR1]
+ str r8, [r11, #MX7D_GPC_IMR2]
+ str r8, [r11, #MX7D_GPC_IMR3]
+ str r8, [r11, #MX7D_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 8 (240us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~250uS.
+ */
+ ldr r8, [r11, #0x14]
+ bic r8, r8, #(0x3f << 24)
+ orr r8, r8, #(0x8 << 24)
+ str r8, [r11, #0x14]
+
+ /* enable the counter. */
+ ldr r8, [r11, #0x14]
+ orr r8, r8, #(0x1 << 30)
+ str r8, [r11, #0x14]
+
+ /* unmask all the GPC interrupts. */
+ str r4, [r11, #MX7D_GPC_IMR1]
+ str r5, [r11, #MX7D_GPC_IMR2]
+ str r6, [r11, #MX7D_GPC_IMR3]
+ str r7, [r11, #MX7D_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 1GHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r7, =2000
+rbc_loop:
+ subs r7, r7, #0x1
+ bne rbc_loop
+
/* Zzz, enter stop mode */
wfi
nop
@@ -586,6 +646,10 @@ wfi_ddr_self_refresh_out:
ddrc_exit_self_refresh
wfi_ddr_retention_out:
+ ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r11]
+
/* check whether it is a standby mode */
ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
ldr r7, [r11, #GPC_PGC_C0]