clk: fractional-divider: Export approximation algorithm to the CCF users
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Thu, 12 Aug 2021 17:00:22 +0000 (20:00 +0300)
committerStephen Boyd <sboyd@kernel.org>
Thu, 12 Aug 2021 19:41:47 +0000 (12:41 -0700)
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>
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-fractional-divider.h [new file with mode: 0644]
drivers/clk/rockchip/clk.c

index b1e556f..535d299 100644 (file)
@@ -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,9 +70,10 @@ 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,
-                                        unsigned long *parent_rate,
-                                        unsigned long *m, unsigned long *n)
+void clk_fractional_divider_general_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 scale;
@@ -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);
diff --git a/drivers/clk/clk-fractional-divider.h b/drivers/clk/clk-fractional-divider.h
new file mode 100644 (file)
index 0000000..a05649e
--- /dev/null
@@ -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
index 049e5e0..b7be7e1 100644 (file)
@@ -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(