linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate()
@ 2017-09-05  9:32 Lars-Peter Clausen
  2017-09-05  9:32 ` [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate() Lars-Peter Clausen
  2017-12-22  2:08 ` [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Stephen Boyd
  0 siblings, 2 replies; 4+ messages in thread
From: Lars-Peter Clausen @ 2017-09-05  9:32 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd; +Cc: linux-clk, Lars-Peter Clausen

If the nocount bit is set the divider is bypassed and the settings for the
divider count should be ignored and a divider value of 1 should be assumed.
Handle this correctly in the driver recalc_rate() callback.

While the driver sets up the part so that the read back dividers values
yield the correct result the power-on reset settings of the part might not
reflect this and hence calling e.g. clk_get_rate() without prior calls to
clk_set_rate() will yield the wrong result.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/clk/clk-axi-clkgen.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 5e918e7afaba..95a6e9834392 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -40,6 +40,10 @@
 #define MMCM_REG_FILTER1	0x4e
 #define MMCM_REG_FILTER2	0x4f
 
+#define MMCM_CLKOUT_NOCOUNT	BIT(6)
+
+#define MMCM_CLK_DIV_NOCOUNT	BIT(12)
+
 struct axi_clkgen {
 	void __iomem *base;
 	struct clk_hw clk_hw;
@@ -315,12 +319,27 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	unsigned int reg;
 	unsigned long long tmp;
 
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
-	dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
+	if (reg & MMCM_CLKOUT_NOCOUNT) {
+		dout = 1;
+	} else {
+		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
+		dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	}
+
 	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
-	d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
-	m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	if (reg & MMCM_CLK_DIV_NOCOUNT)
+		d = 1;
+	else
+		d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
+	if (reg & MMCM_CLKOUT_NOCOUNT) {
+		m = 1;
+	} else {
+		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
+		m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	}
 
 	if (d == 0 || dout == 0)
 		return 0;
-- 
2.11.0


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

* [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate()
  2017-09-05  9:32 [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Lars-Peter Clausen
@ 2017-09-05  9:32 ` Lars-Peter Clausen
  2017-12-22  2:08   ` Stephen Boyd
  2017-12-22  2:08 ` [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Stephen Boyd
  1 sibling, 1 reply; 4+ messages in thread
From: Lars-Peter Clausen @ 2017-09-05  9:32 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd; +Cc: linux-clk, Lars-Peter Clausen

To minimize the rounding error round to the closest integer when
calculating the result in the recalc_rate() and set_rate() callbacks.

Also in order to improve precision multiply first and then divide.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/clk/clk-axi-clkgen.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 95a6e9834392..48d11f2598e8 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -302,13 +302,17 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long *parent_rate)
 {
 	unsigned int d, m, dout;
+	unsigned long long tmp;
 
 	axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
 
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
 
-	return *parent_rate / d * m / dout;
+	tmp = (unsigned long long)*parent_rate * m;
+	tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
+
+	return min_t(unsigned long long, tmp, LONG_MAX);
 }
 
 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
@@ -344,8 +348,8 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	if (d == 0 || dout == 0)
 		return 0;
 
-	tmp = (unsigned long long)(parent_rate / d) * m;
-	do_div(tmp, dout);
+	tmp = (unsigned long long)parent_rate * m;
+	tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
 
 	return min_t(unsigned long long, tmp, ULONG_MAX);
 }
-- 
2.11.0


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

* Re: [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate()
  2017-09-05  9:32 [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Lars-Peter Clausen
  2017-09-05  9:32 ` [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate() Lars-Peter Clausen
@ 2017-12-22  2:08 ` Stephen Boyd
  1 sibling, 0 replies; 4+ messages in thread
From: Stephen Boyd @ 2017-12-22  2:08 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Michael Turquette, linux-clk

On 09/05, Lars-Peter Clausen wrote:
> If the nocount bit is set the divider is bypassed and the settings for the
> divider count should be ignored and a divider value of 1 should be assumed.
> Handle this correctly in the driver recalc_rate() callback.
> 
> While the driver sets up the part so that the read back dividers values
> yield the correct result the power-on reset settings of the part might not
> reflect this and hence calling e.g. clk_get_rate() without prior calls to
> clk_set_rate() will yield the wrong result.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate()
  2017-09-05  9:32 ` [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate() Lars-Peter Clausen
@ 2017-12-22  2:08   ` Stephen Boyd
  0 siblings, 0 replies; 4+ messages in thread
From: Stephen Boyd @ 2017-12-22  2:08 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Michael Turquette, linux-clk

On 09/05, Lars-Peter Clausen wrote:
> To minimize the rounding error round to the closest integer when
> calculating the result in the recalc_rate() and set_rate() callbacks.
> 
> Also in order to improve precision multiply first and then divide.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

end of thread, other threads:[~2017-12-22  2:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-05  9:32 [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Lars-Peter Clausen
2017-09-05  9:32 ` [PATCH 2/2] clk: axi-clkgen: Round closest in round_rate() and recalc_rate() Lars-Peter Clausen
2017-12-22  2:08   ` Stephen Boyd
2017-12-22  2:08 ` [PATCH 1/2] clk: axi-clkgen: Correctly handle nocount bit in recalc_rate() Stephen Boyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).