Commit 4e7cf74f authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Stephen Boyd
Browse files

clk: fractional-divider: Export approximation algorithm to the CCF users



At least one user currently duplicates some functions that are provided
by fractional divider module. Let's export approximation algorithm and
replace the open-coded variant.

As a bonus the exported function will get better documentation in place.

Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: default avatarHeiko Stuebner <heiko@sntech.de>
Acked-by: default avatarHeiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20210812170025.67074-1-andriy.shevchenko@linux.intel.com


[sboyd@kernel.org: Add header guard because why not]
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent e73f0f0e
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/slab.h>
#include <linux/rational.h>

#include "clk-fractional-divider.h"

static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
{
	if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
@@ -68,7 +70,8 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
	return ret;
}

static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate,
void clk_fractional_divider_general_approximation(struct clk_hw *hw,
						  unsigned long rate,
						  unsigned long *parent_rate,
						  unsigned long *m, unsigned long *n)
{
@@ -102,7 +105,7 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
	if (fd->approximation)
		fd->approximation(hw, rate, parent_rate, &m, &n);
	else
		clk_fd_general_approximation(hw, rate, parent_rate, &m, &n);
		clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);

	ret = (u64)*parent_rate * m;
	do_div(ret, n);
+13 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _CLK_FRACTIONAL_DIV_H
#define _CLK_FRACTIONAL_DIV_H

struct clk_hw;

void clk_fractional_divider_general_approximation(struct clk_hw *hw,
						  unsigned long rate,
						  unsigned long *parent_rate,
						  unsigned long *m,
						  unsigned long *n);

#endif
+3 −14
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
#include <linux/regmap.h>
#include <linux/reboot.h>
#include <linux/rational.h>

#include "../clk-fractional-divider.h"
#include "clk.h"

/*
@@ -178,10 +180,8 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
		unsigned long rate, unsigned long *parent_rate,
		unsigned long *m, unsigned long *n)
{
	struct clk_fractional_divider *fd = to_clk_fd(hw);
	unsigned long p_rate, p_parent_rate;
	struct clk_hw *p_parent;
	unsigned long scale;

	p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
	if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
@@ -190,18 +190,7 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
		*parent_rate = p_parent_rate;
	}

	/*
	 * Get rate closer to *parent_rate to guarantee there is no overflow
	 * for m and n. In the result it will be the nearest rate left shifted
	 * by (scale - fd->nwidth) bits.
	 */
	scale = fls_long(*parent_rate / rate - 1);
	if (scale > fd->nwidth)
		rate <<= scale - fd->nwidth;

	rational_best_approximation(rate, *parent_rate,
			GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
			m, n);
	clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
}

static struct clk *rockchip_clk_register_frac_branch(