Commit 5723879c authored by Frank Oltmanns's avatar Frank Oltmanns Committed by Jernej Skrabec
Browse files

clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate



The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Reviewed-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: default avatarFrank Oltmanns <frank@oltmanns.dev>
Link: https://lore.kernel.org/r/20240310-pinephone-pll-fixes-v4-3-46fc80c83637@oltmanns.dev


Signed-off-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
parent 4cece764
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -16,6 +16,20 @@ struct _ccu_nkm {
	unsigned long	m, min_m, max_m;
};

static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long parent,
				  unsigned long n, unsigned long m)
{
	struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);

	if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
		return false;

	if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
		return false;

	return true;
}

static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common,
						       struct clk_hw *parent_hw,
						       unsigned long *parent, unsigned long rate,
@@ -31,6 +45,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
				unsigned long tmp_rate, tmp_parent;

				tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k));

				if (!ccu_nkm_is_valid_rate(common, tmp_parent, _n, _m))
					continue;

				tmp_rate = tmp_parent * _n * _k / _m;

				if (ccu_is_better_rate(common, rate, tmp_rate, best_rate) ||
@@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
	for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
		for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
			for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
				if (!ccu_nkm_is_valid_rate(common, parent, _n, _m))
					continue;

				unsigned long tmp_rate;

				tmp_rate = parent * _n * _k / _m;
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ struct ccu_nkm {
	struct ccu_mux_internal	mux;

	unsigned int		fixed_post_div;
	unsigned long		max_m_n_ratio;
	unsigned long		min_parent_m_ratio;

	struct ccu_common	common;
};