Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 063578dc authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Stephen Boyd
Browse files

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: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
parent 4fbd8d19
Loading
Loading
Loading
Loading
+24 −5
Original line number Diff line number Diff line
@@ -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_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);
	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;