OMAP3: allow to disable UART4
[pandora-kernel.git] / arch / arm / mach-omap2 / clkt34xx_dpll3m2.c
index d6e34dd..caae8b7 100644 (file)
@@ -55,20 +55,46 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        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)
@@ -104,19 +130,22 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 
        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;
 }