Ejemplo n.º 1
0
static void reduce_bus_freq_handler(struct work_struct *work)
{
    unsigned long reg;

    if (low_bus_freq_mode || !low_freq_bus_used())
        return;

    if (audio_bus_freq_mode && lp_audio_freq)
        return;

    while (!mutex_trylock(&bus_freq_mutex))
        msleep(1);

    /* PLL3 is used in the DDR freq change process, enable it. */

    if (low_bus_freq_mode || !low_freq_bus_used()) {
        mutex_unlock(&bus_freq_mutex);
        return;
    }

    if (audio_bus_freq_mode && lp_audio_freq) {
        mutex_unlock(&bus_freq_mutex);
        return;
    }

    clk_enable(pll3);

    if (lp_audio_freq) {
        /* Need to ensure that PLL2_PFD_400M is kept ON. */
        clk_enable(pll2_400);
        update_ddr_freq(50000000);
        audio_bus_freq_mode = 1;
        low_bus_freq_mode = 0;
    } else {
        update_ddr_freq(24000000);
        if (audio_bus_freq_mode)
            clk_disable(pll2_400);
        low_bus_freq_mode = 1;
        audio_bus_freq_mode = 0;
    }

    if (med_bus_freq_mode)
        clk_disable(pll2_400);

    high_bus_freq_mode = 0;
    med_bus_freq_mode = 0;

    if (cpu_is_mx6q()) {
        /* Power gate the PU LDO. */
        org_ldo = reg = __raw_readl(ANADIG_REG_CORE);
        reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
        __raw_writel(reg, ANADIG_REG_CORE);
    }
    clk_disable(pll3);
    mutex_unlock(&bus_freq_mutex);

}
Ejemplo n.º 2
0
/* Set the DDR to either 528MHz or 400MHz for MX6q
 * or 400MHz for MX6DL.
 */
int set_high_bus_freq(int high_bus_freq)
{
    if (busfreq_suspended)
        return 0;

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

    if (high_bus_freq_mode && high_bus_freq)
        return 0;

    if (med_bus_freq_mode && !high_bus_freq)
        return 0;

    while (!mutex_trylock(&bus_freq_mutex))
        msleep(1);

    if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
            (med_bus_freq_mode && !high_bus_freq && lp_med_freq && !lp_high_freq)) {
        mutex_unlock(&bus_freq_mutex);
        return 0;
    }
    clk_enable(pll3);

    /* Enable the PU LDO */
    if (cpu_is_mx6q() && low_bus_freq_mode)
        __raw_writel(org_ldo, ANADIG_REG_CORE);

    if (high_bus_freq) {
        update_ddr_freq(ddr_normal_rate);
        if (med_bus_freq_mode)
            clk_disable(pll2_400);
        high_bus_freq_mode = 1;
        med_bus_freq_mode = 0;
    } else {
        clk_enable(pll2_400);
        update_ddr_freq(ddr_med_rate);
        high_bus_freq_mode = 0;
        med_bus_freq_mode = 1;
    }
    if (audio_bus_freq_mode)
        clk_disable(pll2_400);
    low_bus_freq_mode = 0;
    audio_bus_freq_mode = 0;

    low_bus_freq_mode = 0;

    clk_disable(pll3);
    mutex_unlock(&bus_freq_mutex);

    return 0;
}
void set_ddr_freq(int ddr_rate)
{
	unsigned long flags;
	unsigned int ret = 0;

	spin_lock_irqsave(&ddr_freq_lock, flags);

	if (cpu_is_mx50())
		ret = update_ddr_freq(ddr_rate);

#if 1
{
	unsigned int reg;
    printk(KERN_NOTICE "set_ddr_freq ddr_rate =%d ret = %d \n",ddr_rate, ret);

	reg = __raw_readl(MXC_CCM_CLK_DDR);
    printk(KERN_NOTICE "after ddr divider = 0x%x \n",reg&0x3f);
}
#endif

	spin_unlock_irqrestore(&ddr_freq_lock, flags);
	if (!ret)
		cur_ddr_rate = ddr_rate;
	udelay(100);
}
Ejemplo n.º 4
0
void set_ddr_freq(int ddr_rate)
{
	unsigned long flags;
	unsigned int ret = 0;

	spin_lock_irqsave(&ddr_freq_lock, flags);

	if (cpu_is_mx50())
		ret = update_ddr_freq(ddr_rate);

	spin_unlock_irqrestore(&ddr_freq_lock, flags);
	if (!ret)
		cur_ddr_rate = ddr_rate;
	udelay(100);
}
Ejemplo n.º 5
0
/* Set the DDR to either 528MHz or 400MHz for MX6q
 * or 400MHz for MX6DL.
 */
