All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Implement set_rate for FAPLL on dm816x
@ 2015-03-22 22:35 Tony Lindgren
  2015-03-22 22:35 ` [PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors Tony Lindgren
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Tony Lindgren @ 2015-03-22 22:35 UTC (permalink / raw)
  To: Mike Turquette, Stephen Boyd; +Cc: linux-kernel, linux-omap

Hi all,

Here are few patches to implement set_rate for the FAPLL found
on dm816x.

Regards,

Tony


Tony Lindgren (3):
  clk: ti: Fix FAPLL recalc_rate for rounding errors
  clk: ti: Implement FAPLL set_rate for the synthesizer
  clk: ti: Implement FAPLL set_rate for the PLL

 drivers/clk/ti/fapll.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 262 insertions(+), 8 deletions(-)

-- 
2.1.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors
  2015-03-22 22:35 [PATCH 0/3] Implement set_rate for FAPLL on dm816x Tony Lindgren
@ 2015-03-22 22:35 ` Tony Lindgren
  2015-03-22 22:35 ` [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer Tony Lindgren
  2015-03-22 22:35 ` [PATCH 3/3] clk: ti: Implement FAPLL set_rate for the PLL Tony Lindgren
  2 siblings, 0 replies; 10+ messages in thread
From: Tony Lindgren @ 2015-03-22 22:35 UTC (permalink / raw)
  To: Mike Turquette, Stephen Boyd
  Cc: linux-kernel, linux-omap, Brian Hutchinson, Matthijs van Duin,
	Tero Kristo

We need to round the calculated value to have it match the requested rate.

While at it, let's fix a typo and use a define for SYNTH_MAX_DIV_M as we
will need it in later patches for set_rate.

And let's remove two unused includes.

Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/clk/ti/fapll.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index d216406..3b5e231 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -11,12 +11,10 @@
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
-#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
-#include <asm/div64.h>
 
 /* FAPLL Control Register PLL_CTRL */
 #define FAPLL_MAIN_LOCK		BIT(7)
@@ -49,6 +47,8 @@
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ		BIT(31)
 
+#define SYNTH_MAX_DIV_M		0xff
+
 struct fapll_data {
 	struct clk_hw hw;
 	void __iomem *base;
@@ -218,11 +218,10 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 		rate *= 8;
 	}
 
-	/* Synth ost-divider M */
-	synth_div_m = readl_relaxed(synth->div) & 0xff;
-	do_div(rate, synth_div_m);
+	/* Synth post-divider M */
+	synth_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
 
