summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorRajkumar Subbiah <rsubbia@codeaurora.org>2017-05-08 16:15:22 -0400
committerRajkumar Subbiah <rsubbia@codeaurora.org>2017-05-15 11:45:13 -0400
commit8c2a2f02ed70141c744794226e92d5b4ff9fab08 (patch)
tree541eb834f820832452377023cc10967dce00e8b3 /drivers/clk
parent6d8fa6f1ccf8ec205e34e1333bffc39b920fe171 (diff)
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: Rajkumar Subbiah <rsubbia@codeaurora.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-8998.c137
1 files changed, 48 insertions, 89 deletions
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
index 680c501b4a9d..040707e58e25 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
@@ -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;
-
- rc = mdss_pll_resource_enable(pll, true);
- if (rc) {
- pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
- return rc;
- }
-
- 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);
+ struct mdss_pll_resources *rsc = clk->priv;
+ struct dsi_pll_8998 *pll = rsc->priv;
+ struct dsi_pll_regs *regs = &pll->reg_setup;
- return div;
+ return regs->pll_outdiv_rate;
}
-
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