int set_high_bus_freq(int high_bus_freq)
{
	if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
		cancel_delayed_work_sync(&low_bus_freq_handler);

	if (busfreq_suspended)
		return 0;


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

	if (cpu_is_mx6sl())
		high_bus_freq = 1;

	if (high_bus_freq_mode && high_bus_freq)
		return 0;


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

	if (cpu_is_mx6dl() && high_bus_freq)
		high_bus_freq = 0;

	if (cpu_is_mx6dl() && med_bus_freq_mode)
		return 0;

	if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
	    (med_bus_freq_mode && !high_bus_freq && lp_med_freq &&
	     !lp_high_freq))
		return 0;

	if (cpu_is_mx6sl()) {
		u32 reg;
		unsigned long flags;
		u32 ttbr1;

		spin_lock_irqsave(&freq_lock, flags);
		/* sync the outer cache. */
		outer_sync();

		ttbr1 = save_ttbr1();

		/* Change DDR freq in IRAM. */
		mx6sl_ddr_freq_change_iram(ddr_normal_rate, low_bus_freq_mode);

		restore_ttbr1(ttbr1);

		spin_unlock_irqrestore(&freq_lock, flags);

		/* Set periph_clk to be sourced from pll2_pfd2_400M */
		/* First need to set the divider before changing the */
		/* parent if parent clock is larger than previous one */
		clk_set_rate(ahb_clk, clk_round_rate(ahb_clk,
						     LPAPM_CLK / 3));
		clk_set_rate(axi_clk,
			     clk_round_rate(axi_clk, LPAPM_CLK / 2));
		clk_set_parent(periph_clk, pll2_400);

		if (low_bus_freq_mode) {
			/* Now move ARM to be sourced from PLL2_400 too. */
			clk_set_parent(pll1_sw_clk, pll2_400);

			/* Ensure that the clock will be at original speed. */
			reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
			while (__raw_readl(MXC_CCM_CDHIPR))
				;
			clk_disable(pll1);
		}
		high_bus_freq_mode = 1;
		low_bus_freq_mode = 0;
		audio_bus_freq_mode = 0;
	} else {
		clk_enable(pll3);
		if (high_bus_freq) {
			update_ddr_freq(ddr_normal_rate);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2);
			if (med_bus_freq_mode)
				clk_disable(pll2_400);
			high_bus_freq_mode = 1;
			med_bus_freq_mode = 0;
		} else {
			clk_enable(pll2_400);
			update_ddr_freq(ddr_med_rate);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2_400);
			high_bus_freq_mode = 0;
			med_bus_freq_mode = 1;
		}
		if (audio_bus_freq_mode)
			clk_disable(pll2_400);

		/* AXI_CLK is sourced from PLL3_PFD_540 on MX6DL */
		if (cpu_is_mx6dl() &&
			clk_get_parent(axi_clk) != pll3_540)
			clk_set_parent(axi_clk, pll3_540);

		low_bus_freq_mode = 0;
		audio_bus_freq_mode = 0;

		clk_disable(pll3);
	}
	return 0;
}
Ejemplo n.º 6
0
void reduce_bus_freq(void)
{
	if (!cpu_is_mx6sl()) {
		if (cpu_is_mx6dl() &&
			(clk_get_parent(axi_clk) != periph_clk))
			/* Set the axi_clk to be sourced from the periph_clk.
			  * So that its frequency can be lowered down to 50MHz
			  * or 24MHz as the case may be.
			  */
			clk_set_parent(axi_clk, periph_clk);

		clk_enable(pll3);
		if (lp_audio_freq) {
			/* Need to ensure that PLL2_PFD_400M is kept ON. */
			clk_enable(pll2_400);
			update_ddr_freq(DDR_AUDIO_CLK);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2_200);
			audio_bus_freq_mode = 1;
			low_bus_freq_mode = 0;
		} else {
			update_ddr_freq(LPAPM_CLK);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, osc_clk);
			if (audio_bus_freq_mode)
				clk_disable(pll2_400);
			low_bus_freq_mode = 1;
			audio_bus_freq_mode = 0;
		}

		if (med_bus_freq_mode)
			clk_disable(pll2_400);

		clk_disable(pll3);
		med_bus_freq_mode = 0;
	} else {
		u32 reg;
		u32  div;
		unsigned long flags;

		if (high_bus_freq_mode) {
			/* Set periph_clk to be sourced from OSC_CLK */
			/* Set AXI to 24MHz. */
			clk_set_parent(periph_clk, osc_clk);
			clk_set_rate(axi_clk,
				clk_round_rate(axi_clk, LPAPM_CLK));
			/* Set AHB to 24MHz. */
			clk_set_rate(ahb_clk,
				clk_round_rate(ahb_clk, LPAPM_CLK));
		}
		if (lp_audio_freq) {
			u32 ttbr1;
			/* PLL2 is on in this mode, as DDR is at 100MHz. */
			/* Now change DDR freq while running from IRAM. */

			/* Set AHB to 24MHz. */
			clk_set_rate(ahb_clk,
				clk_round_rate(ahb_clk, LPAPM_CLK / 3));

			spin_lock_irqsave(&freq_lock, flags);
			/* sync the outer cache. */
			outer_sync();

			/* Save TTBR1 */
			ttbr1 = save_ttbr1();

			mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK,
							low_bus_freq_mode);
			restore_ttbr1(ttbr1);

			spin_unlock_irqrestore(&freq_lock, flags);

			if (low_bus_freq_mode) {
				/* Swtich ARM to run off PLL2_PFD2_400MHz
				 * since DDR is anyway at 100MHz.
				 */
				clk_set_parent(pll1_sw_clk, pll2_400);

				/* Ensure that the clock will be
				  * at original speed.
				  */
				reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
				while (__raw_readl(MXC_CCM_CDHIPR))
					;
				/* We have enabled PLL1 in the code below when
				  * ARM is from PLL1, so disable it here.
				  */
				clk_disable(pll1);
			}
			low_bus_freq_mode = 0;
			audio_bus_freq_mode = 1;
		} else {
			u32 ttbr1;
			/* Set MMDC clk to 24MHz. */
			/* Since we are going to set PLL2 in bypass mode,
			  * move the CPU clock off PLL2.
			  */
			/* Ensure that the clock will be at
			  * lowest possible freq.
			  */
			org_arm_podf = __raw_readl(MXC_CCM_CACRR);
			/* Need to enable PLL1 before setting its rate. */
			clk_enable(pll1);
			clk_set_rate(pll1,
				cpu_op_tbl[cpu_op_nr - 1].pll_lpm_rate);
			div = clk_get_rate(pll1) /
					cpu_op_tbl[cpu_op_nr - 1].cpu_rate;

			reg = __raw_writel(div - 1, MXC_CCM_CACRR);
			while (__raw_readl(MXC_CCM_CDHIPR))
				;
			clk_set_parent(pll1_sw_clk, pll1);

			spin_lock_irqsave(&freq_lock, flags);
			/* sync the outer cache. */
			outer_sync();

			ttbr1 = save_ttbr1();
			/* Now change DDR freq while running from IRAM. */
			mx6sl_ddr_freq_change_iram(LPAPM_CLK,
					low_bus_freq_mode);
			restore_ttbr1(ttbr1);

			spin_unlock_irqrestore(&freq_lock, flags);

			low_bus_freq_mode = 1;
			audio_bus_freq_mode = 0;
		}
	}
	high_bus_freq_mode = 0;

}