-	return rate;
+	return DIV_ROUND_UP_ULL(rate, synth_div_m);
 }
 
 static struct clk_ops ti_fapll_synt_ops = {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
  2015-03-22 22:35 [PATCH 0/3] Implement set_rate for FAPLL on dm816x Tony Lindgren
  2015-03-22 22:35 ` [PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors Tony Lindgren
@ 2015-03-22 22:35 ` Tony Lindgren
  2015-03-23 13:25     ` Tero Kristo
  2015-03-22 22:35 ` [PATCH 3/3] clk: ti: Implement FAPLL set_rate for the PLL Tony Lindgren
  2 siblings, 1 reply; 10+ messages in thread
From: Tony Lindgren @ 2015-03-22 22:35 UTC (permalink / raw)
  To: Mike Turquette, Stephen Boyd
  Cc: linux-kernel, linux-omap, Brian Hutchinson, Matthijs van Duin,
	Tero Kristo

We can pretty much get any rate out of the FAPLL because of the fractional
divider. Let's first try just adjusting the post divider, and if that is
not enough, then reprogram both the fractional divider and the post divider.

Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.

Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/clk/ti/fapll.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index 3b5e231..4064f7b 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
@@ -47,6 +48,8 @@
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ		BIT(31)
 
+#define SYNTH_PHASE_K		8
+#define SYNTH_MAX_INT_DIV	0xf
 #define SYNTH_MAX_DIV_M		0xff
 
 struct fapll_data {
@@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 	/*
 	 * Synth frequency integer and fractional divider.
 	 * Note that the phase output K is 8, so the result needs
-	 * to be multiplied by 8.
+	 * to be multiplied by SYNTH_PHASE_K.
 	 */
 	if (synth->freq) {
 		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
@@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
 		rate *= 10000000;
 		do_div(rate, synth_div_freq);
-		rate *= 8;
+		rate *= SYNTH_PHASE_K;
 	}
 
 	/* Synth post-divider M */
@@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 	return DIV_ROUND_UP_ULL(rate, synth_div_m);
 }
 
+static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	unsigned long current_rate, frac_rate;
+	u32 post_div_m;
+
+	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
+	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
+	frac_rate = current_rate * post_div_m;
+
+	return frac_rate;
+}
+
+static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
+					unsigned long rate,
+					unsigned long parent_rate)
+{
+	u32 post_div_m, synth_int_div, synth_frac_div, v;
+
+	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
+	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
+	if (post_div_m > SYNTH_MAX_DIV_M)
+		return -EINVAL;
+	if (!post_div_m)
+		post_div_m = 1;
+
+	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
+		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
+						 SYNTH_PHASE_K *
+						 10000000,
+						 rate * post_div_m);
+		synth_frac_div = synth_int_div % 10000000;
+		synth_int_div /= 10000000;
+
+		if (synth_int_div <= SYNTH_MAX_INT_DIV)
+			break;
+	}
+
+	if (synth_int_div > SYNTH_MAX_INT_DIV)
+		return -EINVAL;
+
+	v = readl_relaxed(synth->freq);
+	v &= ~0x1fffffff;
+	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
+	v |= (synth_frac_div & 0xffffff);
+	v |= SYNTH_LDFREQ;
+	writel_relaxed(v, synth->freq);
+
+	return post_div_m;
+}
+
+static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	struct fapll_data *fd = synth->fd;
+	unsigned long r;
+
+	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+		return -EINVAL;
+
+	/* Only post divider m available with no fractional divider? */
+	if (!synth->freq) {
+		unsigned long frac_rate;
+		u32 synth_post_div_m;
+
+		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
+		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
+		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
+		goto out;
+	}
+
+	r = *parent_rate * SYNTH_PHASE_K;
+	if (rate > r)
+		goto out;
+
+	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
+	if (rate < r)
+		goto out;
+
+	r = rate;
+out:
+	return r;
+}
+
+static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	struct fapll_data *fd = synth->fd;
+	unsigned long frac_rate, post_rate = 0;
+	u32 post_div_m = 0, v;
+
+	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+		return -EINVAL;
+
+	/* Produce the rate with just post divider M? */
+	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
+	if (frac_rate < rate) {
+		if (!synth->freq)
+			return -EINVAL;
+	} else {
+		post_div_m = DIV_ROUND_UP(frac_rate, rate);
+		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
+			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
+		if (!synth->freq && !post_rate)
+			return -EINVAL;
+	}
+
+	/* Need to recalculate the fractional divider? */
+	if ((post_rate != rate) && synth->freq)
+		post_div_m = ti_fapll_synth_set_frac_rate(synth,
+							  rate,
+							  parent_rate);
+
+	v = readl_relaxed(synth->div);
+	v &= ~SYNTH_MAX_DIV_M;
+	v |= post_div_m;
+	v |= SYNTH_LDMDIV1;
+	writel_relaxed(v, synth->div);
+
+	return 0;
+}
+
 static struct clk_ops ti_fapll_synt_ops = {
 	.enable = ti_fapll_synth_enable,
 	.disable = ti_fapll_synth_disable,
 	.is_enabled = ti_fapll_synth_is_enabled,
 	.recalc_rate = ti_fapll_synth_recalc_rate,
+	.round_rate = ti_fapll_synth_round_rate,
+	.set_rate = ti_fapll_synth_set_rate,
 };
 
 static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] clk: ti: Implement FAPLL set_rate for the PLL
  2015-03-22 22:35 [PATCH 0/3] Implement set_rate for FAPLL on dm816x Tony Lindgren
  2015-03-22 22:35 ` [PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors Tony Lindgren
  2015-03-22 22:35 ` [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer Tony Lindgren
@ 2015-03-22 22:35 ` Tony Lindgren
  2 siblings, 0 replies; 10+ messages in thread
From: Tony Lindgren @ 2015-03-22 22:35 UTC (permalink / raw)
  To: Mike Turquette, Stephen Boyd
  Cc: linux-kernel, linux-omap, Brian Hutchinson, Matthijs van Duin,
	Tero Kristo

Since we have a fractional divider for the synthesizer, just implement
a simple multiply logic for the PLL.

It seems the PLL divider needs to have also the multiplier set for the PLL
to lock. At least I have not yet figured out if divided rates are doable.

So let's just ignore the PLL divider for now as the synthesizer has both
integer and fractional dividers so we don't even need to use the PLL
divider for the rates we know work with PLL locking.

Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/clk/ti/fapll.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index 4064f7b..b6f5187 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -18,11 +18,20 @@
 #include <linux/clk/ti.h>
 
 /* FAPLL Control Register PLL_CTRL */
+#define FAPLL_MAIN_MULT_N_SHIFT	16
+#define FAPLL_MAIN_DIV_P_SHIFT	8
 #define FAPLL_MAIN_LOCK		BIT(7)
 #define FAPLL_MAIN_PLLEN	BIT(3)
 #define FAPLL_MAIN_BP		BIT(2)
 #define FAPLL_MAIN_LOC_CTL	BIT(0)
 
+#define FAPLL_MAIN_MAX_MULT_N	0xffff
+#define FAPLL_MAIN_MAX_DIV_P	0xff
+#define FAPLL_MAIN_CLEAR_MASK	\
+	((FAPLL_MAIN_MAX_MULT_N << FAPLL_MAIN_MULT_N_SHIFT) | \
+	 (FAPLL_MAIN_DIV_P_SHIFT << FAPLL_MAIN_DIV_P_SHIFT) | \
+	 FAPLL_MAIN_LOC_CTL)
+
 /* FAPLL powerdown register PWD */
 #define FAPLL_PWD_OFFSET	4
 
@@ -82,6 +91,48 @@ static bool ti_fapll_clock_is_bypass(struct fapll_data *fd)
 		return !!(v & FAPLL_MAIN_BP);
 }
 
+static void ti_fapll_set_bypass(struct fapll_data *fd)
+{
+	u32 v = readl_relaxed(fd->base);
+
+	if (fd->bypass_bit_inverted)
+		v &= ~FAPLL_MAIN_BP;
+	else
+		v |= FAPLL_MAIN_BP;
+	writel_relaxed(v, fd->base);
+}
+
+static void ti_fapll_clear_bypass(struct fapll_data *fd)
+{
+	u32 v = readl_relaxed(fd->base);
+
+	if (fd->bypass_bit_inverted)
+		v |= FAPLL_MAIN_BP;
+	else
+		v &= ~FAPLL_MAIN_BP;
+	writel_relaxed(v, fd->base);
+}
+
+static int ti_fapll_wait_lock(struct fapll_data *fd)
+{
+	int retries = FAPLL_MAX_RETRIES;
+	u32 v;
+
+	while ((v = readl_relaxed(fd->base))) {
+		if (v & FAPLL_MAIN_LOCK)
+			return 0;
+
+		if (retries-- <= 0)
+			break;
+
+		udelay(1);
+	}
+
+	pr_err("%s failed to lock\n", fd->name);
+
+	return -ETIMEDOUT;
+}
+
 static int ti_fapll_enable(struct clk_hw *hw)
 {
 	struct fapll_data *fd = to_fapll(hw);
@@ -89,6 +140,7 @@ static int ti_fapll_enable(struct clk_hw *hw)
 
 	v |= FAPLL_MAIN_PLLEN;
 	writel_relaxed(v, fd->base);
+	ti_fapll_wait_lock(fd);
 
 	return 0;
 }
@@ -144,12 +196,85 @@ static u8 ti_fapll_get_parent(struct clk_hw *hw)
 	return 0;
 }
 
+static int ti_fapll_set_div_mult(unsigned long rate,
+				 unsigned long parent_rate,
+				 u32 *pre_div_p, u32 *mult_n)
+{
+	/*
+	 * So far no luck getting decent clock with PLL divider,
+	 * PLL does not seem to lock and the signal does not look
+	 * right. It seems the divider can only be used together
+	 * with the multiplier?
+	 */
+	if (rate < parent_rate) {
+		pr_warn("FAPLL main divider rates unsupported\n");
+		return -EINVAL;
+	}
+
+	*mult_n = rate / parent_rate;
+	if (*mult_n > FAPLL_MAIN_MAX_MULT_N)
+		return -EINVAL;
+	*pre_div_p = 1;
+
+	return 0;
+}
+
+static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	u32 pre_div_p, mult_n;
+	int error;
+
+	if (!rate)
+		return -EINVAL;
+
+	error = ti_fapll_set_div_mult(rate, *parent_rate,
+				      &pre_div_p, &mult_n);
+	if (error)
+		return error;
+
+	rate = *parent_rate / pre_div_p;
+	rate *= mult_n;
+
+	return rate;
+}
+
+static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct fapll_data *fd = to_fapll(hw);
+	u32 pre_div_p, mult_n, v;
+	int error;
+
+	if (!rate)
+		return -EINVAL;
+
+	error = ti_fapll_set_div_mult(rate, parent_rate,
+				      &pre_div_p, &mult_n);
+	if (error)
+		return error;
+
+	ti_fapll_set_bypass(fd);
+	v = readl_relaxed(fd->base);
+	v &= ~FAPLL_MAIN_CLEAR_MASK;
+	v |= pre_div_p << FAPLL_MAIN_DIV_P_SHIFT;
+	v |= mult_n << FAPLL_MAIN_MULT_N_SHIFT;
+	writel_relaxed(v, fd->base);
+	if (ti_fapll_is_enabled(hw))
+		ti_fapll_wait_lock(fd);
+	ti_fapll_clear_bypass(fd);
+
+	return 0;
+}
+
 static struct clk_ops ti_fapll_ops = {
 	.enable = ti_fapll_enable,
 	.disable = ti_fapll_disable,
 	.is_enabled = ti_fapll_is_enabled,
 	.recalc_rate = ti_fapll_recalc_rate,
 	.get_parent = ti_fapll_get_parent,
+	.round_rate = ti_fapll_round_rate,
+	.set_rate = ti_fapll_set_rate,
 };
 
 static int ti_fapll_synth_enable(struct clk_hw *hw)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
  2015-03-22 22:35 ` [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer Tony Lindgren
@ 2015-03-23 13:25     ` Tero Kristo
  0 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2015-03-23 13:25 UTC (permalink / raw)
  To: Tony Lindgren, Mike Turquette, Stephen Boyd
  Cc: linux-kernel, linux-omap, Brian Hutchinson, Matthijs van Duin

On 03/23/2015 12:35 AM, Tony Lindgren wrote:
> We can pretty much get any rate out of the FAPLL because of the fractional
> divider. Let's first try just adjusting the post divider, and if that is
> not enough, then reprogram both the fractional divider and the post divider.
>
> Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.
>
> Cc: Brian Hutchinson <b.hutchman@gmail.com>
> Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>   drivers/clk/ti/fapll.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 132 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
> index 3b5e231..4064f7b 100644
> --- a/drivers/clk/ti/fapll.c
> +++ b/drivers/clk/ti/fapll.c
> @@ -12,6 +12,7 @@
>   #include <linux/clk-provider.h>
>   #include <linux/delay.h>
>   #include <linux/err.h>
> +#include <linux/math64.h>
>   #include <linux/of.h>
>   #include <linux/of_address.h>
>   #include <linux/clk/ti.h>
> @@ -47,6 +48,8 @@
>   /* Synthesizer frequency register */
>   #define SYNTH_LDFREQ		BIT(31)
>
> +#define SYNTH_PHASE_K		8
> +#define SYNTH_MAX_INT_DIV	0xf
>   #define SYNTH_MAX_DIV_M		0xff
>
>   struct fapll_data {
> @@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	/*
>   	 * Synth frequency integer and fractional divider.
>   	 * Note that the phase output K is 8, so the result needs
> -	 * to be multiplied by 8.
> +	 * to be multiplied by SYNTH_PHASE_K.
>   	 */
>   	if (synth->freq) {
>   		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
> @@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
>   		rate *= 10000000;
>   		do_div(rate, synth_div_freq);
> -		rate *= 8;
> +		rate *= SYNTH_PHASE_K;
>   	}
>
>   	/* Synth post-divider M */
> @@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	return DIV_ROUND_UP_ULL(rate, synth_div_m);
>   }
>
> +static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
> +						  unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	unsigned long current_rate, frac_rate;
> +	u32 post_div_m;
> +
> +	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
> +	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
> +	frac_rate = current_rate * post_div_m;
> +
> +	return frac_rate;
> +}
> +
> +static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
> +					unsigned long rate,
> +					unsigned long parent_rate)
> +{
> +	u32 post_div_m, synth_int_div, synth_frac_div, v;
> +
> +	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
> +	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
> +	if (post_div_m > SYNTH_MAX_DIV_M)
> +		return -EINVAL;
> +	if (!post_div_m)
> +		post_div_m = 1;
> +
> +	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
> +		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
> +						 SYNTH_PHASE_K *
> +						 10000000,
> +						 rate * post_div_m);
> +		synth_frac_div = synth_int_div % 10000000;
> +		synth_int_div /= 10000000;
> +
> +		if (synth_int_div <= SYNTH_MAX_INT_DIV)
> +			break;
> +	}
> +
> +	if (synth_int_div > SYNTH_MAX_INT_DIV)
> +		return -EINVAL;
> +
> +	v = readl_relaxed(synth->freq);
> +	v &= ~0x1fffffff;
> +	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
> +	v |= (synth_frac_div & 0xffffff);

This code is generating these compile time warnings for me:

   CC      drivers/clk/ti/fapll.o
drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used 
uninitialized in this function [-Wuninitialized]
drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used 
uninitialized in this function [-Wuninitialized]
drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here

-Tero


> +	v |= SYNTH_LDFREQ;
> +	writel_relaxed(v, synth->freq);
> +
> +	return post_div_m;
> +}
> +
> +static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
> +				      unsigned long *parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long r;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Only post divider m available with no fractional divider? */
> +	if (!synth->freq) {
> +		unsigned long frac_rate;
> +		u32 synth_post_div_m;
> +
> +		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
> +		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
> +		goto out;
> +	}
> +
> +	r = *parent_rate * SYNTH_PHASE_K;
> +	if (rate > r)
> +		goto out;
> +
> +	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
> +	if (rate < r)
> +		goto out;
> +
> +	r = rate;
> +out:
> +	return r;
> +}
> +
> +static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
> +				   unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long frac_rate, post_rate = 0;
> +	u32 post_div_m = 0, v;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Produce the rate with just post divider M? */
> +	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
> +	if (frac_rate < rate) {
> +		if (!synth->freq)
> +			return -EINVAL;
> +	} else {
> +		post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
> +			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
> +		if (!synth->freq && !post_rate)
> +			return -EINVAL;
> +	}
> +
> +	/* Need to recalculate the fractional divider? */
> +	if ((post_rate != rate) && synth->freq)
> +		post_div_m = ti_fapll_synth_set_frac_rate(synth,
> +							  rate,
> +							  parent_rate);
> +
> +	v = readl_relaxed(synth->div);
> +	v &= ~SYNTH_MAX_DIV_M;
> +	v |= post_div_m;
> +	v |= SYNTH_LDMDIV1;
> +	writel_relaxed(v, synth->div);
> +
> +	return 0;
> +}
> +
>   static struct clk_ops ti_fapll_synt_ops = {
>   	.enable = ti_fapll_synth_enable,
>   	.disable = ti_fapll_synth_disable,
>   	.is_enabled = ti_fapll_synth_is_enabled,
>   	.recalc_rate = ti_fapll_synth_recalc_rate,
> +	.round_rate = ti_fapll_synth_round_rate,
> +	.set_rate = ti_fapll_synth_set_rate,
>   };
>
>   static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
@ 2015-03-23 13:25     ` Tero Kristo
  0 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2015-03-23 13:25 UTC (permalink / raw)
  To: Tony Lindgren, Mike Turquette, Stephen Boyd
  Cc: linux-kernel, linux-omap, Brian Hutchinson, Matthijs van Duin

On 03/23/2015 12:35 AM, Tony Lindgren wrote:
> We can pretty much get any rate out of the FAPLL because of the fractional
> divider. Let's first try just adjusting the post divider, and if that is
> not enough, then reprogram both the fractional divider and the post divider.
>
> Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.
>
> Cc: Brian Hutchinson <b.hutchman@gmail.com>
> Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>   drivers/clk/ti/fapll.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 132 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
> index 3b5e231..4064f7b 100644
> --- a/drivers/clk/ti/fapll.c
> +++ b/drivers/clk/ti/fapll.c
> @@ -12,6 +12,7 @@
>   #include <linux/clk-provider.h>
>   #include <linux/delay.h>
>   #include <linux/err.h>
> +#include <linux/math64.h>
>   #include <linux/of.h>
>   #include <linux/of_address.h>
>   #include <linux/clk/ti.h>
> @@ -47,6 +48,8 @@
>   /* Synthesizer frequency register */
>   #define SYNTH_LDFREQ		BIT(31)
>
> +#define SYNTH_PHASE_K		8
> +#define SYNTH_MAX_INT_DIV	0xf
>   #define SYNTH_MAX_DIV_M		0xff
>
>   struct fapll_data {
> @@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	/*
>   	 * Synth frequency integer and fractional divider.
>   	 * Note that the phase output K is 8, so the result needs
> -	 * to be multiplied by 8.
> +	 * to be multiplied by SYNTH_PHASE_K.
>   	 */
>   	if (synth->freq) {
>   		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
> @@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
>   		rate *= 10000000;
>   		do_div(rate, synth_div_freq);
> -		rate *= 8;
> +		rate *= SYNTH_PHASE_K;
>   	}
>
>   	/* Synth post-divider M */
> @@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	return DIV_ROUND_UP_ULL(rate, synth_div_m);
>   }
>
> +static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
> +						  unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	unsigned long current_rate, frac_rate;
> +	u32 post_div_m;
> +
> +	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
> +	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
> +	frac_rate = current_rate * post_div_m;
> +
> +	return frac_rate;
> +}
> +
> +static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
> +					unsigned long rate,
> +					unsigned long parent_rate)
> +{
> +	u32 post_div_m, synth_int_div, synth_frac_div, v;
> +
> +	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
> +	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
> +	if (post_div_m > SYNTH_MAX_DIV_M)
> +		return -EINVAL;
> +	if (!post_div_m)
> +		post_div_m = 1;
> +
> +	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
> +		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
> +						 SYNTH_PHASE_K *
> +						 10000000,
> +						 rate * post_div_m);
> +		synth_frac_div = synth_int_div % 10000000;
> +		synth_int_div /= 10000000;
> +
> +		if (synth_int_div <= SYNTH_MAX_INT_DIV)
> +			break;
> +	}
> +
> +	if (synth_int_div > SYNTH_MAX_INT_DIV)
> +		return -EINVAL;
> +
> +	v = readl_relaxed(synth->freq);
> +	v &= ~0x1fffffff;
> +	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
> +	v |= (synth_frac_div & 0xffffff);

