Example #1
0
static void reduce_bus_freq(void)
{
	if (cpu_is_imx6())
		clk_prepare_enable(pll3);
	if (audio_bus_count && (low_bus_freq_mode || ultra_low_bus_freq_mode))
		busfreq_notify(LOW_BUSFREQ_EXIT);
	else if (!audio_bus_count)
		busfreq_notify(LOW_BUSFREQ_ENTER);
	if (cpu_is_imx7d())
		enter_lpm_imx7d();
	else if (cpu_is_imx6sl())
		enter_lpm_imx6sl();
	else if (cpu_is_imx6sx() || cpu_is_imx6ul())
		enter_lpm_imx6_up();
	else {
		if (cpu_is_imx6dl())
			/* Set axi to periph_clk */
			imx_clk_set_parent(axi_sel_clk, periph_clk);

		if (audio_bus_count) {
			/* Need to ensure that PLL2_PFD_400M is kept ON. */
			clk_prepare_enable(pll2_400);
			update_ddr_freq_imx_smp(LOW_AUDIO_CLK);
			/* Make sure periph clk's parent also got updated */
			imx_clk_set_parent(periph_clk2_sel, pll3);
			imx_clk_set_parent(periph_pre_clk, pll2_200);
			imx_clk_set_parent(periph_clk, periph_pre_clk);
			audio_bus_freq_mode = 1;
			low_bus_freq_mode = 0;
			cur_bus_freq_mode = BUS_FREQ_AUDIO;
		} else {
			update_ddr_freq_imx_smp(LPAPM_CLK);
			/* Make sure periph clk's parent also got updated */
			imx_clk_set_parent(periph_clk2_sel, osc_clk);
			/* Set periph_clk parent to OSC via periph_clk2_sel */
			imx_clk_set_parent(periph_clk, periph_clk2);
			if (audio_bus_freq_mode)
				clk_disable_unprepare(pll2_400);
			low_bus_freq_mode = 1;
			audio_bus_freq_mode = 0;
			cur_bus_freq_mode = BUS_FREQ_LOW;
		}
	}
	if (cpu_is_imx6())
		clk_disable_unprepare(pll3);

	med_bus_freq_mode = 0;
	high_bus_freq_mode = 0;

	if (audio_bus_freq_mode)
		dev_dbg(busfreq_dev, "Bus freq set to audio mode. Count:\
			high %d, med %d, audio %d\n",
			high_bus_count, med_bus_count, audio_bus_count);
	if (low_bus_freq_mode)
		dev_dbg(busfreq_dev, "Bus freq set to low mode. Count:\
			high %d, med %d, audio %d\n",
			high_bus_count, med_bus_count, audio_bus_count);
}
Example #2
0
static int imx_gpcv2_probe(struct platform_device *pdev)
{
	int ret;
	struct regulator *pcie_reg, *mipi_reg, *usb_hsic_reg;

	if (cpu_is_imx7d()) {
		pcie_reg = devm_regulator_get(&pdev->dev, "pcie-phy");
		if (IS_ERR(pcie_reg)) {
			ret = PTR_ERR(pcie_reg);
			dev_info(&pdev->dev, "pcie regulator not ready.\n");
			return ret;
		}
		nb_pcie.notifier_call = &imx_pcie_regulator_notify;

		ret = regulator_register_notifier(pcie_reg, &nb_pcie);
		if (ret) {
			dev_err(&pdev->dev,
				"pcie regulator notifier request failed\n");
			return ret;
		}

		mipi_reg = devm_regulator_get(&pdev->dev, "mipi-phy");
		if (IS_ERR(mipi_reg)) {
			ret = PTR_ERR(mipi_reg);
			dev_info(&pdev->dev, "mipi regulator not ready.\n");
			return ret;
		}
		nb_mipi.notifier_call = &imx_mipi_regulator_notify;

		ret = regulator_register_notifier(mipi_reg, &nb_mipi);
		if (ret) {
			dev_err(&pdev->dev,
				"mipi regulator notifier request failed.\n");
			return ret;
		}

		usb_hsic_reg = devm_regulator_get(&pdev->dev, "vcc");
		if (IS_ERR(usb_hsic_reg)) {
			ret = PTR_ERR(usb_hsic_reg);
			dev_err(&pdev->dev, "usb hsic regulator not ready.\n");
			return ret;
		}
		nb_usb_hsic.notifier_call = &imx_usb_hsic_regulator_notify;

		ret = regulator_register_notifier(usb_hsic_reg, &nb_usb_hsic);
		if (ret) {
			dev_err(&pdev->dev,
				"usb hsic regulator notifier request failed\n");
			return ret;
		}
	}
	return 0;
}
Example #3
0
static void __init _mxc_timer_init(int irq,
				   struct clk *clk_per, struct clk *clk_ipg)
{
	uint32_t tctl_val;

	if (IS_ERR(clk_per)) {
		pr_err("i.MX timer: unable to get clk\n");
		return;
	}

	if (!IS_ERR(clk_ipg))
		clk_prepare_enable(clk_ipg);

	clk_prepare_enable(clk_per);

	/*
	 * Initialise to a known state (all timers off, and timing reset)
	 */

	__raw_writel(0, timer_base + MXC_TCTL);
	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */

