Example #1
0
void imx_gpcv2_set_cpu_power_gate_by_wfi(u32 cpu, bool pdn)
{
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&gpcv2_lock, flags);
	val = readl_relaxed(gpc_base + GPC_LPCR_A7_AD);

	if (cpu == 0) {
		if (pdn) {
			imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C0);
			val |= BM_LPCR_A7_AD_EN_C0_WFI_PDN |
				BM_LPCR_A7_AD_EN_C0_IRQ_PUP;
		} else {
			imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C0);
			val &= ~(BM_LPCR_A7_AD_EN_C0_WFI_PDN |
				BM_LPCR_A7_AD_EN_C0_IRQ_PUP);
		}
	}
	if (cpu == 1) {
		if (pdn) {
			imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
			val |= BM_LPCR_A7_AD_EN_C1_WFI_PDN |
				BM_LPCR_A7_AD_EN_C1_IRQ_PUP;
		} else {
			imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
			val &= ~(BM_LPCR_A7_AD_EN_C1_WFI_PDN |
				BM_LPCR_A7_AD_EN_C1_IRQ_PUP);
		}
	}
	writel_relaxed(val, gpc_base + GPC_LPCR_A7_AD);
	spin_unlock_irqrestore(&gpcv2_lock, flags);
}
Example #2
0
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);
}
Example #3
0
static int imx_mipi_regulator_notify(struct notifier_block *nb,
					unsigned long event,
					void *ignored)
{
	u32 val = 0;

	val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
	writel_relaxed(val | BIT(2), gpc_base + GPC_PGC_CPU_MAPPING);

	switch (event) {
	case REGULATOR_EVENT_PRE_ENABLE:
		val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ);
		writel_relaxed(val | BIT(0), gpc_base + GPC_PU_PGC_SW_PUP_REQ);
		while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ) & BIT(0))
			;
		break;
	case REGULATOR_EVENT_PRE_DISABLE:
		/* only disable phy need to set PGC bit, enable does NOT need */
		imx_gpcv2_set_m_core_pgc(true, GPC_PGC_MIPI_PHY);
		val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ);
		writel_relaxed(val | BIT(0), gpc_base + GPC_PU_PGC_SW_PDN_REQ);
		while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ) & BIT(0))
			;
		imx_gpcv2_set_m_core_pgc(false, GPC_PGC_MIPI_PHY);
		break;
	default:
		break;
	}

	val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
	writel_relaxed(val & ~BIT(2), gpc_base + GPC_PGC_CPU_MAPPING);

	return NOTIFY_OK;
}
Example #4
0
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);
}
Example #5
0
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
{
	u32 val = readl_relaxed(gpc_base + (pdn ?
		GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ));

	imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
	val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
	writel_relaxed(val, gpc_base + (pdn ?
		GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ));

	while ((readl_relaxed(gpc_base + (pdn ?
		GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ)) &
		BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7) != 0)
		;
	imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
}
Example #6
0
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);
	}
}
Example #7
0
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);
}
Example #8
0
static void imx_gpcv2_mf_mix_off(void)
{
	int i;

	for (i = 0; i < IMR_NUM; i++)
		if (((gpcv2_wake_irqs[i] | gpcv2_mf_request_on[i]) &
						gpcv2_mf_irqs[i]) != 0)
			return;

	pr_info("Turn off Mega/Fast mix in DSM\n");
	imx_gpcv2_set_mix_phy_gate_by_lpm(1, 5);
	imx_gpcv2_set_m_core_pgc(true, GPC_PGC_FM);
}
Example #9
0
static void imx_gpcv2_mf_mix_off(void)
{
	int i;

	for (i = 0; i < IMR_NUM; i++)
		if (((gpcv2_wake_irqs[i] | gpcv2_mf_request_on[i]) &
						gpcv2_mf_irqs[i]) != 0)
			return;

	pr_info("Turn off Mega/Fast mix in DSM\n");

	imx_gpcv2_set_slot_ack(1, FAST_MEGA_MIX, false, false);
	imx_gpcv2_set_slot_ack(5, FAST_MEGA_MIX, true, false);
	imx_gpcv2_set_m_core_pgc(true, GPC_PGC_FM);
}