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

Commit 8c2a2f02 authored by Rajkumar Subbiah's avatar Rajkumar Subbiah
Browse files

clk: msm: Fix pll out div programming



The PLL out divider is currently not programmed when the PLL is
locked. Since they are setup as fixed ratio dividers, the set_div
is not called during set_rate. So this fix moves the pll out div
programming to pll out mux selection callback which gets called
during set_rate.

Change-Id: I48b0254c6eb308071706258d2b5a77f06d9927c2
Signed-off-by: default avatarRajkumar Subbiah <rsubbia@codeaurora.org>
parent 6d8fa6f1
Loading
Loading
Loading
Loading
+48 −89
Original line number Diff line number Diff line
@@ -551,11 +551,23 @@ static int dsi_pll_enable(struct dsi_pll_vco_clk *vco)
{
	int rc;
	struct mdss_pll_resources *rsc = vco->priv;
	struct dsi_pll_8998 *pll = rsc->priv;
	struct dsi_pll_regs *regs = &pll->reg_setup;

	dsi_pll_enable_pll_bias(rsc);
	if (rsc->slave)
		dsi_pll_enable_pll_bias(rsc->slave);

	/*
	 * The PLL out dividers are fixed divider clocks and hence the
	 * set_div is not called during set_rate cycle of the tree.
	 * The outdiv rate is therefore set in the pll out mux's set_sel
	 * callback. But that will be called only after vco's set rate.
	 * Hence PLL out div value is set here before locking the PLL.
	 */
	MDSS_PLL_REG_W(rsc->pll_base, PLL_PLL_OUTDIV_RATE,
		regs->pll_outdiv_rate);

	/* Start PLL */
	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01);

@@ -682,7 +694,9 @@ static int vco_8998_prepare(struct clk *c)
static unsigned long dsi_pll_get_vco_rate(struct clk *c)
{
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *pll = vco->priv;
	struct mdss_pll_resources *rsc = vco->priv;
	struct dsi_pll_8998 *pll = rsc->priv;
	struct dsi_pll_regs *regs = &pll->reg_setup;
	int rc;
	u64 ref_clk = vco->ref_clk_rate;
	u64 vco_rate;
@@ -692,27 +706,30 @@ static unsigned long dsi_pll_get_vco_rate(struct clk *c)
	u32 outdiv;
	u64 pll_freq, tmp64;

	rc = mdss_pll_resource_enable(pll, true);
	rc = mdss_pll_resource_enable(rsc, true);
	if (rc) {
		pr_err("failed to enable pll(%d) resource, rc=%d\n",
		       pll->index, rc);
		       rsc->index, rc);
		return 0;
	}

	dec = MDSS_PLL_REG_R(pll->pll_base, PLL_DECIMAL_DIV_START_1);
	dec = MDSS_PLL_REG_R(rsc->pll_base, PLL_DECIMAL_DIV_START_1);
	dec &= 0xFF;

	frac = MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_LOW_1);
	frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_MID_1) &
	frac = MDSS_PLL_REG_R(rsc->pll_base, PLL_FRAC_DIV_START_LOW_1);
	frac |= ((MDSS_PLL_REG_R(rsc->pll_base, PLL_FRAC_DIV_START_MID_1) &
		  0xFF) <<
		8);
	frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_HIGH_1) &
	frac |= ((MDSS_PLL_REG_R(rsc->pll_base, PLL_FRAC_DIV_START_HIGH_1) &
		  0x3) <<
		16);

	/* OUTDIV_1:0 field is (log(outdiv, 2)) */
	outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE);
	outdiv = MDSS_PLL_REG_R(rsc->pll_base, PLL_PLL_OUTDIV_RATE);
	outdiv &= 0x3;

	regs->pll_outdiv_rate = outdiv;

	outdiv = 1 << outdiv;

	/*
@@ -730,7 +747,7 @@ static unsigned long dsi_pll_get_vco_rate(struct clk *c)
	pr_debug("dec=0x%x, frac=0x%x, outdiv=%d, vco=%llu\n",
		 dec, frac, outdiv, vco_rate);

	(void)mdss_pll_resource_enable(pll, false);
	(void)mdss_pll_resource_enable(rsc, false);

	return (unsigned long)vco_rate;
}
@@ -884,72 +901,26 @@ static int bit_clk_set_div(struct div_clk *clk, int div)
	return rc;
}

static int pll_out_clk_set_div(struct div_clk *clk, int div)
static int dsi_pll_out_set_mux_sel(struct mux_clk *clk, int sel)
{
	int rc;
	u32 reg_val = 0;
	int i;

	struct mdss_pll_resources *rsc = clk->priv;
	struct dsi_pll_8998 *pll = rsc->priv;
	struct dsi_pll_regs *regs = &pll->reg_setup;

	rc = mdss_pll_resource_enable(rsc, true);
	if (rc) {
		pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
		return rc;
	}

	/*
	 * out_div = 2 ^ div_log
	 * To get div_log from output div just get the index of the
	 * 1 bit in the value.
	 * div_log ranges from 0-3. so check the 4 lsbs
	 */

	for (i = 0; i < 4; i++) {
		if (div & (1 << i)) {
			reg_val = i;
			break;
		}
	}

	regs->pll_outdiv_rate = reg_val;

	MDSS_PLL_REG_W(rsc->pll_base, PLL_PLL_OUTDIV_RATE, reg_val);

	pr_debug("Setting PLL outdiv rate on pll(%d) to 0x%x\n",
		rsc->index, reg_val);

	(void)mdss_pll_resource_enable(rsc, false);
	regs->pll_outdiv_rate = sel;

	return 0;
}


