lkml.org 
[lkml]   [2015]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 1/2] clk: fractional-divider: switch to rational best approximation
Date
This patch converts the code to use rational best approximation algorithm which
is more precise.

Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/clk/Kconfig | 3 +--
drivers/clk/clk-fractional-divider.c | 39 ++++++++++++++----------------------
2 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 0b474a0..46d90a9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -14,6 +14,7 @@ config COMMON_CLK
select HAVE_CLK_PREPARE
select CLKDEV_LOOKUP
select SRCU
+ select RATIONAL
---help---
The common clock framework is a single definition of struct
clk, useful across many platforms, as well as an
@@ -63,7 +64,6 @@ config COMMON_CLK_SI5351
tristate "Clock driver for SiLabs 5351A/B/C"
depends on I2C
select REGMAP_I2C
- select RATIONAL
---help---
This driver supports Silicon Labs 5351A/B/C programmable clock
generators.
@@ -139,7 +139,6 @@ config COMMON_CLK_CDCE706
tristate "Clock driver for TI CDCE706 clock synthesizer"
depends on I2C
select REGMAP_I2C
- select RATIONAL
---help---
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.

diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 6aa72d9..9c53704 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -7,13 +7,14 @@
*
* Adjustable fractional divider clock implementation.
* Output rate = (m / n) * parent_rate.
+ * Uses rational best approximation algorithm.
*/

#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
-#include <linux/gcd.h>
+#include <linux/rational.h>

#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)

@@ -21,9 +22,9 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long m, n;
unsigned long flags = 0;
- u32 val, m, n;
- u64 ret;
+ u32 val;

if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
@@ -39,30 +40,22 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
if (!n || !m)
return parent_rate;

- ret = (u64)parent_rate * m;
- do_div(ret, n);
-
- return ret;
+ return mult_frac(parent_rate, m, n);
}

static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+ unsigned long *parent_rate)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- unsigned maxn = (fd->nmask >> fd->nshift) + 1;
- unsigned div;
+ unsigned long m, n;

- if (!rate || rate >= *prate)
- return *prate;
+ if (!rate || rate >= *parent_rate)
+ return *parent_rate;

- div = gcd(*prate, rate);
-
- while ((*prate / div) > maxn) {
- div <<= 1;
- rate <<= 1;
- }
+ rational_best_approximation(rate, *parent_rate,
+ fd->mmask >> fd->mshift, fd->nmask >> fd->nshift, &m, &n);

- return rate;
+ return mult_frac(rate, m, n);
}

static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -70,13 +63,11 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
- unsigned long div;
- unsigned n, m;
+ unsigned long n, m;
u32 val;

- div = gcd(parent_rate, rate);
- m = rate / div;
- n = parent_rate / div;
+ rational_best_approximation(rate, parent_rate,
+ fd->mmask >> fd->mshift, fd->nmask >> fd->nshift, &m, &n);

if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
--
2.1.4


\
 
 \ /
  Last update: 2015-03-30 21:41    [W:0.095 / U:0.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site