This code is generating these compile time warnings for me:

   CC      drivers/clk/ti/fapll.o
drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used 
uninitialized in this function [-Wuninitialized]
drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used 
uninitialized in this function [-Wuninitialized]
drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here

-Tero


> +	v |= SYNTH_LDFREQ;
> +	writel_relaxed(v, synth->freq);
> +
> +	return post_div_m;
> +}
> +
> +static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
> +				      unsigned long *parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long r;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Only post divider m available with no fractional divider? */
> +	if (!synth->freq) {
> +		unsigned long frac_rate;
> +		u32 synth_post_div_m;
> +
> +		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
> +		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
> +		goto out;
> +	}
> +
> +	r = *parent_rate * SYNTH_PHASE_K;
> +	if (rate > r)
> +		goto out;
> +
> +	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
> +	if (rate < r)
> +		goto out;
> +
> +	r = rate;
> +out:
> +	return r;
> +}
> +
> +static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
> +				   unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long frac_rate, post_rate = 0;
> +	u32 post_div_m = 0, v;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Produce the rate with just post divider M? */
> +	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
> +	if (frac_rate < rate) {
> +		if (!synth->freq)
> +			return -EINVAL;
> +	} else {
> +		post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
> +			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
> +		if (!synth->freq && !post_rate)
> +			return -EINVAL;
> +	}
> +
> +	/* Need to recalculate the fractional divider? */
> +	if ((post_rate != rate) && synth->freq)
> +		post_div_m = ti_fapll_synth_set_frac_rate(synth,
> +							  rate,
> +							  parent_rate);
> +
> +	v = readl_relaxed(synth->div);
> +	v &= ~SYNTH_MAX_DIV_M;
> +	v |= post_div_m;
> +	v |= SYNTH_LDMDIV1;
> +	writel_relaxed(v, synth->div);
> +
> +	return 0;
> +}
> +
>   static struct clk_ops ti_fapll_synt_ops = {
>   	.enable = ti_fapll_synth_enable,
>   	.disable = ti_fapll_synth_disable,
>   	.is_enabled = ti_fapll_synth_is_enabled,
>   	.recalc_rate = ti_fapll_synth_recalc_rate,
> +	.round_rate = ti_fapll_synth_round_rate,
> +	.set_rate = ti_fapll_synth_set_rate,
>   };
>
>   static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
  2015-03-23 13:25     ` Tero Kristo
  (?)
@ 2015-03-23 15:52     ` Tony Lindgren
  2015-03-24 16:37       ` Tony Lindgren
  -1 siblings, 1 reply; 10+ messages in thread
From: Tony Lindgren @ 2015-03-23 15:52 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Mike Turquette, Stephen Boyd, linux-kernel, linux-omap,
	Brian Hutchinson, Matthijs van Duin

* Tero Kristo <t-kristo@ti.com> [150323 06:25]:
> On 03/23/2015 12:35 AM, Tony Lindgren wrote:
> >+static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
> >+					unsigned long rate,
> >+					unsigned long parent_rate)
> >+{
> >+	u32 post_div_m, synth_int_div, synth_frac_div, v;
> >+
> >+	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
> >+	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
> >+	if (post_div_m > SYNTH_MAX_DIV_M)
> >+		return -EINVAL;
> >+	if (!post_div_m)
> >+		post_div_m = 1;
> >+
> >+	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
> >+		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
> >+						 SYNTH_PHASE_K *
> >+						 10000000,
> >+						 rate * post_div_m);
> >+		synth_frac_div = synth_int_div % 10000000;
> >+		synth_int_div /= 10000000;
> >+
> >+		if (synth_int_div <= SYNTH_MAX_INT_DIV)
> >+			break;
> >+	}
> >+
> >+	if (synth_int_div > SYNTH_MAX_INT_DIV)
> >+		return -EINVAL;
> >+
> >+	v = readl_relaxed(synth->freq);
> >+	v &= ~0x1fffffff;
> >+	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
> >+	v |= (synth_frac_div & 0xffffff);
> 
> This code is generating these compile time warnings for me:
> 
>   CC      drivers/clk/ti/fapll.o
> drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
> drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used
> uninitialized in this function [-Wuninitialized]
> drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
> drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used
> uninitialized in this function [-Wuninitialized]
> drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here

Oops thanks will check. I did move this into a separate function
to make it more readable, probably happened at that point.

Regards,

Tony

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
  2015-03-23 15:52     ` Tony Lindgren
