clk: msm: mdss: fix DP register configurations

This change provides the below updates:

- Current DP PLL driver uses the pll_base and the base
  address for the TXn registers instead of phy_base address.
  Fix this by using the correct base address.

- Disable handoff for vco_divided_clk
  by implementing handoff function for this clock.

- Update the PLL settings to fix PLL locking issues.

CRs-Fixed: 1009740
Change-Id: Iea46c5b0482bceb841309175ede42ec3be3e20fd
Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
This commit is contained in:
Chandan Uddaraju 2016-05-11 11:46:49 -07:00 committed by Kyle Yan
parent d98ad5e9f4
commit b96f15ac07
3 changed files with 80 additions and 54 deletions

View file

@ -159,7 +159,7 @@ int hsclk_divsel_get_div(struct div_clk *clk)
pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div); pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div);
return hsclk_div; return div;
} }
int vco_divided_clk_set_div(struct div_clk *clk, int div) int vco_divided_clk_set_div(struct div_clk *clk, int div)
@ -178,8 +178,10 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div)
auxclk_div &= ~0x03; /* bits 0 to 1 */ auxclk_div &= ~0x03; /* bits 0 to 1 */
if (div == 4) if (div == 4)
auxclk_div |= 2; auxclk_div |= 2;
else else if (div == 2)
auxclk_div |= 1; auxclk_div |= 1;
else
auxclk_div |= 2; /* Default divider */
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
DP_PHY_VCO_DIV, auxclk_div); DP_PHY_VCO_DIV, auxclk_div);
@ -191,6 +193,16 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div)
return rc; return rc;
} }
enum handoff vco_divided_clk_handoff(struct clk *c)
{
/*
* Since cont-splash is not enabled, disable handoff
* for vco_divider_clk.
*/
return HANDOFF_DISABLED_CLK;
}
int vco_divided_clk_get_div(struct div_clk *clk) int vco_divided_clk_get_div(struct div_clk *clk)
{ {
int rc; int rc;
@ -208,8 +220,11 @@ int vco_divided_clk_get_div(struct div_clk *clk)
if (auxclk_div == 2) if (auxclk_div == 2)
div = 4; div = 4;
else else if (auxclk_div == 1)
div = 2; div = 2;
else
div = 0;
mdss_pll_resource_enable(dp_res, false); mdss_pll_resource_enable(dp_res, false);
pr_debug("%s: auxclk_div=%d, div=%d\n", __func__, auxclk_div, div); pr_debug("%s: auxclk_div=%d, div=%d\n", __func__, auxclk_div, div);
@ -223,13 +238,15 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
struct mdss_pll_resources *dp_res = vco->priv; struct mdss_pll_resources *dp_res = vco->priv;
MDSS_PLL_REG_W(dp_res->phy_base, MDSS_PLL_REG_W(dp_res->phy_base,
DP_PHY_PD_CTL, 0x39); DP_PHY_PD_CTL, 0x3d);
MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_PLL_IVCO, 0x0f);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_SYSCLK_EN_SEL, 0x37); QSERDES_COM_SYSCLK_EN_SEL, 0x37);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_SYS_CLK_CTRL, 0x02); QSERDES_COM_SYS_CLK_CTRL, 0x06);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CLK_ENABLE1, 0x0e); QSERDES_COM_CLK_ENABLE1, 0x0e);
@ -239,41 +256,41 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
QSERDES_COM_CLK_SEL, 0x30); QSERDES_COM_CLK_SEL, 0x30);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_LOCK_CMP_EN, 0x08); QSERDES_COM_LOCK_CMP_EN, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_PLL_CCTRL_MODE0, 0x34); QSERDES_COM_PLL_CCTRL_MODE0, 0x34);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_PLL_RCTRL_MODE0, 0x16); QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CP_CTRL_MODE0, 0x08); QSERDES_COM_CP_CTRL_MODE0, 0x08);
/* Different for 2700 & 5400 Mhz clock rates */ /* Different for each clock rates */
if (rate == DP_VCO_RATE_8100MHz) { if (rate == DP_VCO_RATE_8100MHz) {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DEC_START_MODE0, 0x69); QSERDES_COM_DEC_START_MODE0, 0x69);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START1_MODE0, 0x9a); QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START2_MODE0, 0x29); QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07);
} else if (rate == DP_VCO_RATE_9720MHz) { } else if (rate == DP_VCO_RATE_9720MHz) {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DEC_START_MODE0, 0x7e); QSERDES_COM_DEC_START_MODE0, 0x7e);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START1_MODE0, 0x52); QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START2_MODE0, 0x98); QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START3_MODE0, 0x08); QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09);
} else if (rate == DP_VCO_RATE_10800MHz) { } else if (rate == DP_VCO_RATE_10800MHz) {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DEC_START_MODE0, 0x8c); QSERDES_COM_DEC_START_MODE0, 0x8c);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START1_MODE0, 0xcd); QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START2_MODE0, 0x8c); QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09); QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a);
} else { } else {
pr_err("%s: unsupported rate: %ld\n", __func__, rate); pr_err("%s: unsupported rate: %ld\n", __func__, rate);
return -EINVAL; return -EINVAL;
@ -322,91 +339,96 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CORE_CLK_EN, 0x0f); QSERDES_COM_CORE_CLK_EN, 0x0f);
/* Different for 2700 Mhz clock rate */ /* Different for each clock rate */
if (rate == DP_VCO_RATE_8100MHz) { if (rate == DP_VCO_RATE_8100MHz) {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CMN_CONFIG, 0x02); QSERDES_COM_CMN_CONFIG, 0x02);
} else if (rate == DP_VCO_RATE_9720MHz) { } else if (rate == DP_VCO_RATE_9720MHz) {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CMN_CONFIG, 0x42); QSERDES_COM_CMN_CONFIG, 0x02);
} else { } else {
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_COM_CMN_CONFIG, 0x12); QSERDES_COM_CMN_CONFIG, 0x02);
} }
/* Configuration for 1620Mhz VCO frequency */ MDSS_PLL_REG_W(dp_res->phy_base,
MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
0x1a); 0x1a);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
0x1a); 0x1a);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL,
0x38);
MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL,
0x38);
MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL,
0x2c);
MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL,
0x2c);
MDSS_PLL_REG_W(dp_res->phy_base,
DP_PHY_TX0_TX1_LANE_CTL, 0x05); DP_PHY_TX0_TX1_LANE_CTL, 0x05);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
DP_PHY_TX2_TX3_LANE_CTL, 0x05); DP_PHY_TX2_TX3_LANE_CTL, 0x05);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1,
0x40); 0x40);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1,
0x40); 0x40);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN,
0x30); 0x30);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, QSERDES_TX1_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN,
0x30); 0x30);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_INTERFACE_SELECT, QSERDES_TX0_OFFSET + TXn_INTERFACE_SELECT,
0x3d); 0x3d);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_INTERFACE_SELECT, QSERDES_TX1_OFFSET + TXn_INTERFACE_SELECT,
0x3d); 0x3d);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE,
0x0f); 0x0f);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE,
0x0f); 0x0f);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_RESET_TSYNC_EN, QSERDES_TX0_OFFSET + TXn_RESET_TSYNC_EN,
0x03); 0x03);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_RESET_TSYNC_EN, QSERDES_TX1_OFFSET + TXn_RESET_TSYNC_EN,
0x03); 0x03);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TRAN_DRVR_EMP_EN, QSERDES_TX0_OFFSET + TXn_TRAN_DRVR_EMP_EN,
0x03); 0x03);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TRAN_DRVR_EMP_EN, QSERDES_TX1_OFFSET + TXn_TRAN_DRVR_EMP_EN,
0x03); 0x03);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, QSERDES_TX0_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, QSERDES_TX1_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TX_INTERFACE_MODE, QSERDES_TX0_OFFSET + TXn_TX_INTERFACE_MODE,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE,
0x00); 0x00);
MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL,
0x23);
MDSS_PLL_REG_W(dp_res->pll_base,
QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL,
0x23);
return res; return res;
} }
@ -491,22 +513,22 @@ static int dp_pll_enable(struct clk *c)
pr_debug("%s: PLL is locked\n", __func__); pr_debug("%s: PLL is locked\n", __func__);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
0x3f); 0x3f);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
0x3f); 0x3f);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
0x10); 0x10);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
0x10); 0x10);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TX_POL_INV, QSERDES_TX0_OFFSET + TXn_TX_POL_INV,
0x0a); 0x0a);
MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TX_POL_INV, QSERDES_TX1_OFFSET + TXn_TX_POL_INV,
0x0a); 0x0a);
MDSS_PLL_REG_W(dp_res->phy_base, MDSS_PLL_REG_W(dp_res->phy_base,

View file

@ -231,6 +231,7 @@ int dp_pll_clock_register_cobalt(struct platform_device *pdev,
*/ */
clk_ops_vco_divided_clk_src_c = clk_ops_slave_div; clk_ops_vco_divided_clk_src_c = clk_ops_slave_div;
clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare;
clk_ops_vco_divided_clk_src_c.handoff = vco_divided_clk_handoff;
/* We can select different clock ops for future versions */ /* We can select different clock ops for future versions */
dp_vco_clk.c.ops = &dp_cobalt_vco_clk_ops; dp_vco_clk.c.ops = &dp_cobalt_vco_clk_ops;

View file

@ -51,6 +51,8 @@
#define TXn_CLKBUF_ENABLE 0x0008 #define TXn_CLKBUF_ENABLE 0x0008
#define TXn_TX_EMP_POST1_LVL 0x000C #define TXn_TX_EMP_POST1_LVL 0x000C
#define TXn_TX_DRV_LVL 0x001C
#define TXn_RESET_TSYNC_EN 0x0024 #define TXn_RESET_TSYNC_EN 0x0024
#define TXn_PRE_STALL_LDO_BOOST_EN 0x0028 #define TXn_PRE_STALL_LDO_BOOST_EN 0x0028
#define TXn_TX_BAND 0x002C #define TXn_TX_BAND 0x002C
@ -154,6 +156,7 @@ int dp_vco_set_rate(struct clk *c, unsigned long rate);
unsigned long dp_vco_get_rate(struct clk *c); unsigned long dp_vco_get_rate(struct clk *c);
long dp_vco_round_rate(struct clk *c, unsigned long rate); long dp_vco_round_rate(struct clk *c, unsigned long rate);
enum handoff dp_vco_handoff(struct clk *c); enum handoff dp_vco_handoff(struct clk *c);
enum handoff vco_divided_clk_handoff(struct clk *c);
int dp_vco_prepare(struct clk *c); int dp_vco_prepare(struct clk *c);
void dp_vco_unprepare(struct clk *c); void dp_vco_unprepare(struct clk *c);
int hsclk_divsel_set_div(struct div_clk *clk, int div); int hsclk_divsel_set_div(struct div_clk *clk, int div);