* [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, ®);
- dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+ axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, ®);
+ if (reg & MMCM_CLKOUT_NOCOUNT) {
+ dout = 1;
+ } else {
+ axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®);
+ dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+ }
+
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®);
- d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
- axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®);
- 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, ®);
+ if (reg & MMCM_CLKOUT_NOCOUNT) {
+ m = 1;
+ } else {
+ axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®);
+ 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
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).