Merge tag 'omap-for-v3.17/soc-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / arm / mach-omap2 / clkt_dpll.c
index b2ff6cd..f251a14 100644 (file)
@@ -285,10 +285,13 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        int m, n, r, scaled_max_m;
+       int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
        unsigned long scaled_rt_rp;
        unsigned long new_rate = 0;
        struct dpll_data *dd;
        unsigned long ref_rate;
+       long delta;
+       long prev_min_delta = LONG_MAX;
        const char *clk_name;
 
        if (!clk || !clk->dpll_data)
@@ -334,23 +337,34 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
                if (r == DPLL_MULT_UNDERFLOW)
                        continue;
 
+               /* skip rates above our target rate */
+               delta = target_rate - new_rate;
+               if (delta < 0)
+                       continue;
+
+               if (delta < prev_min_delta) {
+                       prev_min_delta = delta;
+                       min_delta_m = m;
+                       min_delta_n = n;
+               }
+
                pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
                         clk_name, m, n, new_rate);
 
-               if (target_rate == new_rate) {
-                       dd->last_rounded_m = m;
-                       dd->last_rounded_n = n;
-                       dd->last_rounded_rate = target_rate;
+               if (delta == 0)
                        break;
-               }
        }
 
-       if (target_rate != new_rate) {
+       if (prev_min_delta == LONG_MAX) {
                pr_debug("clock: %s: cannot round to rate %lu\n",
                         clk_name, target_rate);
                return ~0;
        }
 
-       return target_rate;
+       dd->last_rounded_m = min_delta_m;
+       dd->last_rounded_n = min_delta_n;
+       dd->last_rounded_rate = target_rate - prev_min_delta;
+
+       return dd->last_rounded_rate;
 }