Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[cascardo/linux.git] / drivers / clk / sunxi-ng / ccu_nkmp.c
index 9f2b98e..9769dee 100644 (file)
@@ -29,14 +29,14 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
        unsigned long _n, _k, _m, _p;
 
        for (_k = 1; _k <= nkmp->max_k; _k++) {
-               for (_p = 0; _p <= nkmp->max_p; _p++) {
+               for (_p = 1; _p <= nkmp->max_p; _p <<= 1) {
                        unsigned long tmp_rate;
 
-                       rational_best_approximation(rate / _k, parent >> _p,
+                       rational_best_approximation(rate / _k, parent / _p,
                                                    nkmp->max_n, nkmp->max_m,
                                                    &_n, &_m);
 
-                       tmp_rate = (parent * _n * _k >> _p) / _m;
+                       tmp_rate = parent * _n * _k / (_m * _p);
 
                        if (tmp_rate > rate)
                                continue;
@@ -110,13 +110,12 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
 
        _nkmp.max_n = 1 << nkmp->n.width;
        _nkmp.max_k = 1 << nkmp->k.width;
-       _nkmp.max_m = 1 << nkmp->m.width;
-       _nkmp.max_p = (1 << nkmp->p.width) - 1;
+       _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+       _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
-       ccu_nkmp_find_best(*parent_rate, rate,
-                          &_nkmp);
+       ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
 
-       return (*parent_rate * _nkmp.n * _nkmp.k >> _nkmp.p) / _nkmp.m;
+       return *parent_rate * _nkmp.n * _nkmp.k / (_nkmp.m * _nkmp.p);
 }
 
 static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -129,8 +128,8 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
 
        _nkmp.max_n = 1 << nkmp->n.width;
        _nkmp.max_k = 1 << nkmp->k.width;
-       _nkmp.max_m = 1 << nkmp->m.width;
-       _nkmp.max_p = (1 << nkmp->p.width) - 1;
+       _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+       _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
        ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
 
@@ -145,7 +144,7 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
        reg |= (_nkmp.n - 1) << nkmp->n.shift;
        reg |= (_nkmp.k - 1) << nkmp->k.shift;
        reg |= (_nkmp.m - 1) << nkmp->m.shift;
-       reg |= _nkmp.p << nkmp->p.shift;
+       reg |= ilog2(_nkmp.p) << nkmp->p.shift;
 
        writel(reg, nkmp->common.base + nkmp->common.reg);