static int pll_out_clk_get_div(struct div_clk *clk)
static int dsi_pll_out_get_mux_sel(struct mux_clk *clk)
{
	int rc;
	u32 reg_val;
	int div;

	struct mdss_pll_resources *pll = clk->priv;
	struct mdss_pll_resources *rsc = clk->priv;
	struct dsi_pll_8998 *pll = rsc->priv;
	struct dsi_pll_regs *regs = &pll->reg_setup;

	rc = mdss_pll_resource_enable(pll, true);
	if (rc) {
		pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
		return rc;
	return regs->pll_outdiv_rate;
}

	reg_val = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE);
	div = 1 << (reg_val & 3);

	(void)mdss_pll_resource_enable(pll, false);

	return div;
}


static int post_vco_clk_get_div(struct div_clk *clk)
{
	int rc;
@@ -1111,7 +1082,6 @@ static struct clk_ops clk_ops_bitclk_src_c;
static struct clk_ops clk_ops_post_vco_div_c;
static struct clk_ops clk_ops_post_bit_div_c;
static struct clk_ops clk_ops_pclk_src_c;
static struct clk_ops clk_ops_pll_out_div_c;

static struct clk_div_ops clk_post_vco_div_ops = {
	.set_div = post_vco_clk_set_div,
@@ -1133,11 +1103,6 @@ static struct clk_div_ops clk_bitclk_src_ops = {
	.get_div = bit_clk_get_div,
};

static struct clk_div_ops clk_pll_out_div_ops = {
	.set_div = pll_out_clk_set_div,
	.get_div = pll_out_clk_get_div,
};

static struct clk_ops clk_ops_vco_8998 = {
	.set_rate = vco_8998_set_rate,
	.round_rate = vco_8998_round_rate,
@@ -1151,6 +1116,11 @@ static struct clk_mux_ops mdss_mux_ops = {
	.get_mux_sel = mdss_get_mux_sel,
};

static struct clk_mux_ops mdss_pll_out_mux_ops = {
	.set_mux_sel = dsi_pll_out_set_mux_sel,
	.get_mux_sel = dsi_pll_out_get_mux_sel,
};

/*
 * Clock tree for generating DSI byte and pixel clocks.
 *
@@ -1236,11 +1206,10 @@ static struct div_clk dsi0pll_pll_out_div1 = {
		.min_div = 1,
		.max_div = 1,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi0pll_vco_clk.c,
		.dbg_name = "dsi0pll_pll_out_div1",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi0pll_pll_out_div1.c),
	}
@@ -1252,11 +1221,10 @@ static struct div_clk dsi0pll_pll_out_div2 = {
		.min_div = 2,
		.max_div = 2,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi0pll_vco_clk.c,
		.dbg_name = "dsi0pll_pll_out_div2",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi0pll_pll_out_div2.c),
	}
@@ -1268,11 +1236,10 @@ static struct div_clk dsi0pll_pll_out_div4 = {
		.min_div = 4,
		.max_div = 4,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi0pll_vco_clk.c,
		.dbg_name = "dsi0pll_pll_out_div4",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi0pll_pll_out_div4.c),
	}
@@ -1284,11 +1251,10 @@ static struct div_clk dsi0pll_pll_out_div8 = {
		.min_div = 8,
		.max_div = 8,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi0pll_vco_clk.c,
		.dbg_name = "dsi0pll_pll_out_div8",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi0pll_pll_out_div8.c),
	}
@@ -1302,7 +1268,7 @@ static struct mux_clk dsi0pll_pll_out_mux = {
		{&dsi0pll_pll_out_div4.c, 2},
		{&dsi0pll_pll_out_div8.c, 3},
	},
	.ops = &mdss_mux_ops,
	.ops = &mdss_pll_out_mux_ops,
	.c = {
		.parent = &dsi0pll_pll_out_div1.c,
		.dbg_name = "dsi0pll_pll_out_mux",
@@ -1486,11 +1452,10 @@ static struct div_clk dsi1pll_pll_out_div1 = {
		.min_div = 1,
		.max_div = 1,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi1pll_vco_clk.c,
		.dbg_name = "dsi1pll_pll_out_div1",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi1pll_pll_out_div1.c),
	}
@@ -1502,11 +1467,10 @@ static struct div_clk dsi1pll_pll_out_div2 = {
		.min_div = 2,
		.max_div = 2,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi1pll_vco_clk.c,
		.dbg_name = "dsi1pll_pll_out_div2",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi1pll_pll_out_div2.c),
	}
@@ -1518,11 +1482,10 @@ static struct div_clk dsi1pll_pll_out_div4 = {
		.min_div = 4,
		.max_div = 4,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi1pll_vco_clk.c,
		.dbg_name = "dsi1pll_pll_out_div4",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi1pll_pll_out_div4.c),
	}
@@ -1534,11 +1497,10 @@ static struct div_clk dsi1pll_pll_out_div8 = {
		.min_div = 8,
		.max_div = 8,
	},
	.ops = &clk_pll_out_div_ops,
	.c = {
		.parent = &dsi1pll_vco_clk.c,
		.dbg_name = "dsi1pll_pll_out_div8",
		.ops = &clk_ops_pll_out_div_c,
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dsi1pll_pll_out_div8.c),
	}
@@ -1552,7 +1514,7 @@ static struct mux_clk dsi1pll_pll_out_mux = {
		{&dsi1pll_pll_out_div4.c, 2},
		{&dsi1pll_pll_out_div8.c, 3},
	},
	.ops = &mdss_mux_ops,
	.ops = &mdss_pll_out_mux_ops,
	.c = {
		.parent = &dsi1pll_pll_out_div1.c,
		.dbg_name = "dsi1pll_pll_out_mux",
@@ -1786,9 +1748,6 @@ int dsi_pll_clock_register_8998(struct platform_device *pdev,
	clk_ops_bitclk_src_c = clk_ops_div;
	clk_ops_bitclk_src_c.prepare = mdss_pll_div_prepare;

	clk_ops_pll_out_div_c = clk_ops_div;
	clk_ops_pll_out_div_c.prepare = mdss_pll_div_prepare;

	/*
	 * Set the ops for the two dividers in the pixel clock tree to the
	 * slave_div to ensure that a set rate on this divider clock will not