@ 2015-03-24 16:37       ` Tony Lindgren
  2015-03-24 18:53           ` Tero Kristo
  0 siblings, 1 reply; 10+ messages in thread
From: Tony Lindgren @ 2015-03-24 16:37 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Mike Turquette, Stephen Boyd, linux-kernel, linux-omap,
	Brian Hutchinson, Matthijs van Duin

* Tony Lindgren <tony@atomide.com> [150323 08:58]:
> * Tero Kristo <t-kristo@ti.com> [150323 06:25]:
> > 
> > This code is generating these compile time warnings for me:
> > 
> >   CC      drivers/clk/ti/fapll.o
> > drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
> > drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used
> > uninitialized in this function [-Wuninitialized]
> > drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
> > drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used
> > uninitialized in this function [-Wuninitialized]
> > drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here
> 
> Oops thanks will check. I did move this into a separate function
> to make it more readable, probably happened at that point.

Updated version of this patch below, let me know if you want the
whole set reposted.

Regards,

Tony

8< -------------------
From: Tony Lindgren <tony@atomide.com>
Date: Mon, 16 Mar 2015 18:04:20 -0700
Subject: [PATCH] clk: ti: Implement FAPLL set_rate for the synthesizer

We can pretty much get any rate out of the FAPLL because of the fractional
divider. Let's first try just adjusting the post divider, and if that is
not enough, then reprogram both the fractional divider and the post divider.

Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.

Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
@@ -47,6 +48,8 @@
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ		BIT(31)
 
