summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandan Uddaraju <chandanu@codeaurora.org>2014-06-21 23:30:41 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:41:20 -0700
commit303869b47ed1ca962fc40997a2264eaebd58f5cf (patch)
tree66fd9fa702c37185a30016345adb0c740ccf7b7c
parentc021117747be8982d70e57ee95db0a9977a9a046 (diff)
clk: mdss-dsi-pll: add support for auto PLL calculator for 20nm PHY
Add code to support DSI auto PLL calculator for 8994 platform that uses 20nm physical layer. Update the PLL configuration and DSI PHY regulator configurations to the recommended settings. Change-Id: Ia3d7042d537539491317f99d7bcc2c480f850216 Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c203
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c7
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll.h2
3 files changed, 130 insertions, 82 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 bc17bd2fd0d4..9ee5748a2372 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-20nm-pll-util.c
@@ -53,7 +53,7 @@
#define MMSS_DSI_PHY_PLL_KVCO_CODE 0x0074
#define MMSS_DSI_PHY_PLL_VREF_CFG1 0x0078
#define MMSS_DSI_PHY_PLL_VREF_CFG2 0x007C
-#define MMSS_DSI_PHY_PLL_VREF_CFG3 0x0000
+#define MMSS_DSI_PHY_PLL_VREF_CFG3 0x0080
#define MMSS_DSI_PHY_PLL_VREF_CFG4 0x0084
#define MMSS_DSI_PHY_PLL_VREF_CFG5 0x0088
#define MMSS_DSI_PHY_PLL_VREF_CFG6 0x008C
@@ -99,8 +99,8 @@
#define MMSS_DSI_PHY_PLL_PLL_VCO_HIGH 0x014C
#define MMSS_DSI_PHY_PLL_RESET_SM 0x0150
-#define DSI_PLL_POLL_MAX_READS 10
-#define DSI_PLL_POLL_TIMEOUT_US 500
+#define DSI_PLL_POLL_MAX_READS 15
+#define DSI_PLL_POLL_TIMEOUT_US 1000
int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel)
@@ -329,7 +329,7 @@ static void dsi_pll_disable(struct clk *c)
dsi_pll_res->handoff_resources = false;
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x00);
+ MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x02);
mdss_pll_resource_enable(dsi_pll_res, false);
dsi_pll_res->pll_on = false;
@@ -338,12 +338,34 @@ static void dsi_pll_disable(struct clk *c)
return;
}
-void pll_20nm_dsi_phy_ctrl_config(struct mdss_pll_resources *dsi_pll_res,
+static inline void pll_20nm_phy_reset_state_machine_ctrl
+ (struct mdss_pll_resources *dsi_pll_res)
+{
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RES_CODE_START_SEG1, 0x64);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RES_CODE_START_SEG2, 0x64);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RES_TRIM_CONTROL, 0x15);
+
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RESETSM_CNTRL, 0x20);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RESETSM_CNTRL2, 0x07);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x02);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x03);
+}
+
+void dsi_pll_20nm_phy_ctrl_config(struct mdss_pll_resources *dsi_pll_res,
int off)
{
+ pll_20nm_phy_reset_state_machine_ctrl(dsi_pll_res);
+ wmb();
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0174, 0x80);
- wmb();
+ udelay(1000);
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0174, 0x00);
@@ -351,15 +373,12 @@ void pll_20nm_dsi_phy_ctrl_config(struct mdss_pll_resources *dsi_pll_res,
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0184, 0x77);
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0170, 0x7f);
- wmb();
/* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x01d4, 0x00);
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_2 */
MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0178, 0x00);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0178, 0x02);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base, off + 0x0178, 0x03);
}
static void pll_20nm_phy_kvco_config(struct dsi_pll_vco_clk *vco)
@@ -367,47 +386,27 @@ static void pll_20nm_phy_kvco_config(struct dsi_pll_vco_clk *vco)
struct mdss_pll_resources *dsi_pll_res = vco->priv;
MDSS_PLL_REG_W(dsi_pll_res->pll_base, MMSS_DSI_PHY_PLL_DIV_REF1, 0x00);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base, MMSS_DSI_PHY_PLL_DIV_REF2, 0x00);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base, MMSS_DSI_PHY_PLL_DIV_REF2, 0x01);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_KVCO_COUNT1, 0x00);
+ MMSS_DSI_PHY_PLL_KVCO_COUNT1, 0x8A);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_KVCO_CAL_CNTRL, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_KVCO_CODE, 0x2A);
+ MMSS_DSI_PHY_PLL_KVCO_CODE, 0x00);
}
static void pll_20nm_phy_loop_bw_config(struct mdss_pll_resources *dsi_pll_res)
{
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_IP_SETI, 0x01);
+ MMSS_DSI_PHY_PLL_PLL_IP_SETI, 0x03);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_CP_SETI, 0x2F);
+ MMSS_DSI_PHY_PLL_PLL_CP_SETI, 0x3F);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_IP_SETP, 0x13);
+ MMSS_DSI_PHY_PLL_PLL_IP_SETP, 0x03);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_CP_SETP, 0x0F);
+ MMSS_DSI_PHY_PLL_PLL_CP_SETP, 0x1F);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_CRCTRL, 0x24);
-}
-
-static void pll_20nm_phy_reset_st_machine_ctrl
- (struct mdss_pll_resources *dsi_pll_res)
-{
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RES_CODE_START_SEG1, 0x64);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RES_CODE_START_SEG2, 0x64);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RES_TRIM_CONTROL, 0x15);
-
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RESETSM_CNTRL, 0xf4);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RESETSM_CNTRL2, 0x0f);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x02);
- MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x03);
+ MMSS_DSI_PHY_PLL_PLL_CRCTRL, 0x77);
}
static void pll_20nm_phy_config(struct dsi_pll_vco_clk *vco)
@@ -447,11 +446,15 @@ static void pll_20nm_phy_config(struct dsi_pll_vco_clk *vco)
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_VREF_CFG2, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_VREF_CFG3, 0x10);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_VREF_CFG4, 0x00);
+ MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_BGTC, 0x0F);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_PLL_TEST_UPDN, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLL_VCO_TUNE, 0x01);
+ MMSS_DSI_PHY_PLL_PLL_VCO_TUNE, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_PLL_AMP_OS, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
@@ -461,7 +464,7 @@ static void pll_20nm_phy_config(struct dsi_pll_vco_clk *vco)
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_RES_CODE_DN, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_RES_CODE_CAL_CSR, 0x77);
+ MMSS_DSI_PHY_PLL_RES_CODE_CAL_CSR, 0x00);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_RES_TRIM_EN_VCOCALDONE, 0x0);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
@@ -478,61 +481,103 @@ static void pll_20nm_phy_config(struct dsi_pll_vco_clk *vco)
int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate)
{
s64 vco_clk_rate = rate;
- s32 div_frac_start, frac_act_div;
- s64 dec_start;
- s64 duration, pll_comp_val;
+ s32 div_frac_start;
+ s32 div_frac_start1, div_frac_start2, div_frac_start3;
+ s64 dec_start_multiple, dec_start, multiplier = (1 << 20);
+ s64 dec_start1, dec_start2;
+ s64 duration = 128, pll_comp_val;
+ s64 pll_plllock_cmp1, pll_plllock_cmp2, pll_plllock_cmp3;
+
struct mdss_pll_resources *dsi_pll_res = vco->priv;
- pr_debug("%s: vco set rate: %ld\n", __func__, rate);
+ pr_debug("%s: vco set rate: %lld\n", __func__, vco_clk_rate);
pll_20nm_phy_config(vco);
- dec_start = div_s64(vco_clk_rate, 2 * vco->ref_clk_rate);
- div_s64_rem(vco_clk_rate,
- 2 * vco->ref_clk_rate, &frac_act_div);
- div_frac_start = frac_act_div << 18;
+ dec_start_multiple = div_s64(vco_clk_rate * multiplier,
+ 2 * vco->ref_clk_rate);
+ div_s64_rem(dec_start_multiple,
+ multiplier, &div_frac_start);
+
+ dec_start = div_s64(dec_start_multiple, multiplier);
+ pr_debug("%s: dec_start_multiple = 0x%llx\n",
+ __func__, dec_start_multiple);
+ pr_debug("%s: dec_start = 0x%llx, div_frac_start = 0x%x\n",
+ __func__, dec_start, div_frac_start);
+
+ dec_start1 = (dec_start & 0x7f) | BIT(7);
+ dec_start2 = ((dec_start & 0x80) >> 7) | BIT(1);
+ pr_debug("%s: dec_start1 = 0x%llx, dec_start2 = 0x%llx\n",
+ __func__, dec_start1, dec_start2);
+
+ div_frac_start1 = (div_frac_start & 0x7f) | BIT(7);
+ div_frac_start2 = ((div_frac_start >> 7) & 0x7f) | BIT(7);
+ div_frac_start3 = ((div_frac_start >> 14) & 0x3f) | BIT(6);
+ pr_debug("%s: div_frac_start1 = 0x%x\n",
+ __func__, div_frac_start1);
+ pr_debug("%s: div_frac_start2 = 0x%x\n",
+ __func__, div_frac_start2);
+ pr_debug("%s: div_frac_start3 = 0x%x\n",
+ __func__, div_frac_start3);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START1, 0xd5);
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START1,
+ div_frac_start1);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START2, 0xaa);
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START2,
+ div_frac_start2);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START3, 0x79);
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START3,
+ div_frac_start3);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DEC_START1, 0xac);
+ MMSS_DSI_PHY_PLL_DEC_START1,
+ dec_start1);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DEC_START2, 0x2);
+ MMSS_DSI_PHY_PLL_DEC_START2,
+ dec_start2);
+
+ pll_comp_val = div_s64(dec_start_multiple * 2 * (duration - 1),
+ 10 * multiplier);
- duration = 128;
- pll_comp_val = div_s64(div_s64(vco_clk_rate,
- 2 * vco->ref_clk_rate)
- * (duration - 1), 10);
+ pr_debug("%s: pll_comp_val = 0x%llx\n", __func__, pll_comp_val);
+
+ pll_plllock_cmp1 = pll_comp_val & 0xff;
+ pll_plllock_cmp2 = (pll_comp_val >> 8) & 0xff;
+ pll_plllock_cmp3 = (pll_comp_val >> 16) & 0xff;
+ pr_debug("%s: pll_plllock_cmp1 = 0x%llx\n",
+ __func__, pll_plllock_cmp1);
+ pr_debug("%s: pll_plllock_cmp2 = 0x%llx\n",
+ __func__, pll_plllock_cmp2);
+ pr_debug("%s: pll_plllock_cmp3 = 0x%llx\n",
+ __func__, pll_plllock_cmp3);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLLLOCK_CMP1, 0x74);
+ MMSS_DSI_PHY_PLL_PLLLOCK_CMP1,
+ pll_plllock_cmp1);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLLLOCK_CMP2, 0x04);
+ MMSS_DSI_PHY_PLL_PLLLOCK_CMP2,
+ pll_plllock_cmp2);
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_PLLLOCK_CMP3, 0x00);
+ MMSS_DSI_PHY_PLL_PLLLOCK_CMP3,
+ pll_plllock_cmp3);
/*
* Make sure that PLL vco configuration is complete
* before controlling the state machine.
*/
- mb();
udelay(1000);
- pll_20nm_phy_reset_st_machine_ctrl(dsi_pll_res);
+ wmb();
return 0;
}
unsigned long pll_20nm_vco_get_rate(struct clk *c)
{
- u64 vco_rate;
+ u64 vco_rate, multiplier = (1 << 20);
s32 div_frac_start;
u32 dec_start;
struct dsi_pll_vco_clk *vco = to_vco_clk(c);
@@ -546,27 +591,25 @@ unsigned long pll_20nm_vco_get_rate(struct clk *c)
return rc;
}
- dec_start = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DEC_START2) << 7;
- dec_start |= MDSS_PLL_REG_R(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DEC_START1);
+ dec_start = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_DEC_START2) & BIT(0)) << 7;
+ dec_start |= (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_DEC_START1) & 0x7f);
+ pr_debug("%s: dec_start = 0x%x\n", __func__, dec_start);
- div_frac_start = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START3) << 14;
+ div_frac_start = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START3) & 0x3f) << 14;
div_frac_start |= (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START2) << 7);
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START2) & 0x7f) << 7;
div_frac_start |= MDSS_PLL_REG_R(dsi_pll_res->pll_base,
- MMSS_DSI_PHY_PLL_DIV_FRAC_START1);
-
- vco_rate = ref_clk * 2 * (dec_start + (div_frac_start >> 18));
- pr_debug("vco rate = %lld", vco_rate);
-
- /*
- * TODO: Currently, the dyanmic vco calculator is not finalized.
- * Hardcoding the vco_rate for now.
- */
- vco_rate = 1708439040;
- pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
+ MMSS_DSI_PHY_PLL_DIV_FRAC_START1) & 0x7f;
+ pr_debug("%s: div_frac_start = 0x%x\n",
+ __func__, div_frac_start);
+
+ vco_rate = ref_clk * 2 * dec_start;
+ vco_rate += ((ref_clk * 2 * div_frac_start) / multiplier);
+ pr_debug("%s: returning vco rate = %lu\n",
+ __func__, (unsigned long)vco_rate);
mdss_pll_resource_enable(dsi_pll_res, false);
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c b/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c
index debe96828a40..e7074a6ef778 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c
@@ -65,7 +65,12 @@ static int dsi_pll_enable_seq_8994(struct mdss_pll_resources *dsi_pll_res)
MDSS_PLL_REG_W(dsi_pll_res->pll_base,
MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN, 0x00);
udelay(500);
- pll_20nm_dsi_phy_ctrl_config(dsi_pll_res, 0x200); /* Ctrl 0 */
+ dsi_pll_20nm_phy_ctrl_config(dsi_pll_res, 0x200); /* Ctrl 0 */
+ /*
+ * Make sure that the PHY controller configurations are completed
+ * before checking the pll lock status.
+ */
+ wmb();
pll_locked = dsi_20nm_pll_lock_status(dsi_pll_res);
if (!pll_locked) {
pr_err("DSI PLL lock failed\n");
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll.h b/drivers/clk/msm/mdss/mdss-dsi-pll.h
index b0135dc0109b..1060bc436044 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll.h
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll.h
@@ -68,7 +68,7 @@ int digital_get_div(struct div_clk *clk);
int analog_set_div(struct div_clk *clk, int div);
int analog_get_div(struct div_clk *clk);
int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res);
-void pll_20nm_dsi_phy_ctrl_config
+void dsi_pll_20nm_phy_ctrl_config
(struct mdss_pll_resources *dsi_pll_res, int off);
int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate);
unsigned long vco_get_rate(struct clk *c);