Skip to content

Commit

Permalink
clk: sunxi-ng: Remove the use of rational computations
Browse files Browse the repository at this point in the history
While the rational library works great, it doesn't really allow us to add
more constraints, like the minimum.

Remove that in order to be able to deal with the constraints we'll need.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
  • Loading branch information
Maxime Ripard committed Oct 25, 2016
1 parent a501a14 commit ee28648
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 51 deletions.
3 changes: 0 additions & 3 deletions drivers/clk/sunxi-ng/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,14 @@ config SUNXI_CCU_NK

config SUNXI_CCU_NKM
bool
select RATIONAL
select SUNXI_CCU_GATE

config SUNXI_CCU_NKMP
bool
select RATIONAL
select SUNXI_CCU_GATE

config SUNXI_CCU_NM
bool
select RATIONAL
select SUNXI_CCU_FRAC
select SUNXI_CCU_GATE

Expand Down
31 changes: 15 additions & 16 deletions drivers/clk/sunxi-ng/ccu_nkm.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/

#include <linux/clk-provider.h>
#include <linux/rational.h>

#include "ccu_gate.h"
#include "ccu_nkm.h"
Expand All @@ -28,21 +27,21 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
unsigned long _n, _k, _m;

for (_k = 1; _k <= nkm->max_k; _k++) {
unsigned long tmp_rate;

rational_best_approximation(rate / _k, parent,
nkm->max_n, nkm->max_m, &_n, &_m);

tmp_rate = parent * _n * _k / _m;

if (tmp_rate > rate)
continue;

if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
best_n = _n;
best_k = _k;
best_m = _m;
for (_n = 1; _n <= nkm->max_n; _n++) {
for (_m = 1; _n <= nkm->max_m; _m++) {
unsigned long tmp_rate;

tmp_rate = parent * _n * _k / _m;

if (tmp_rate > rate)
continue;
if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
best_n = _n;
best_k = _k;
best_m = _m;
}
}
}
}

Expand Down
37 changes: 18 additions & 19 deletions drivers/clk/sunxi-ng/ccu_nkmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/

#include <linux/clk-provider.h>
#include <linux/rational.h>

#include "ccu_gate.h"
#include "ccu_nkmp.h"
Expand All @@ -29,24 +28,24 @@ 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 = 1; _p <= nkmp->max_p; _p <<= 1) {
unsigned long tmp_rate;

rational_best_approximation(rate / _k, parent / _p,
nkmp->max_n, nkmp->max_m,
&_n, &_m);

tmp_rate = parent * _n * _k / (_m * _p);

if (tmp_rate > rate)
continue;

if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
best_n = _n;
best_k = _k;
best_m = _m;
best_p = _p;
for (_n = 1; _n <= nkmp->max_n; _n++) {
for (_m = 1; _n <= nkmp->max_m; _m++) {
for (_p = 1; _p <= nkmp->max_p; _p <<= 1) {
unsigned long tmp_rate;

tmp_rate = parent * _n * _k / (_m * _p);

if (tmp_rate > rate)
continue;

if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
best_n = _n;
best_k = _k;
best_m = _m;
best_p = _p;
}
}
}
}
}
Expand Down
54 changes: 41 additions & 13 deletions drivers/clk/sunxi-ng/ccu_nm.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,42 @@
*/

#include <linux/clk-provider.h>
#include <linux/rational.h>

#include "ccu_frac.h"
#include "ccu_gate.h"
#include "ccu_nm.h"

struct _ccu_nm {
unsigned long n, max_n;
unsigned long m, max_m;
};

static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
struct _ccu_nm *nm)
{
unsigned long best_rate = 0;
unsigned long best_n = 0, best_m = 0;
unsigned long _n, _m;

for (_n = 1; _n <= nm->max_n; _n++) {
for (_m = 1; _n <= nm->max_m; _m++) {
unsigned long tmp_rate = parent * _n / _m;

if (tmp_rate > rate)
continue;

if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
best_n = _n;
best_m = _m;
}
}
}

nm->n = best_n;
nm->m = best_m;
}

static void ccu_nm_disable(struct clk_hw *hw)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
Expand Down Expand Up @@ -61,43 +91,41 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
unsigned long max_n, max_m;
unsigned long n, m;
struct _ccu_nm _nm;

max_n = 1 << nm->n.width;
max_m = nm->m.max ?: 1 << nm->m.width;
_nm.max_n = 1 << nm->n.width;
_nm.max_m = nm->m.max ?: 1 << nm->m.width;

rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m);
ccu_nm_find_best(*parent_rate, rate, &_nm);

return *parent_rate * n / m;
return *parent_rate * _nm.n / _nm.m;
}

static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
struct _ccu_nm _nm;
unsigned long flags;
unsigned long max_n, max_m;
unsigned long n, m;
u32 reg;

if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate);
else
ccu_frac_helper_disable(&nm->common, &nm->frac);

max_n = 1 << nm->n.width;
max_m = nm->m.max ?: 1 << nm->m.width;
_nm.max_n = 1 << nm->n.width;
_nm.max_m = nm->m.max ?: 1 << nm->m.width;

rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m);
ccu_nm_find_best(parent_rate, rate, &_nm);

spin_lock_irqsave(nm->common.lock, flags);

reg = readl(nm->common.base + nm->common.reg);
reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift);
reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);

writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift),
nm->common.base + nm->common.reg);

spin_unlock_irqrestore(nm->common.lock, flags);
Expand Down

0 comments on commit ee28648

Please sign in to comment.