From: Lars-Peter Clausen <l...@metafoo.de>

[ Upstream commit 063578dc5f407f67d149133818efabe457daafda ]

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 <l...@metafoo.de>
Signed-off-by: Stephen Boyd <sb...@codeaurora.org>
Signed-off-by: Sasha Levin <alexander.le...@microsoft.com>
---
 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.14.1

Reply via email to