Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1701214 > unrolled thread

[PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter

Started byHeiko Stuebner <heiko@sntech.de>
First post2017-08-01 18:30 +0200
Last post2017-08-08 18:00 +0200
Articles 3 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter Heiko Stuebner <heiko@sntech.de> - 2017-08-01 18:30 +0200
    Re: [PATCH 2/2] clk: rockchip: add special approximation to fix up  fractional clk's jitter Elaine Zhang <zhangqing@rock-chips.com> - 2017-08-02 05:50 +0200
    Re: [PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter Heiko Stuebner <heiko@sntech.de> - 2017-08-08 18:00 +0200

#1701214 — [PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter

FromHeiko Stuebner <heiko@sntech.de>
Date2017-08-01 18:30 +0200
Subject[PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter
Message-ID<u9Ids-6fm-23@gated-at.bofh.it>
From: Elaine Zhang <zhangqing@rock-chips.com>

From Rockchips fractional divider description:
  3.1.9  Fractional divider usage
  To get specific frequency, clocks of I2S, SPDIF, UARTcan be generated by
  fractional divider. Generally you must set that denominator is 20 times
  larger than numerator to generate precise clock frequency. So the
  fractional divider applies only to generate low frequency clock like
  I2S, UART.

Therefore add a special approximation function that handles this
special requirement.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index fe1d393cf678..b6db79a00602 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -29,6 +29,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/reboot.h>
+#include <linux/rational.h>
 #include "clk.h"
 
 /**
@@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
 	return notifier_from_errno(ret);
 }
 
+/**
+ * fractional divider must set that denominator is 20 times larger than
+ * numerator to generate precise clock frequency.
+ */
+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)) {
+		p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
+		p_parent_rate = clk_hw_get_rate(p_parent);
+		*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);
+}
+
 static struct clk *rockchip_clk_register_frac_branch(
 		struct rockchip_clk_provider *ctx, const char *name,
 		const char *const *parent_names, u8 num_parents,
@@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch(
 	div->nwidth = 16;
 	div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
 	div->lock = lock;
+	div->approximation = rockchip_fractional_approximation;
 	div_ops = &clk_fractional_divider_ops;
 
 	clk = clk_register_composite(NULL, name, parent_names, num_parents,
-- 
2.11.0

[toc] | [next] | [standalone]


#1701687 — Re: [PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter

FromElaine Zhang <zhangqing@rock-chips.com>
Date2017-08-02 05:50 +0200
SubjectRe: [PATCH 2/2] clk: rockchip: add special approximation to fix up fractional clk's jitter
Message-ID<u9SPw-4x2-13@gated-at.bofh.it>
In reply to#1701214

On 08/02/2017 12:22 AM, Heiko Stuebner wrote:
> From: Elaine Zhang <zhangqing@rock-chips.com>
>
>>From Rockchips fractional divider description:
>    3.1.9  Fractional divider usage
>    To get specific frequency, clocks of I2S, SPDIF, UARTcan be generated by
>    fractional divider. Generally you must set that denominator is 20 times
>    larger than numerator to generate precise clock frequency. So the
>    fractional divider applies only to generate low frequency clock like
>    I2S, UART.
>
> Therefore add a special approximation function that handles this
> special requirement.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>   drivers/clk/rockchip/clk.c | 36 ++++++++++++++++++++++++++++++++++++
>   1 file changed, 36 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
> index fe1d393cf678..b6db79a00602 100644
> --- a/drivers/clk/rockchip/clk.c
> +++ b/drivers/clk/rockchip/clk.c
> @@ -29,6 +29,7 @@
>   #include <linux/mfd/syscon.h>
>   #include <linux/regmap.h>
>   #include <linux/reboot.h>
> +#include <linux/rational.h>
>   #include "clk.h"
>
>   /**
> @@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
>   	return notifier_from_errno(ret);
>   }
>
> +/**
> + * fractional divider must set that denominator is 20 times larger than
> + * numerator to generate precise clock frequency.
> + */
> +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)) {
> +		p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
> +		p_parent_rate = clk_hw_get_rate(p_parent);
> +		*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);
> +}
> +
>   static struct clk *rockchip_clk_register_frac_branch(
>   		struct rockchip_clk_provider *ctx, const char *name,
>   		const char *const *parent_names, u8 num_parents,
> @@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch(
>   	div->nwidth = 16;
>   	div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
>   	div->lock = lock;
> +	div->approximation = rockchip_fractional_approximation;
>   	div_ops = &clk_fractional_divider_ops;
>
>   	clk = clk_register_composite(NULL, name, parent_names, num_parents,
>
Tested-by: Elaine Zhang <zhangqing@rock-chips.com>

[toc] | [prev] | [next] | [standalone]


#1706709

FromHeiko Stuebner <heiko@sntech.de>
Date2017-08-08 18:00 +0200
Message-ID<ucf5i-258-65@gated-at.bofh.it>
In reply to#1701214
Am Dienstag, 1. August 2017, 18:22:24 CEST schrieb Heiko Stuebner:
> From: Elaine Zhang <zhangqing@rock-chips.com>
> 
> From Rockchips fractional divider description:
>   3.1.9  Fractional divider usage
>   To get specific frequency, clocks of I2S, SPDIF, UARTcan be generated by
>   fractional divider. Generally you must set that denominator is 20 times
>   larger than numerator to generate precise clock frequency. So the
>   fractional divider applies only to generate low frequency clock like
>   I2S, UART.
> 
> Therefore add a special approximation function that handles this
> special requirement.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>

applied for 4.14


Heiko

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web