+#define SYNTH_PHASE_K		8
+#define SYNTH_MAX_INT_DIV	0xf
 #define SYNTH_MAX_DIV_M		0xff
 
 struct fapll_data {
@@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 	/*
 	 * Synth frequency integer and fractional divider.
 	 * Note that the phase output K is 8, so the result needs
-	 * to be multiplied by 8.
+	 * to be multiplied by SYNTH_PHASE_K.
 	 */
 	if (synth->freq) {
 		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
@@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
 		rate *= 10000000;
 		do_div(rate, synth_div_freq);
-		rate *= 8;
+		rate *= SYNTH_PHASE_K;
 	}
 
 	/* Synth post-divider M */
@@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 	return DIV_ROUND_UP_ULL(rate, synth_div_m);
 }
 
+static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	unsigned long current_rate, frac_rate;
+	u32 post_div_m;
+
+	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
+	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
+	frac_rate = current_rate * post_div_m;
+
+	return frac_rate;
+}
+
+static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
+					unsigned long rate,
+					unsigned long parent_rate)
+{
+	u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v;
+
+	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
+	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
+	if (post_div_m > SYNTH_MAX_DIV_M)
+		return -EINVAL;
+	if (!post_div_m)
+		post_div_m = 1;
+
+	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
+		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
+						 SYNTH_PHASE_K *
+						 10000000,
+						 rate * post_div_m);
+		synth_frac_div = synth_int_div % 10000000;
+		synth_int_div /= 10000000;
+
+		if (synth_int_div <= SYNTH_MAX_INT_DIV)
+			break;
+	}
+
+	if (synth_int_div > SYNTH_MAX_INT_DIV)
+		return -EINVAL;
+
+	v = readl_relaxed(synth->freq);
+	v &= ~0x1fffffff;
+	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
+	v |= (synth_frac_div & 0xffffff);
+	v |= SYNTH_LDFREQ;
+	writel_relaxed(v, synth->freq);
+
+	return post_div_m;
+}
+
+static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	struct fapll_data *fd = synth->fd;
+	unsigned long r;
+
+	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+		return -EINVAL;
+
+	/* Only post divider m available with no fractional divider? */
+	if (!synth->freq) {
+		unsigned long frac_rate;
+		u32 synth_post_div_m;
+
+		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
+		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
+		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
+		goto out;
+	}
+
+	r = *parent_rate * SYNTH_PHASE_K;
+	if (rate > r)
+		goto out;
+
+	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
+	if (rate < r)
+		goto out;
+
+	r = rate;
+out:
+	return r;
+}
+
+static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct fapll_synth *synth = to_synth(hw);
+	struct fapll_data *fd = synth->fd;
+	unsigned long frac_rate, post_rate = 0;
+	u32 post_div_m = 0, v;
+
+	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+		return -EINVAL;
+
+	/* Produce the rate with just post divider M? */
+	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
+	if (frac_rate < rate) {
+		if (!synth->freq)
+			return -EINVAL;
+	} else {
+		post_div_m = DIV_ROUND_UP(frac_rate, rate);
+		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
+			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
+		if (!synth->freq && !post_rate)
+			return -EINVAL;
+	}
+
+	/* Need to recalculate the fractional divider? */
+	if ((post_rate != rate) && synth->freq)
+		post_div_m = ti_fapll_synth_set_frac_rate(synth,
+							  rate,
+							  parent_rate);
+
+	v = readl_relaxed(synth->div);
+	v &= ~SYNTH_MAX_DIV_M;
+	v |= post_div_m;
+	v |= SYNTH_LDMDIV1;
+	writel_relaxed(v, synth->div);
+
+	return 0;
+}
+
 static struct clk_ops ti_fapll_synt_ops = {
 	.enable = ti_fapll_synth_enable,
 	.disable = ti_fapll_synth_disable,
 	.is_enabled = ti_fapll_synth_is_enabled,
 	.recalc_rate = ti_fapll_synth_recalc_rate,
+	.round_rate = ti_fapll_synth_round_rate,
+	.set_rate = ti_fapll_synth_set_rate,
 };
 
 static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
  2015-03-24 16:37       ` Tony Lindgren
@ 2015-03-24 18:53           ` Tero Kristo
  0 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2015-03-24 18:53 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Mike Turquette, Stephen Boyd, linux-kernel, linux-omap,
	Brian Hutchinson, Matthijs van Duin

