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: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Heiko 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: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
e73f0f0ee7
commit
4e7cf74fa3
@ -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
drivers/clk/clk-fractional-divider.h
Normal file
13
drivers/clk/clk-fractional-divider.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* 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
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user