aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2017-09-05 05:32:40 -0400
committerStephen Boyd <sboyd@codeaurora.org>2017-12-21 21:07:11 -0500
commit063578dc5f407f67d149133818efabe457daafda (patch)
treecf1ab0b9a47d56e7601b1fef2ae598aaae29cf25
parent4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff)
clk: axi-clkgen: Correctly handle nocount bit in recalc_rate()
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> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r--drivers/clk/clk-axi-clkgen.c29
1 files 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 @@
40#define MMCM_REG_FILTER1 0x4e 40#define MMCM_REG_FILTER1 0x4e
41#define MMCM_REG_FILTER2 0x4f 41#define MMCM_REG_FILTER2 0x4f
42 42
43#define MMCM_CLKOUT_NOCOUNT BIT(6)
44
45#define MMCM_CLK_DIV_NOCOUNT BIT(12)
46
43struct axi_clkgen { 47struct axi_clkgen {
44 void __iomem *base; 48 void __iomem *base;
45 struct clk_hw clk_hw; 49 struct clk_hw clk_hw;
@@ -315,12 +319,27 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
315 unsigned int reg; 319 unsigned int reg;
316 unsigned long long tmp; 320 unsigned long long tmp;
317 321
318 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg); 322 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
319 dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); 323 if (reg & MMCM_CLKOUT_NOCOUNT) {
324 dout = 1;
325 } else {
326 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
327 dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
328 }
329
320 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg); 330 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
321 d = (reg & 0x3f) + ((reg >> 6) & 0x3f); 331 if (reg & MMCM_CLK_DIV_NOCOUNT)
322 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg); 332 d = 1;
323 m = (reg & 0x3f) + ((reg >> 6) & 0x3f); 333 else
334 d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
335
336 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
337 if (reg & MMCM_CLKOUT_NOCOUNT) {
338 m = 1;
339 } else {
340 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
341 m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
342 }
324 343
325 if (d == 0 || dout == 0) 344 if (d == 0 || dout == 0)
326 return 0; 345 return 0;