On 03/24/2015 06:37 PM, Tony Lindgren wrote:
> * Tony Lindgren <tony@atomide.com> [150323 08:58]:
>> * Tero Kristo <t-kristo@ti.com> [150323 06:25]:
>>>
>>> This code is generating these compile time warnings for me:
>>>
>>>    CC      drivers/clk/ti/fapll.o
>>> drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
>>> drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used
>>> uninitialized in this function [-Wuninitialized]
>>> drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
>>> drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used
>>> uninitialized in this function [-Wuninitialized]
>>> drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here
>>
>> Oops thanks will check. I did move this into a separate function
>> to make it more readable, probably happened at that point.
>
> Updated version of this patch below, let me know if you want the
> whole set reposted.

Yes this is fine, all patches queued for 4.1, thanks!

-Tero

>
> Regards,
>
> Tony
>
> 8< -------------------
> From: Tony Lindgren <tony@atomide.com>
> Date: Mon, 16 Mar 2015 18:04:20 -0700
> Subject: [PATCH] clk: ti: Implement FAPLL set_rate for the synthesizer
>
> We can pretty much get any rate out of the FAPLL because of the fractional
> divider. Let's first try just adjusting the post divider, and if that is
> not enough, then reprogram both the fractional divider and the post divider.
>
> Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.
>
> Cc: Brian Hutchinson <b.hutchman@gmail.com>
> Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
>
> --- a/drivers/clk/ti/fapll.c
> +++ b/drivers/clk/ti/fapll.c
> @@ -12,6 +12,7 @@
>   #include <linux/clk-provider.h>
>   #include <linux/delay.h>
>   #include <linux/err.h>
> +#include <linux/math64.h>
>   #include <linux/of.h>
>   #include <linux/of_address.h>
>   #include <linux/clk/ti.h>
> @@ -47,6 +48,8 @@
>   /* Synthesizer frequency register */
>   #define SYNTH_LDFREQ		BIT(31)
>
> +#define SYNTH_PHASE_K		8
> +#define SYNTH_MAX_INT_DIV	0xf
>   #define SYNTH_MAX_DIV_M		0xff
>
>   struct fapll_data {
> @@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	/*
>   	 * Synth frequency integer and fractional divider.
>   	 * Note that the phase output K is 8, so the result needs
> -	 * to be multiplied by 8.
> +	 * to be multiplied by SYNTH_PHASE_K.
>   	 */
>   	if (synth->freq) {
>   		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
> @@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
>   		rate *= 10000000;
>   		do_div(rate, synth_div_freq);
> -		rate *= 8;
> +		rate *= SYNTH_PHASE_K;
>   	}
>
>   	/* Synth post-divider M */
> @@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	return DIV_ROUND_UP_ULL(rate, synth_div_m);
>   }
>
> +static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
> +						  unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	unsigned long current_rate, frac_rate;
> +	u32 post_div_m;
> +
> +	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
> +	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
> +	frac_rate = current_rate * post_div_m;
> +
> +	return frac_rate;
> +}
> +
> +static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
> +					unsigned long rate,
> +					unsigned long parent_rate)
> +{
> +	u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v;
> +
> +	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
> +	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
> +	if (post_div_m > SYNTH_MAX_DIV_M)
> +		return -EINVAL;
> +	if (!post_div_m)
> +		post_div_m = 1;
> +
> +	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
> +		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
> +						 SYNTH_PHASE_K *
> +						 10000000,
> +						 rate * post_div_m);
> +		synth_frac_div = synth_int_div % 10000000;
> +		synth_int_div /= 10000000;
> +
> +		if (synth_int_div <= SYNTH_MAX_INT_DIV)
> +			break;
> +	}
> +
> +	if (synth_int_div > SYNTH_MAX_INT_DIV)
> +		return -EINVAL;
> +
> +	v = readl_relaxed(synth->freq);
> +	v &= ~0x1fffffff;
> +	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
> +	v |= (synth_frac_div & 0xffffff);
> +	v |= SYNTH_LDFREQ;
> +	writel_relaxed(v, synth->freq);
> +
> +	return post_div_m;
> +}
> +
> +static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
> +				      unsigned long *parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long r;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Only post divider m available with no fractional divider? */
> +	if (!synth->freq) {
> +		unsigned long frac_rate;
> +		u32 synth_post_div_m;
> +
> +		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
> +		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
> +		goto out;
> +	}
> +
> +	r = *parent_rate * SYNTH_PHASE_K;
> +	if (rate > r)
> +		goto out;
> +
> +	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
> +	if (rate < r)
> +		goto out;
> +
> +	r = rate;
> +out:
> +	return r;
> +}
> +
> +static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
> +				   unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long frac_rate, post_rate = 0;
> +	u32 post_div_m = 0, v;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Produce the rate with just post divider M? */
> +	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
> +	if (frac_rate < rate) {
> +		if (!synth->freq)
> +			return -EINVAL;
> +	} else {
> +		post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
> +			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
> +		if (!synth->freq && !post_rate)
> +			return -EINVAL;
> +	}
> +
> +	/* Need to recalculate the fractional divider? */
> +	if ((post_rate != rate) && synth->freq)
> +		post_div_m = ti_fapll_synth_set_frac_rate(synth,
> +							  rate,
> +							  parent_rate);
> +
> +	v = readl_relaxed(synth->div);
> +	v &= ~SYNTH_MAX_DIV_M;
> +	v |= post_div_m;
> +	v |= SYNTH_LDMDIV1;
> +	writel_relaxed(v, synth->div);
> +
> +	return 0;
> +}
> +
>   static struct clk_ops ti_fapll_synt_ops = {
>   	.enable = ti_fapll_synth_enable,
>   	.disable = ti_fapll_synth_disable,
>   	.is_enabled = ti_fapll_synth_is_enabled,
>   	.recalc_rate = ti_fapll_synth_recalc_rate,
> +	.round_rate = ti_fapll_synth_round_rate,
> +	.set_rate = ti_fapll_synth_set_rate,
>   };
>
>   static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer
@ 2015-03-24 18:53           ` Tero Kristo
  0 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2015-03-24 18:53 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Mike Turquette, Stephen Boyd, linux-kernel, linux-omap,
	Brian Hutchinson, Matthijs van Duin

On 03/24/2015 06:37 PM, Tony Lindgren wrote:
> * Tony Lindgren <tony@atomide.com> [150323 08:58]:
>> * Tero Kristo <t-kristo@ti.com> [150323 06:25]:
>>>
>>> This code is generating these compile time warnings for me:
>>>
>>>    CC      drivers/clk/ti/fapll.o
>>> drivers/clk/ti/fapll.c: In function ‘ti_fapll_synth_set_rate’:
>>> drivers/clk/ti/fapll.c:394:5: warning: ‘synth_int_div’ may be used
>>> uninitialized in this function [-Wuninitialized]
>>> drivers/clk/ti/fapll.c:373:18: note: ‘synth_int_div’ was declared here
>>> drivers/clk/ti/fapll.c:400:23: warning: ‘synth_frac_div’ may be used
>>> uninitialized in this function [-Wuninitialized]
>>> drivers/clk/ti/fapll.c:373:33: note: ‘synth_frac_div’ was declared here
>>
>> Oops thanks will check. I did move this into a separate function
>> to make it more readable, probably happened at that point.
>
> Updated version of this patch below, let me know if you want the
> whole set reposted.

Yes this is fine, all patches queued for 4.1, thanks!

-Tero

>
> Regards,
>
> Tony
>
> 8< -------------------
> From: Tony Lindgren <tony@atomide.com>
> Date: Mon, 16 Mar 2015 18:04:20 -0700
> Subject: [PATCH] clk: ti: Implement FAPLL set_rate for the synthesizer
>
> We can pretty much get any rate out of the FAPLL because of the fractional
> divider. Let's first try just adjusting the post divider, and if that is
> not enough, then reprogram both the fractional divider and the post divider.
>
> Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.
>
> Cc: Brian Hutchinson <b.hutchman@gmail.com>
> Cc: Matthijs van Duin <matthijsvanduin@gmail.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
>
> --- a/drivers/clk/ti/fapll.c
> +++ b/drivers/clk/ti/fapll.c
> @@ -12,6 +12,7 @@
>   #include <linux/clk-provider.h>
>   #include <linux/delay.h>
>   #include <linux/err.h>
> +#include <linux/math64.h>
>   #include <linux/of.h>
>   #include <linux/of_address.h>
>   #include <linux/clk/ti.h>
> @@ -47,6 +48,8 @@
>   /* Synthesizer frequency register */
>   #define SYNTH_LDFREQ		BIT(31)
>
> +#define SYNTH_PHASE_K		8
> +#define SYNTH_MAX_INT_DIV	0xf
>   #define SYNTH_MAX_DIV_M		0xff
>
>   struct fapll_data {
> @@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	/*
>   	 * Synth frequency integer and fractional divider.
>   	 * Note that the phase output K is 8, so the result needs
> -	 * to be multiplied by 8.
> +	 * to be multiplied by SYNTH_PHASE_K.
>   	 */
>   	if (synth->freq) {
>   		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
> @@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
>   		rate *= 10000000;
>   		do_div(rate, synth_div_freq);
> -		rate *= 8;
> +		rate *= SYNTH_PHASE_K;
>   	}
>
>   	/* Synth post-divider M */
> @@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
>   	return DIV_ROUND_UP_ULL(rate, synth_div_m);
>   }
>
> +static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
> +						  unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	unsigned long current_rate, frac_rate;
> +	u32 post_div_m;
> +
> +	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
> +	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
> +	frac_rate = current_rate * post_div_m;
> +
> +	return frac_rate;
> +}
> +
> +static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
> +					unsigned long rate,
> +					unsigned long parent_rate)
> +{
> +	u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v;
> +
> +	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
> +	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
> +	if (post_div_m > SYNTH_MAX_DIV_M)
> +		return -EINVAL;
> +	if (!post_div_m)
> +		post_div_m = 1;
> +
> +	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
> +		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
> +						 SYNTH_PHASE_K *
> +						 10000000,
> +						 rate * post_div_m);
> +		synth_frac_div = synth_int_div % 10000000;
> +		synth_int_div /= 10000000;
> +
> +		if (synth_int_div <= SYNTH_MAX_INT_DIV)
> +			break;
> +	}
> +
> +	if (synth_int_div > SYNTH_MAX_INT_DIV)
> +		return -EINVAL;
> +
> +	v = readl_relaxed(synth->freq);
> +	v &= ~0x1fffffff;
> +	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
> +	v |= (synth_frac_div & 0xffffff);
> +	v |= SYNTH_LDFREQ;
> +	writel_relaxed(v, synth->freq);
> +
> +	return post_div_m;
> +}
> +
> +static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
> +				      unsigned long *parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long r;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Only post divider m available with no fractional divider? */
> +	if (!synth->freq) {
> +		unsigned long frac_rate;
> +		u32 synth_post_div_m;
> +
> +		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
> +		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
> +		goto out;
> +	}
> +
> +	r = *parent_rate * SYNTH_PHASE_K;
> +	if (rate > r)
> +		goto out;
> +
> +	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
> +	if (rate < r)
> +		goto out;
> +
> +	r = rate;
> +out:
> +	return r;
> +}
> +
> +static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
> +				   unsigned long parent_rate)
> +{
> +	struct fapll_synth *synth = to_synth(hw);
> +	struct fapll_data *fd = synth->fd;
> +	unsigned long frac_rate, post_rate = 0;
> +	u32 post_div_m = 0, v;
> +
> +	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
> +		return -EINVAL;
> +
> +	/* Produce the rate with just post divider M? */
> +	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
> +	if (frac_rate < rate) {
> +		if (!synth->freq)
> +			return -EINVAL;
> +	} else {
> +		post_div_m = DIV_ROUND_UP(frac_rate, rate);
> +		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
> +			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
> +		if (!synth->freq && !post_rate)
> +			return -EINVAL;
> +	}
> +
> +	/* Need to recalculate the fractional divider? */
> +	if ((post_rate != rate) && synth->freq)
> +		post_div_m = ti_fapll_synth_set_frac_rate(synth,
> +							  rate,
> +							  parent_rate);
> +
> +	v = readl_relaxed(synth->div);
> +	v &= ~SYNTH_MAX_DIV_M;
> +	v |= post_div_m;
> +	v |= SYNTH_LDMDIV1;
> +	writel_relaxed(v, synth->div);
> +
> +	return 0;
> +}
> +
>   static struct clk_ops ti_fapll_synt_ops = {
>   	.enable = ti_fapll_synth_enable,
>   	.disable = ti_fapll_synth_disable,
>   	.is_enabled = ti_fapll_synth_is_enabled,
>   	.recalc_rate = ti_fapll_synth_recalc_rate,
> +	.round_rate = ti_fapll_synth_round_rate,
> +	.set_rate = ti_fapll_synth_set_rate,
>   };
>
>   static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-03-24 18:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-22 22:35 [PATCH 0/3] Implement set_rate for FAPLL on dm816x Tony Lindgren
2015-03-22 22:35 ` [PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors Tony Lindgren
2015-03-22 22:35 ` [PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer Tony Lindgren
2015-03-23 13:25   ` Tero Kristo
2015-03-23 13:25     ` Tero Kristo
2015-03-23 15:52     ` Tony Lindgren
2015-03-24 16:37       ` Tony Lindgren
2015-03-24 18:53         ` Tero Kristo
2015-03-24 18:53           ` Tero Kristo
2015-03-22 22:35 ` [PATCH 3/3] clk: ti: Implement FAPLL set_rate for the PLL Tony Lindgren

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.