void imx_gpcv2_set_cpu_power_gate_in_idle(bool pdn) { unsigned long flags; u32 cpu; for_each_possible_cpu(cpu) imx_gpcv2_set_cpu_power_gate_by_lpm(cpu, pdn); spin_lock_irqsave(&gpcv2_lock, flags); imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_C0); imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_C1); imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_SCU); imx_gpcv2_set_plat_power_gate_by_lpm(pdn); if (pdn) { imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false); imx_gpcv2_set_slot_ack(1, CORE1_A7, false, false); imx_gpcv2_set_slot_ack(2, SCU_A7, false, true); imx_gpcv2_set_slot_ack(6, SCU_A7, true, false); imx_gpcv2_set_slot_ack(7, CORE0_A7, true, false); imx_gpcv2_set_slot_ack(8, CORE1_A7, true, true); } else { writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 0 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 1 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 2 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 6 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 7 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 8 * 0x4); writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK | BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK, gpc_base + GPC_PGC_ACK_SEL_A7); } spin_unlock_irqrestore(&gpcv2_lock, flags); }
void imx_gpcv2_post_resume(void) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0; int i, val; /* only external IRQs to wake up LPM and core 0/1 */ val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC); val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP; writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC); /* mask m4 dsm trigger if M4 not enabled*/ if (!imx_src_is_m4_enabled()) writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) | BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4); /* set mega/fast mix in A7 domain */ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING); /* set SCU timing */ writel_relaxed((0x59 << 10) | 0x5B | (0x51 << 20), gpc_base + GPC_PGC_SCU_TIMING); val = readl_relaxed(gpc_base + GPC_SLPCR); val &= ~(BM_SLPCR_EN_DSM); if (!imx_src_is_m4_enabled()) val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE; writel_relaxed(val, gpc_base + GPC_SLPCR); /* disable memory low power mode */ val = readl_relaxed(gpc_base + GPC_MLPCR); val |= BM_GPC_MLPCR_MEMLP_CTL_DIS; writel_relaxed(val, gpc_base + GPC_MLPCR); for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpcv2_saved_imrs[i], reg_imr1 + i * 4); imx_gpcv2_set_lpm_mode(WAIT_CLOCKED); imx_gpcv2_set_cpu_power_gate_by_lpm(0, false); imx_gpcv2_set_plat_power_gate_by_lpm(false); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C0); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_SCU); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_FM); for (i = 0; i < MAX_SLOT_NUMBER; i++) { if (i==1||i==4) /* skip slts m4 uses */ continue; writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + i * 0x4); } writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK | BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK, gpc_base + GPC_PGC_ACK_SEL_A7); }
void imx_gpcv2_pre_suspend(bool arm_power_off) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0; int i; if (arm_power_off) { imx_gpcv2_set_lpm_mode(STOP_POWER_OFF); /* enable core0 power down/up with low power mode */ imx_gpcv2_set_cpu_power_gate_by_lpm(0, true); /* enable plat power down with low power mode */ imx_gpcv2_set_plat_power_gate_by_lpm(true); /* * To avoid confuse, we use slot 0~4 for power down, * slot 5~9 for power up. * * Power down slot sequence: * Slot0 -> CORE0 * Slot1 -> Mega/Fast MIX * Slot2 -> SCU * * Power up slot sequence: * Slot5 -> Mega/Fast MIX * Slot6 -> SCU * Slot7 -> CORE0 */ imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false); imx_gpcv2_set_slot_ack(2, SCU_A7, false, true); if ((!imx_src_is_m4_enabled()) || (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop())) imx_gpcv2_mf_mix_off(); imx_gpcv2_set_slot_ack(6, SCU_A7, true, false); imx_gpcv2_set_slot_ack(7, CORE0_A7, true, true); /* enable core0, scu */ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C0); imx_gpcv2_set_m_core_pgc(true, GPC_PGC_SCU); } else { imx_gpcv2_set_lpm_mode(STOP_POWER_ON); } for (i = 0; i < IMR_NUM; i++) { gpcv2_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); writel_relaxed(~gpcv2_wake_irqs[i], reg_imr1 + i * 4); } }
void imx_gpcv2_post_resume(void) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0; int i; for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpcv2_saved_imrs[i], reg_imr1 + i * 4); imx_gpcv2_set_lpm_mode(WAIT_CLOCKED); imx_gpcv2_set_cpu_power_gate_by_lpm(0, false); imx_gpcv2_set_plat_power_gate_by_lpm(false); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C0); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_SCU); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_FM); for (i = 0; i < MAX_SLOT_NUMBER; i++) writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + i * 0x4); writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK | BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK, gpc_base + GPC_PGC_ACK_SEL_A7); }