unsigned long validrate, sdrcrate, _mpurate;
struct omap_sdrc_params *sdrc_cs0;
struct omap_sdrc_params *sdrc_cs1;
+ u32 cm_clksel1_pll;
+ struct dpll_data *dd;
int ret;
if (!clk || !rate)
return -EINVAL;
- validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
- if (validrate != rate)
+ if (!clk->parent || !clk->parent->dpll_data)
return -EINVAL;
+ dd = clk->parent->dpll_data;
+ cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
+
+ validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+ if (validrate == rate) {
+ cm_clksel1_pll &= ~clk->clksel_mask;
+ cm_clksel1_pll |= new_div << __ffs(clk->clksel_mask);
+ } else {
+ rate = omap2_dpll_round_rate(clk->parent, rate);
+ if (rate == ~0)
+ return -EINVAL;
+
+ cm_clksel1_pll &= ~(dd->mult_mask | dd->div1_mask | clk->clksel_mask);
+ cm_clksel1_pll |= dd->last_rounded_m << __ffs(dd->mult_mask);
+ cm_clksel1_pll |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
+ cm_clksel1_pll |= 1 << __ffs(clk->clksel_mask);
+
+ validrate = rate;
+ }
+
+#if 0
sdrcrate = sdrc_ick_p->rate;
if (rate > clk->rate)
sdrcrate <<= ((rate / clk->rate) >> 1);
else
sdrcrate >>= ((clk->rate / rate) >> 1);
+#else
+ /* HACK! */
+ sdrcrate = rate / 2;
+#endif
ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
if (ret)
if (sdrc_cs1)
omap3_configure_core_dpll(
- new_div, unlock_dll, c, rate > clk->rate,
+ cm_clksel1_pll, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
else
omap3_configure_core_dpll(
- new_div, unlock_dll, c, rate > clk->rate,
+ cm_clksel1_pll, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
0, 0, 0, 0);
clk->rate = rate;
+ /* HACK */
+ clk->parent->rate = clk->parent->recalc(clk->parent);
+
return 0;
}