示例#1
0
文件: clock24xx.c 项目: 274914765/C
/* Sets basic clocks based on the specified rate */
static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
{
    u32 cur_rate, done_rate, bypass = 0, tmp;
    struct prcm_config *prcm;
    unsigned long found_speed = 0;
    unsigned long flags;

    if (clk != &virt_prcm_set)
        return -EINVAL;

    for (prcm = rate_table; prcm->mpu_speed; prcm++) {
        if (!(prcm->flags & cpu_mask))
            continue;

        if (prcm->xtal_speed != sys_ck.rate)
            continue;

        if (prcm->mpu_speed <= rate) {
            found_speed = prcm->mpu_speed;
            break;
        }
    }

    if (!found_speed) {
        printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
               rate / 1000000);
        return -EINVAL;
    }

    curr_prcm_set = prcm;
    cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);

    if (prcm->dpll_speed == cur_rate / 2) {
        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
    } else if (prcm->dpll_speed == cur_rate * 2) {
        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
    } else if (prcm->dpll_speed != cur_rate) {
        local_irq_save(flags);

        if (prcm->dpll_speed == prcm->xtal_speed)
            bypass = 1;

        if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
            CORE_CLK_SRC_DPLL_X2)
            done_rate = CORE_CLK_SRC_DPLL_X2;
        else
            done_rate = CORE_CLK_SRC_DPLL;

        /* MPU divider */
        cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);

        /* dsp + iva1 div(2420), iva2.1(2430) */
        cm_write_mod_reg(prcm->cm_clksel_dsp,
                 OMAP24XX_DSP_MOD, CM_CLKSEL);

        cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);

        /* Major subsystem dividers */
        tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
        cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
        if (cpu_is_omap2430())
            cm_write_mod_reg(prcm->cm_clksel_mdm,
                     OMAP2430_MDM_MOD, CM_CLKSEL);

        /* x2 to enter init_mem */
        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);

        omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
                   bypass);

        omap2_init_memory_params(omap2_dll_force_needed());
        omap2_reprogram_sdrc(done_rate, 0);

        local_irq_restore(flags);
    }
    omap2_dpll_recalc(&dpll_ck);

    return 0;
}
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
{
	u32 cur_rate, low, mult, div, valid_rate, done_rate;
	u32 bypass = 0;
	struct prcm_config tmpset;
	const struct dpll_data *dd;

	cur_rate = omap2xxx_clk_get_core_rate(dclk);
	mult = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	mult &= OMAP24XX_CORE_CLK_SRC_MASK;

	if ((rate == (cur_rate / 2)) && (mult == 2)) {
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
	} else if (rate != cur_rate) {
		valid_rate = omap2_dpllcore_round_rate(rate);
		if (valid_rate != rate)
			return -EINVAL;

		if (mult == 1)
			low = curr_prcm_set->dpll_speed;
		else
			low = curr_prcm_set->dpll_speed / 2;

		dd = clk->dpll_data;
		if (!dd)
			return -EINVAL;

		tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
					   dd->div1_mask);
		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
		tmpset.cm_clksel2_pll = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
		if (rate > low) {
			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
			mult = ((rate / 2) / 1000000);
			done_rate = CORE_CLK_SRC_DPLL_X2;
		} else {
			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
			mult = (rate / 1000000);
			done_rate = CORE_CLK_SRC_DPLL;
		}
		tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
		tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));

		/* Worst case */
		tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;

		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
			bypass = 1;

		/* For omap2xxx_sdrc_init_params() */
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);

		/* Force dll lock mode */
		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
			       bypass);

		/* Errata: ret dll entry state */
		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
		omap2xxx_sdrc_reprogram(done_rate, 0);
	}

	return 0;
}
示例#3
0
文件: clock24xx.c 项目: 274914765/C
static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
{
    u32 cur_rate, low, mult, div, valid_rate, done_rate;
    u32 bypass = 0;
    struct prcm_config tmpset;
    const struct dpll_data *dd;
    unsigned long flags;
    int ret = -EINVAL;

    local_irq_save(flags);
    cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
    mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
    mult &= OMAP24XX_CORE_CLK_SRC_MASK;

    if ((rate == (cur_rate / 2)) && (mult == 2)) {
        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
    } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
    } else if (rate != cur_rate) {
        valid_rate = omap2_dpll_round_rate(rate);
        if (valid_rate != rate)
            goto dpll_exit;

        if (mult == 1)
            low = curr_prcm_set->dpll_speed;
        else
            low = curr_prcm_set->dpll_speed / 2;

        dd = clk->dpll_data;
        if (!dd)
            goto dpll_exit;

        tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
        tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
                       dd->div1_mask);
        div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
        tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
        tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
        if (rate > low) {
            tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
            mult = ((rate / 2) / 1000000);
            done_rate = CORE_CLK_SRC_DPLL_X2;
        } else {
            tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
            mult = (rate / 1000000);
            done_rate = CORE_CLK_SRC_DPLL;
        }
        tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
        tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));

        /* Worst case */
        tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;

        if (rate == curr_prcm_set->xtal_speed)    /* If asking for 1-1 */
            bypass = 1;

        omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */

        /* Force dll lock mode */
        omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
                   bypass);

        /* Errata: ret dll entry state */
        omap2_init_memory_params(omap2_dll_force_needed());
        omap2_reprogram_sdrc(done_rate, 0);
    }
    omap2_dpll_recalc(&dpll_ck);
    ret = 0;

dpll_exit:
    local_irq_restore(flags);
    return(ret);
}
示例#4
0
/* Sets basic clocks based on the specified rate */
static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
{
    u32 cur_rate, done_rate, bypass = 0, tmp;
    struct prcm_config *prcm;
    unsigned long flags, found_speed;

    if (clk != &virt_prcm_set)
        return -EINVAL;

    found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm);
    if (!found_speed) {
        printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
               rate / 1000000);
        return -EINVAL;
    }

    curr_prcm_set = prcm;
    cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);

    if (prcm->dpll_speed == cur_rate / 2) {
        omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
    } else if (prcm->dpll_speed == cur_rate * 2) {
        omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
    } else if (prcm->dpll_speed != cur_rate) {
        local_irq_save(flags);

        if (prcm->dpll_speed == prcm->xtal_speed)
            bypass = 1;

        if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
                CORE_CLK_SRC_DPLL_X2)
            done_rate = CORE_CLK_SRC_DPLL_X2;
        else
            done_rate = CORE_CLK_SRC_DPLL;

        /* MPU divider */
        cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);

        /* dsp + iva1 div(2420), iva2.1(2430) */
        cm_write_mod_reg(prcm->cm_clksel_dsp,
                         OMAP24XX_DSP_MOD, CM_CLKSEL);

        cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);

        /* Major subsystem dividers */
        tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
        cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
                         CM_CLKSEL1);

        if (cpu_is_omap2430())
            cm_write_mod_reg(prcm->cm_clksel_mdm,
                             OMAP2430_MDM_MOD, CM_CLKSEL);

        /* x2 to enter omap2xxx_sdrc_init_params() */
        omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);

        omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
                       bypass);

        omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
        omap2xxx_sdrc_reprogram(done_rate, 0);

        local_irq_restore(flags);
    }

    return 0;
}