int __init omap2_clk_init(void) { struct prcm_config *prcm; struct omap_clk *c; u32 clkrate; if (cpu_is_omap242x()) cpu_mask = RATE_IN_242X; else if (cpu_is_omap2430()) cpu_mask = RATE_IN_243X; clk_init(&omap2_clk_functions); for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) clk_init_one(c->lk.clk); osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); propagate_rate(&osc_ck); sys_ck.rate = omap2_sys_clk_recalc(&sys_ck); propagate_rate(&sys_ck); for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) if (c->cpu & cpu_mask) { clkdev_add(&c->lk); clk_register(c->lk.clk); } /* Check the MPU rate set by bootloader */ clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); for (prcm = rate_table; prcm->mpu_speed; prcm++) { if (!(prcm->flags & cpu_mask)) continue; if (prcm->xtal_speed != sys_ck.rate) continue; if (prcm->dpll_speed <= clkrate) break; } curr_prcm_set = prcm; recalculate_root_clocks(); printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " "%ld.%01ld/%ld/%ld MHz\n", (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; /* * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ clk_enable_init_clocks(); /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ vclk = clk_get(NULL, "virt_prcm_set"); sclk = clk_get(NULL, "sys_ck"); return 0; }
static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate, u8 rate_storage) { unsigned long rate; rate = omap2xxx_clk_get_core_rate(clk, parent_rate); if (rate_storage == CURRENT_RATE) clk->rate = rate; else if (rate_storage == TEMP_RATE) clk->temp_rate = rate; }
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; }
unsigned long omap2_dpllcore_recalc(struct clk *clk) { return omap2xxx_clk_get_core_rate(clk); }
/* Sets basic clocks based on the specified rate */ int omap2_select_table_rate(struct clk *clk, unsigned long rate) { u32 cur_rate, done_rate, bypass = 0, tmp; const struct prcm_config *prcm; unsigned long found_speed = 0; unsigned long flags; for (prcm = rate_table; prcm->mpu_speed; prcm++) { if (!(prcm->flags & cpu_mask)) continue; if (prcm->xtal_speed != sclk->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 = omap2xxx_clk_get_core_rate(dclk); 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; }
unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, unsigned long parent_rate) { return omap2xxx_clk_get_core_rate(); }
int __init omap2_clk_init(void) { struct prcm_config *prcm; struct clk **clkp; u32 clkrate; if (cpu_is_omap242x()) cpu_mask = RATE_IN_242X; else if (cpu_is_omap2430()) cpu_mask = RATE_IN_243X; clk_init(&omap2_clk_functions); omap2_osc_clk_recalc(&osc_ck, 0, CURRENT_RATE); omap2_sys_clk_recalc(&sys_ck, sys_ck.parent->rate, CURRENT_RATE); for (clkp = onchip_24xx_clks; clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks); clkp++) { if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) { clk_register(*clkp); continue; } if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) { clk_register(*clkp); continue; } } /* Check the MPU rate set by bootloader */ clkrate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate); for (prcm = rate_table; prcm->mpu_speed; prcm++) { if (!(prcm->flags & cpu_mask)) continue; if (prcm->xtal_speed != sys_ck.rate) continue; if (prcm->dpll_speed <= clkrate) break; } curr_prcm_set = prcm; recalculate_root_clocks(); printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " "%ld.%01ld/%ld/%ld MHz\n", (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; /* * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ clk_enable_init_clocks(); /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ vclk = clk_get(NULL, "virt_prcm_set"); sclk = clk_get(NULL, "sys_ck"); return 0; }