summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorHuaibin Yang <huaibiny@codeaurora.org>2014-12-09 12:38:51 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:41:36 -0700
commitc47167a9bedac245d6982fa6a4cc644cf973f7e7 (patch)
treee9095f2e7e3e50b8aaab57df73d6719f7dc89ed7 /drivers/clk
parent31a3efe49a5baf6ccdeff216eea8e9b7db4e930f (diff)
clk: mdss: implement new pll re-locking sequence
The new sequence is intended to improve pll locking time. This patch is to implement locking pll using stored codes and bypassing calibration. Change-Id: I1a26843b5d784984dff4fee0e17841cfc1be37cc Signed-off-by: Huaibin Yang <huaibiny@codeaurora.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c69
-rw-r--r--drivers/clk/msm/mdss/mdss-pll.h2
2 files changed, 61 insertions, 10 deletions
diff --git a/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c b/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c
index b7cf01b28003..493c1634f50f 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c
@@ -167,6 +167,10 @@ static void pll_20nm_cache_trim_codes(struct mdss_pll_resources *dsi_pll_res)
MDSS_PLL_REG_R(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_CORE_VCO_TUNE);
+ pr_debug("core_kvco_code=0x%x core_vco_turn=0x%x\n",
+ dsi_pll_res->cache_pll_trim_codes[0],
+ dsi_pll_res->cache_pll_trim_codes[1]);
+
mdss_pll_resource_enable(dsi_pll_res, false);
dsi_pll_res->reg_upd = true;
@@ -852,8 +856,15 @@ enum handoff pll_20nm_vco_handoff(struct clk *c)
dsi_pll_res->pll_on = true;
c->rate = pll_20nm_vco_get_rate(c);
ret = HANDOFF_ENABLED_CLK;
+ dsi_pll_res->vco_locking_rate = c->rate;
+ dsi_pll_res->is_init_locked = true;
+ pll_20nm_cache_trim_codes(dsi_pll_res);
+ pr_debug("handoff vco_locking_rate=0x%llu\n",
+ dsi_pll_res->vco_locking_rate);
} else {
mdss_pll_resource_enable(dsi_pll_res, false);
+ dsi_pll_res->vco_locking_rate = 0;
+ dsi_pll_res->is_init_locked = false;
}
return ret;
@@ -913,28 +924,41 @@ static void pll_20nm_config_vco_start(void __iomem *pll_base)
MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x03);
}
-static int pll_20nm_vco_init_lock(struct mdss_pll_resources *dsi_pll_res)
+static void pll_20nm_config_bypass_cal(void __iomem *pll_base)
+{
+ MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL, 0xac);
+ MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN, 0x28);
+}
+
+static int pll_20nm_vco_relock(struct mdss_pll_resources *dsi_pll_res)
{
int rc = 0;
- struct mdss_pll_vco_calc vco_calc;
- pll_20nm_config_common_block(dsi_pll_res->pll_base);
- pll_20nm_config_loop_bw(dsi_pll_res->pll_base);
+ pll_20nm_override_trim_codes(dsi_pll_res);
+ pll_20nm_config_bypass_cal(dsi_pll_res->pll_base);
+ pll_20nm_config_vco_start(dsi_pll_res->pll_base);
- pll_20nm_vco_rate_calc(&vco_calc, dsi_pll_res->vco_current_rate,
- dsi_pll_res->vco_ref_clk_rate);
- pll_20nm_config_vco_rate(dsi_pll_res->pll_base, &vco_calc);
+ if (!pll_20nm_is_pll_locked(dsi_pll_res)) {
+ pr_err("DSI PLL re-lock failed\n");
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int pll_20nm_vco_init_lock(struct mdss_pll_resources *dsi_pll_res)
+{
+ int rc = 0;
pll_20nm_config_resetsm(dsi_pll_res->pll_base);
pll_20nm_config_vco_start(dsi_pll_res->pll_base);
if (!pll_20nm_is_pll_locked(dsi_pll_res)) {
- pr_err("DSI PLL lock failed\n");
+ pr_err("DSI PLL init lock failed\n");
rc = -EINVAL;
goto init_lock_err;
}
- pr_debug("DSI PLL Lock success\n");
pll_20nm_cache_trim_codes(dsi_pll_res);
init_lock_err:
@@ -944,13 +968,38 @@ init_lock_err:
int pll_20nm_vco_enable_seq(struct mdss_pll_resources *dsi_pll_res)
{
int rc = 0;
+ struct mdss_pll_vco_calc vco_calc;
if (!dsi_pll_res) {
pr_err("Invalid PLL resources\n");
return -EINVAL;
}
- rc = pll_20nm_vco_init_lock(dsi_pll_res);
+ pll_20nm_config_common_block(dsi_pll_res->pll_base);
+ pll_20nm_config_loop_bw(dsi_pll_res->pll_base);
+
+ pll_20nm_vco_rate_calc(&vco_calc, dsi_pll_res->vco_current_rate,
+ dsi_pll_res->vco_ref_clk_rate);
+ pll_20nm_config_vco_rate(dsi_pll_res->pll_base, &vco_calc);
+
+ pr_debug("init lock=%d prev vco_rate=%llu, new vco_rate=%llu\n",
+ dsi_pll_res->is_init_locked, dsi_pll_res->vco_locking_rate,
+ dsi_pll_res->vco_current_rate);
+ /*
+ * Run auto-lock sequence if it is either bootup initial
+ * locking or when the vco rate is changed. Otherwise, just
+ * use stored codes and bypass caliberation.
+ */
+ if (!dsi_pll_res->is_init_locked || (dsi_pll_res->vco_locking_rate !=
+ dsi_pll_res->vco_current_rate)) {
+ rc = pll_20nm_vco_init_lock(dsi_pll_res);
+ dsi_pll_res->is_init_locked = (rc) ? false : true;
+ } else {
+ rc = pll_20nm_vco_relock(dsi_pll_res);
+ }
+
+ dsi_pll_res->vco_locking_rate = (rc) ? 0 :
+ dsi_pll_res->vco_current_rate;
return rc;
}
diff --git a/drivers/clk/msm/mdss/mdss-pll.h b/drivers/clk/msm/mdss/mdss-pll.h
index 92c27bc7da44..1e51e6ec4280 100644
--- a/drivers/clk/msm/mdss/mdss-pll.h
+++ b/drivers/clk/msm/mdss/mdss-pll.h
@@ -62,7 +62,9 @@ struct mdss_pll_resources {
void __iomem *gdsc_base;
void __iomem *dyn_pll_base;
+ bool is_init_locked;
s64 vco_current_rate;
+ s64 vco_locking_rate;
s64 vco_ref_clk_rate;
/*