diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c index 49a90c8e11f2..e9f4d86f21aa 100644 --- a/arch/arm/mach-imx/pm-imx7.c +++ b/arch/arm/mach-imx/pm-imx7.c @@ -369,6 +369,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 */ @@ -1054,6 +1055,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 91019802ea17..7a4ca800ab8a 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 @@ -92,6 +94,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 @@ -575,6 +581,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 @@ -595,6 +655,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]