Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee28648c authored by Maxime Ripard's avatar Maxime Ripard
Browse files

clk: sunxi-ng: Remove the use of rational computations



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: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: default avatarChen-Yu Tsai <wens@csie.org>
parent a501a14e
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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

+15 −16
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@
 */

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

#include "ccu_gate.h"
#include "ccu_nkm.h"
@@ -28,16 +27,14 @@ 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++) {
		for (_n = 1; _n <= nkm->max_n; _n++) {
			for (_m = 1; _n <= nkm->max_m; _m++) {
				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;
@@ -45,6 +42,8 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
					best_m = _m;
				}
			}
		}
	}

	nkm->n = best_n;
	nkm->k = best_k;
+18 −19
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@
 */

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

#include "ccu_gate.h"
#include "ccu_nkmp.h"
@@ -29,13 +28,11 @@ 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 (_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;

			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)
@@ -50,6 +47,8 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
					}
				}
			}
		}
	}

	nkmp->n = best_n;
	nkmp->k = best_k;
+41 −13
Original line number Diff line number Diff line
@@ -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);
@@ -61,24 +91,22 @@ 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))
@@ -86,10 +114,10 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long 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);

@@ -97,7 +125,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
	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);