	if (timer_is_v2()) {
		tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
		if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) {
			tctl_val |= V2_TCTL_CLK_OSC_DIV8;
			if (cpu_is_imx6dl() || cpu_is_imx6sll() ||
				cpu_is_imx6sx() || cpu_is_imx6ul() ||
				cpu_is_imx6ull() || cpu_is_imx7d()) {
				/* 24 / 8 = 3 MHz */
				__raw_writel(7 << V2_TPRER_PRE24M,
					timer_base + MXC_TPRER);
				tctl_val |= V2_TCTL_24MEN;
			}
		} else {
			tctl_val |= V2_TCTL_CLK_PER;
		}
	} else {
		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
	}

	__raw_writel(tctl_val, timer_base + MXC_TCTL);

	/* init and register the timer to the framework */
	mxc_clocksource_init(clk_per);
	mxc_clockevent_init(clk_per);

	/* Make irqs happen */
	setup_irq(irq, &mxc_timer_irq);
}
Example #4
0
void __init imx_gpcv2_init(void)
{
	struct device_node *np;
	int i, val;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
	gpc_base = of_iomap(np, 0);
	WARN_ON(!gpc_base);

	/* Initially mask all interrupts */
	for (i = 0; i < IMR_NUM; i++) {
		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()) {
		of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 0,
			&gpcv2_mf_irqs[0]);
		of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 1,
			&gpcv2_mf_irqs[1]);
		of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 2,
			&gpcv2_mf_irqs[2]);
		of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 3,
			&gpcv2_mf_irqs[3]);
		if (!(gpcv2_mf_irqs[0] | gpcv2_mf_irqs[1] |
			gpcv2_mf_irqs[2] | gpcv2_mf_irqs[3]))
			pr_info("No wakeup source in Mega/Fast domain found!\n");
	}

	/* 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 */
	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);
	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);

	val = readl_relaxed(gpc_base + GPC_SLPCR);
	val &= ~(BM_SLPCR_EN_DSM | 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);

	/* Register GPC as the secondary interrupt controller behind GIC */
	gic_arch_extn.irq_mask = imx_gpcv2_irq_mask;
	gic_arch_extn.irq_unmask = imx_gpcv2_irq_unmask;
	gic_arch_extn.irq_set_wake = imx_gpcv2_irq_set_wake;
}
Example #5
0
/*
 * Set the DDR to either 528MHz or 400MHz for iMX6qd
 * or 400MHz for iMX6dl.
 */
static int set_high_bus_freq(int high_bus_freq)
{
	struct clk *periph_clk_parent;

	if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
		cancel_delayed_work_sync(&low_bus_freq_handler);

	if (busfreq_suspended)
		return 0;

	if (cpu_is_imx6q())
		periph_clk_parent = pll2_bus;
	else
		periph_clk_parent = pll2_400;

	if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
		return 0;

	if (high_bus_freq_mode)
		return 0;

	/* medium bus freq is only supported for MX6DQ */
	if (med_bus_freq_mode && !high_bus_freq)
		return 0;

	if (low_bus_freq_mode || ultra_low_bus_freq_mode)
		busfreq_notify(LOW_BUSFREQ_EXIT);

	if (cpu_is_imx6())
		clk_prepare_enable(pll3);

	if (cpu_is_imx7d())
		exit_lpm_imx7d();
	else if (cpu_is_imx6sl())
		exit_lpm_imx6sl();
	else if (cpu_is_imx6sx() || cpu_is_imx6ul())
		exit_lpm_imx6_up();
	else {
		if (high_bus_freq) {
			clk_prepare_enable(pll2_400);
			update_ddr_freq_imx_smp(ddr_normal_rate);
			/* Make sure periph clk's parent also got updated */
			imx_clk_set_parent(periph_clk2_sel, pll3);
			imx_clk_set_parent(periph_pre_clk, periph_clk_parent);
			imx_clk_set_parent(periph_clk, periph_pre_clk);
			if (cpu_is_imx6dl()) {
				/* Set axi to pll3_pfd1_540m */
				imx_clk_set_parent(axi_alt_sel_clk, pll3_pfd1_540m);
				imx_clk_set_parent(axi_sel_clk, axi_alt_sel_clk);
			}
			clk_disable_unprepare(pll2_400);
		} else {
			update_ddr_freq_imx_smp(ddr_med_rate);
			/* Make sure periph clk's parent also got updated */
			imx_clk_set_parent(periph_clk2_sel, pll3);
			imx_clk_set_parent(periph_pre_clk, pll2_400);
			imx_clk_set_parent(periph_clk, periph_pre_clk);
		}
		if (audio_bus_freq_mode)
			clk_disable_unprepare(pll2_400);
	}

	high_bus_freq_mode = 1;
	med_bus_freq_mode = 0;
	low_bus_freq_mode = 0;
	audio_bus_freq_mode = 0;
	cur_bus_freq_mode = BUS_FREQ_HIGH;

	if (cpu_is_imx6())
		clk_disable_unprepare(pll3);
	if (high_bus_freq_mode)
		dev_dbg(busfreq_dev, "Bus freq set to high mode. Count:\
			high %d, med %d, audio %d\n",
			high_bus_count, med_bus_count, audio_bus_count);
	if (med_bus_freq_mode)
		dev_dbg(busfreq_dev, "Bus freq set to med mode. Count:\
			high %d, med %d, audio %d\n",
			high_bus_count, med_bus_count, audio_bus_count);

	return 0;
}