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

Commit 3f5563da authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: msm: mdss: update Dp PLL/Phy configuration" into msm-4.8

parents d09b7efc e95883b0
Loading
Loading
Loading
Loading
+209 −167
Original line number Diff line number Diff line
@@ -49,13 +49,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div)
	link2xclk_div_tx1 |= 0x4;

	/*configure DP PHY MODE */
	phy_mode = 0x48;
	phy_mode = 0x58;

	if (div == 10) {
		link2xclk_div_tx0 |= 1;
		link2xclk_div_tx1 |= 1;
		phy_mode |= 1;
	}
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_BAND,
			link2xclk_div_tx0);
@@ -64,7 +59,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div)
			link2xclk_div_tx1);
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_MODE, phy_mode);

	/* Make sure the PHY register writes are done */
	wmb();

	pr_debug("%s: div=%d link2xclk_div_tx0=%x, link2xclk_div_tx1=%x\n",
			__func__, div, link2xclk_div_tx0, link2xclk_div_tx1);
@@ -105,63 +101,6 @@ int link2xclk_divsel_get_div(struct div_clk *clk)
	return div;
}

int hsclk_divsel_set_div(struct div_clk *clk, int div)
{
	int rc;
	u32 hsclk_div;
	struct mdss_pll_resources *dp_res = clk->priv;

	rc = mdss_pll_resource_enable(dp_res, true);
	if (rc) {
		pr_err("Failed to enable mdss DP PLL resources\n");
		return rc;
	}

	hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL);
	hsclk_div &= ~0x0f;	/* bits 0 to 3 */

	if (div == 3)
		hsclk_div |= 4;
	else
		hsclk_div |= 0;

	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_HSCLK_SEL, hsclk_div);

	pr_debug("%s: div=%d hsclk_div=%x\n", __func__, div, hsclk_div);

	mdss_pll_resource_enable(dp_res, false);

	return rc;
}

int hsclk_divsel_get_div(struct div_clk *clk)
{
	int rc;
	u32 hsclk_div, div;
	struct mdss_pll_resources *dp_res = clk->priv;

	rc = mdss_pll_resource_enable(dp_res, true);
	if (rc) {
		pr_err("Failed to enable dp_res resources\n");
		return rc;
	}

	hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL);
	hsclk_div &= 0x0f;

	if (hsclk_div == 4)
		div = 3;
	else
		div = 2;

	mdss_pll_resource_enable(dp_res, false);

	pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div);

	return div;
}

int vco_divided_clk_set_div(struct div_clk *clk, int div)
{
	int rc;
@@ -174,18 +113,18 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div)
		return rc;
	}

	auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV);
	auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV);
	auxclk_div &= ~0x03;	/* bits 0 to 1 */

	auxclk_div |= 1; /* Default divider */

	if (div == 4)
		auxclk_div |= 2;
	else if (div == 2)
		auxclk_div |= 1;
	else
		auxclk_div |= 2; /* Default divider */

	MDSS_PLL_REG_W(dp_res->pll_base,
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_VCO_DIV, auxclk_div);

	/* Make sure the PHY registers writes are done */
	wmb();
	pr_debug("%s: div=%d auxclk_div=%x\n", __func__, div, auxclk_div);

	mdss_pll_resource_enable(dp_res, false);
@@ -215,15 +154,12 @@ int vco_divided_clk_get_div(struct div_clk *clk)
		return rc;
	}

	auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV);
	auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV);
	auxclk_div &= 0x03;

	div = 2; /* Default divider */
	if (auxclk_div == 2)
		div = 4;
	else if (auxclk_div == 1)
		div = 2;
	else
		div = 0;

	mdss_pll_resource_enable(dp_res, false);

@@ -239,14 +175,12 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_PD_CTL, 0x3d);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_PLL_IVCO, 0x0f);
	/* Make sure the PHY register writes are done */
	wmb();
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_SYSCLK_EN_SEL, 0x37);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_SYS_CLK_CTRL, 0x06);

	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CLK_ENABLE1, 0x0e);
@@ -255,16 +189,16 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CLK_SEL, 0x30);

	/* Different for each clock rates */
	if (rate == DP_VCO_HSCLK_RATE_1620MHz) {
		pr_debug("%s: VCO rate: %lld\n", __func__,
				DP_VCO_RATE_8100MHz);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP_EN, 0x00);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_PLL_CCTRL_MODE0, 0x34);
			QSERDES_COM_SYS_CLK_CTRL, 0x02);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
			QSERDES_COM_HSCLK_SEL, 0x2c);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CP_CTRL_MODE0, 0x08);
	/* Different for each clock rates */
	if (rate == DP_VCO_RATE_8100MHz) {
			QSERDES_COM_LOCK_CMP_EN, 0x04);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DEC_START_MODE0, 0x69);
		MDSS_PLL_REG_W(dp_res->pll_base,
@@ -273,58 +207,88 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
			QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07);
	} else if (rate == DP_VCO_RATE_9720MHz) {
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DEC_START_MODE0, 0x7e);
			QSERDES_COM_CMN_CONFIG, 0x42);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
			QSERDES_COM_LOCK_CMP1_MODE0, 0xbf);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00);
			QSERDES_COM_LOCK_CMP2_MODE0, 0x21);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09);
	} else if (rate == DP_VCO_RATE_10800MHz) {
			QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
	} else if (rate == DP_VCO_HSCLK_RATE_2700MHz) {
		pr_debug("%s: VCO rate: %lld\n", __func__,
				DP_VCO_RATE_8100MHz);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DEC_START_MODE0, 0x8c);
			QSERDES_COM_SYS_CLK_CTRL, 0x06);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
			QSERDES_COM_HSCLK_SEL, 0x84);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00);
			QSERDES_COM_LOCK_CMP_EN, 0x08);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a);
	} else {
		pr_err("%s: unsupported rate: %ld\n", __func__, rate);
		return -EINVAL;
	}

			QSERDES_COM_DEC_START_MODE0, 0x69);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f);
			QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
			QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_VCO_TUNE_MAP, 0x00);

	if (rate == DP_VCO_RATE_8100MHz) {
			QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CMN_CONFIG, 0x02);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP1_MODE0, 0x3f);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP2_MODE0, 0x38);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
	} else if (rate == DP_VCO_RATE_9720MHz) {
	} else if (rate == DP_VCO_HSCLK_RATE_5400MHz) {
		pr_debug("%s: VCO rate: %lld\n", __func__,
				DP_VCO_RATE_10800MHz);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP1_MODE0, 0x7f);
			QSERDES_COM_SYS_CLK_CTRL, 0x06);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP2_MODE0, 0x43);
			QSERDES_COM_HSCLK_SEL, 0x80);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
	} else {
			QSERDES_COM_LOCK_CMP_EN, 0x08);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DEC_START_MODE0, 0x8c);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CMN_CONFIG, 0x12);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP1_MODE0, 0x7f);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP2_MODE0, 0x70);
		MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
	} else {
		pr_err("%s: unsupported rate: %ld\n", __func__, rate);
		return -EINVAL;
	}
	/* Make sure the PLL register writes are done */
	wmb();

	if ((rate == DP_VCO_HSCLK_RATE_1620MHz)
	    || (rate == DP_VCO_HSCLK_RATE_2700MHz)) {
		MDSS_PLL_REG_W(dp_res->phy_base,
				DP_PHY_VCO_DIV, 0x1);
	} else {
		MDSS_PLL_REG_W(dp_res->phy_base,
				DP_PHY_VCO_DIV, 0x2);
	}
	/* Make sure the PHY register writes are done */
	wmb();

	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_VCO_TUNE_MAP, 0x00);

	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_BG_TIMER, 0x00);
@@ -335,58 +299,42 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_VCO_TUNE_CTRL, 0x00);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37);
			QSERDES_COM_CP_CTRL_MODE0, 0x06);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CORE_CLK_EN, 0x0f);

	/* Different for each clock rate */
	if (rate == DP_VCO_RATE_8100MHz) {
			QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CMN_CONFIG, 0x02);
	} else if (rate == DP_VCO_RATE_9720MHz) {
			QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CMN_CONFIG, 0x02);
	} else {
			QSERDES_COM_PLL_IVCO, 0x07);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CMN_CONFIG, 0x02);
	}
			QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37);
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_CORE_CLK_EN, 0x0f);

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x1a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x1a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
			0x00);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
			0x00);
	/* Make sure the PLL register writes are done */
	wmb();

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL,
			0x38);
			DP_PHY_MODE, 0x58);
	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);
			DP_PHY_TX0_TX1_LANE_CTL, 0x05);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL,
			0x2c);
			DP_PHY_TX2_TX3_LANE_CTL, 0x05);

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_TX0_TX1_LANE_CTL, 0x05);
			QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x1a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_TX2_TX3_LANE_CTL, 0x05);
			QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x1a);

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1,
			0x40);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1,
			0x40);

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN,
			0x30);
@@ -429,6 +377,15 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE,
			0x00);

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_BAND,
			0x4);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TX_BAND,
			0x4);
	/* Make sure the PHY register writes are done */
	wmb();
	return res;
}

@@ -479,9 +436,12 @@ static int dp_pll_enable(struct clk *c)
			DP_PHY_CFG, 0x01);
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x09);
	/* Make sure the PHY register writes are done */
	wmb();
	MDSS_PLL_REG_W(dp_res->pll_base,
			QSERDES_COM_RESETSM_CNTRL, 0x20);

	/* Make sure the PLL register writes are done */
	wmb();
	/* poll for PLL ready status */
	if (readl_poll_timeout_atomic((dp_res->pll_base +
			QSERDES_COM_C_READY_STATUS),
@@ -497,7 +457,8 @@ static int dp_pll_enable(struct clk *c)

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x19);

	/* Make sure the PHY register writes are done */
	wmb();
	/* poll for PHY ready status */
	if (readl_poll_timeout_atomic((dp_res->phy_base +
			DP_PHY_STATUS),
@@ -513,17 +474,17 @@ static int dp_pll_enable(struct clk *c)

	pr_debug("%s: PLL is locked\n", __func__);

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x3f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x3f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
			QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
			0x10);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
			QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
			0x3f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
			0x10);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_POL_INV,
@@ -533,6 +494,8 @@ static int dp_pll_enable(struct clk *c)
			0x0a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x18);
	udelay(2000);

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x19);

@@ -542,6 +505,77 @@ static int dp_pll_enable(struct clk *c)
	 */
	wmb();

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_LANE_MODE_1,
			0xf6);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_LANE_MODE_1,
			0xf6);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE,
			0x1f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE,
			0x1f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE,
			0x0f);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE,
			0x0f);
	/*
	 * Make sure all the register writes are completed before
	 * doing any other operation
	 */
	wmb();

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x09);
	udelay(2000);

	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_CFG, 0x19);
	udelay(2000);
	/* poll for PHY ready status */
	if (readl_poll_timeout_atomic((dp_res->phy_base +
			DP_PHY_STATUS),
			status,
			((status & BIT(1)) > 0),
			DP_PLL_POLL_SLEEP_US,
			DP_PLL_POLL_TIMEOUT_US)) {
		pr_err("%s: Lane_mode: Phy_ready is not high. Status=%x\n",
				__func__, status);
		rc = -EINVAL;
		goto lock_err;
	}

	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL,
			0x2a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL,
			0x2a);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL,
			0x20);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL,
			0x20);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX,
			0x11);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX,
			0x11);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX,
			0x11);
	MDSS_PLL_REG_W(dp_res->phy_base,
			QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX,
			0x11);
	/* Make sure the PHY register writes are done */
	wmb();

lock_err:
	return rc;
}
@@ -554,7 +588,7 @@ static int dp_pll_disable(struct clk *c)

	/* Assert DP PHY power down */
	MDSS_PLL_REG_W(dp_res->phy_base,
			DP_PHY_PD_CTL, 0x3c);
			DP_PHY_PD_CTL, 0x2);
	/*
	 * Make sure all the register writes to disable PLL are
	 * completed before doing any other operation
@@ -655,14 +689,20 @@ unsigned long dp_vco_get_rate(struct clk *c)
	div = MDSS_PLL_REG_R(pll->pll_base, QSERDES_COM_HSCLK_SEL);
	div &= 0x0f;

	if (div == 4)
	if (div == 12)
		hsclk_div = 5; /* Default */
	else if (div == 4)
		hsclk_div = 3;
	else
	else if (div == 0)
		hsclk_div = 2;
	else {
		pr_debug("unknown divider. forcing to default\n");
		hsclk_div = 5;
	}

	div = MDSS_PLL_REG_R(pll->phy_base, DP_PHY_MODE);

	if (div & 0x48)
	if (div & 0x58)
		pr_err("%s: DP PAR Rate not correct\n", __func__);

	if ((div & 0x3) == 1)
@@ -673,12 +713,14 @@ unsigned long dp_vco_get_rate(struct clk *c)
		pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div);

	if (link2xclk_div == 10) {
		vco_rate = DP_VCO_RATE_9720MHz;
		vco_rate = DP_VCO_HSCLK_RATE_2700MHz;
	} else {
		if (hsclk_div == 3)
			vco_rate = DP_VCO_RATE_8100MHz;
		if (hsclk_div == 5)
			vco_rate = DP_VCO_HSCLK_RATE_1620MHz;
		else if (hsclk_div == 3)
			vco_rate = DP_VCO_HSCLK_RATE_2700MHz;
		else
			vco_rate = DP_VCO_RATE_10800MHz;
			vco_rate = DP_VCO_HSCLK_RATE_5400MHz;
	}

	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
@@ -695,8 +737,8 @@ long dp_vco_round_rate(struct clk *c, unsigned long rate)

	if (rate <= vco->min_rate)
		rrate = vco->min_rate;
	else if (rate <= DP_VCO_RATE_9720MHz)
		rrate = DP_VCO_RATE_9720MHz;
	else if (rate <= DP_VCO_HSCLK_RATE_2700MHz)
		rrate = DP_VCO_HSCLK_RATE_2700MHz;
	else
		rrate = vco->max_rate;

+64 −89
Original line number Diff line number Diff line
@@ -16,40 +16,37 @@
 ******** Display Port PLL driver block diagram for branch clocks **********
 ***************************************************************************

			   +-------------------+
			   |    dp_vco_clk     |
			   |   (DP PLL/VCO)    |
			   +---------+---------+
				     |
				     |
				     v
			  +----------+-----------+
			  | hsclk_divsel_clk_src |
			  +----------+-----------+
				     |
			+--------------------------+
			|       DP_VCO_CLK         |
			|			   |
			|  +-------------------+   |
			|  |   (DP PLL/VCO)    |   |
			|  +---------+---------+   |
			|	     v		   |
			| +----------+-----------+ |
			| | hsclk_divsel_clk_src | |
			| +----------+-----------+ |
			+--------------------------+
				     |
				     v
	   +------------<------------|------------>-------------+
	   |                         |                          |
	   |                         |                          |
+----------v----------+	  +----------v----------+    +----------v----------+
|vco_divided_clk_src  |	  |    dp_link_2x_clk	|    |	 dp_link_2x_clk	   |
|   (aux_clk_ops)     |	  |			|    |			   |
v----------+----------v	  |	divsel_five	|    |	   divsel_ten	   |
|   dp_link_2x_clk    |	  | vco_divided_clk_src	|    | vco_divided_clk_src |
|     divsel_five     |	  |			|    |			   |
v----------+----------v	  |	divsel_two	|    |	   divsel_four	   |
	   |		  +----------+----------+    +----------+----------+
	   |                         |                          |
	   v			     v				v
				     |	+--------------------+	|
  Input to MMSSCC block		     |	|		     |	|
   for DP pixel clock		     +--> dp_link_2x_clk_mux <--+
					|		     |
					+----------+---------+
				     |	+---------------------+	|
  Input to MMSSCC block		     |	|    (aux_clk_ops)    |	|
  for link clk, crypto clk	     +-->   vco_divided_clk   <-+
  and interface clock			|	_src_mux      |
					+----------+----------+
						   |
						   v
					 Input to MMSSCC block
					 for link clk, crypto clk
					 and interface clock

					 for DP pixel clock

 ******************************************************************************
 */
@@ -68,14 +65,9 @@ v----------+----------v | divsel_five | | divsel_ten |
#include "mdss-dp-pll.h"
#include "mdss-dp-pll-8998.h"

static const struct clk_ops clk_ops_hsclk_divsel_clk_src_c;
static const struct clk_ops clk_ops_vco_divided_clk_src_c;
static const struct clk_ops clk_ops_link_2x_clk_div_c;

static struct clk_div_ops hsclk_divsel_ops = {
	.set_div = hsclk_divsel_set_div,
	.get_div = hsclk_divsel_get_div,
};
static const struct clk_ops clk_ops_gen_mux_dp;

static struct clk_div_ops link2xclk_divsel_ops = {
	.set_div = link2xclk_divsel_set_div,
@@ -101,8 +93,8 @@ static struct clk_mux_ops mdss_mux_ops = {
};

static struct dp_pll_vco_clk dp_vco_clk = {
	.min_rate = DP_VCO_RATE_8100MHz,
	.max_rate = DP_VCO_RATE_10800MHz,
	.min_rate = DP_VCO_HSCLK_RATE_1620MHz,
	.max_rate = DP_VCO_HSCLK_RATE_5400MHz,
	.c = {
		.dbg_name = "dp_vco_clk",
		.ops = &dp_8998_vco_clk_ops,
@@ -111,21 +103,6 @@ static struct dp_pll_vco_clk dp_vco_clk = {
	},
};

static struct div_clk hsclk_divsel_clk_src = {
	.data = {
		.min_div = 2,
		.max_div = 3,
	},
	.ops = &hsclk_divsel_ops,
	.c = {
		.parent = &dp_vco_clk.c,
		.dbg_name = "hsclk_divsel_clk_src",
		.ops = &clk_ops_hsclk_divsel_clk_src_c,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(hsclk_divsel_clk_src.c),
	},
};

static struct div_clk dp_link_2x_clk_divsel_five = {
	.data = {
		.div = 5,
@@ -134,7 +111,7 @@ static struct div_clk dp_link_2x_clk_divsel_five = {
	},
	.ops = &link2xclk_divsel_ops,
	.c = {
		.parent = &hsclk_divsel_clk_src.c,
		.parent = &dp_vco_clk.c,
		.dbg_name = "dp_link_2x_clk_divsel_five",
		.ops = &clk_ops_link_2x_clk_div_c,
		.flags = CLKFLAG_NO_RATE_CACHE,
@@ -142,61 +119,60 @@ static struct div_clk dp_link_2x_clk_divsel_five = {
	},
};

static struct div_clk dp_link_2x_clk_divsel_ten = {
static struct div_clk vco_divsel_four_clk_src = {
	.data = {
		.div = 10,
		.min_div = 10,
		.max_div = 10,
		.div = 4,
		.min_div = 4,
		.max_div = 4,
	},
	.ops = &link2xclk_divsel_ops,
	.ops = &vco_divided_clk_ops,
	.c = {
		.parent = &hsclk_divsel_clk_src.c,
		.dbg_name = "dp_link_2x_clk_divsel_ten",
		.ops = &clk_ops_link_2x_clk_div_c,
		.parent = &dp_vco_clk.c,
		.dbg_name = "vco_divsel_four_clk_src",
		.ops = &clk_ops_vco_divided_clk_src_c,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dp_link_2x_clk_divsel_ten.c),
		CLK_INIT(vco_divsel_four_clk_src.c),
	},
};

static struct mux_clk dp_link_2x_clk_mux = {
	.num_parents = 2,
	.parents = (struct clk_src[]) {
		{&dp_link_2x_clk_divsel_five.c, 0},
		{&dp_link_2x_clk_divsel_ten.c, 1},
static struct div_clk vco_divsel_two_clk_src = {
	.data = {
		.div = 2,
		.min_div = 2,
		.max_div = 2,
	},
	.ops = &mdss_mux_ops,
	.ops = &vco_divided_clk_ops,
	.c = {
		.parent = &dp_link_2x_clk_divsel_five.c,
		.dbg_name = "dp_link_2x_clk_mux",
		.ops = &clk_ops_gen_mux,
		.parent = &dp_vco_clk.c,
		.dbg_name = "vco_divsel_two_clk_src",
		.ops = &clk_ops_vco_divided_clk_src_c,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(dp_link_2x_clk_mux.c),
	}
		CLK_INIT(vco_divsel_two_clk_src.c),
	},
};

static struct div_clk vco_divided_clk_src = {
	.data = {
		.div = 4,
		.min_div = 4,
		.max_div = 4,
static struct mux_clk vco_divided_clk_src_mux = {
	.num_parents = 2,
	.parents = (struct clk_src[]) {
		{&vco_divsel_two_clk_src.c, 0},
		{&vco_divsel_four_clk_src.c, 1},
	},
	.ops = &vco_divided_clk_ops,
	.ops = &mdss_mux_ops,
	.c = {
		.parent = &hsclk_divsel_clk_src.c,
		.dbg_name = "vco_divided_clk",
		.ops = &clk_ops_vco_divided_clk_src_c,
		.parent = &vco_divsel_two_clk_src.c,
		.dbg_name = "vco_divided_clk_src_mux",
		.ops = &clk_ops_gen_mux_dp,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(vco_divided_clk_src.c),
	},
		CLK_INIT(vco_divided_clk_src_mux.c),
	}
};

static struct clk_lookup dp_pllcc_8998[] = {
	CLK_LIST(dp_vco_clk),
	CLK_LIST(hsclk_divsel_clk_src),
	CLK_LIST(dp_link_2x_clk_divsel_five),
	CLK_LIST(dp_link_2x_clk_divsel_ten),
	CLK_LIST(dp_link_2x_clk_mux),
	CLK_LIST(vco_divided_clk_src),
	CLK_LIST(vco_divsel_four_clk_src),
	CLK_LIST(vco_divsel_two_clk_src),
	CLK_LIST(vco_divided_clk_src_mux),
};

int dp_pll_clock_register_8998(struct platform_device *pdev,
@@ -211,14 +187,10 @@ int dp_pll_clock_register_8998(struct platform_device *pdev,

	/* Set client data for vco, mux and div clocks */
	dp_vco_clk.priv = pll_res;
	hsclk_divsel_clk_src.priv = pll_res;
	dp_link_2x_clk_mux.priv = pll_res;
	vco_divided_clk_src.priv = pll_res;
	vco_divided_clk_src_mux.priv = pll_res;
	vco_divsel_two_clk_src.priv = pll_res;
	vco_divsel_four_clk_src.priv = pll_res;
	dp_link_2x_clk_divsel_five.priv = pll_res;
	dp_link_2x_clk_divsel_ten.priv = pll_res;

	clk_ops_hsclk_divsel_clk_src_c = clk_ops_div;
	clk_ops_hsclk_divsel_clk_src_c.prepare = mdss_pll_div_prepare;

	clk_ops_link_2x_clk_div_c = clk_ops_div;
	clk_ops_link_2x_clk_div_c.prepare = mdss_pll_div_prepare;
@@ -233,6 +205,9 @@ int dp_pll_clock_register_8998(struct platform_device *pdev,
	clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare;
	clk_ops_vco_divided_clk_src_c.handoff = vco_divided_clk_handoff;

	clk_ops_gen_mux_dp = clk_ops_gen_mux;
	clk_ops_gen_mux_dp.get_rate = parent_get_rate;

	/* We can select different clock ops for future versions */
	dp_vco_clk.c.ops = &dp_8998_vco_clk_ops;

+11 −1
Original line number Diff line number Diff line
@@ -59,12 +59,19 @@
#define TXn_SLEW_CNTL				0x0030
#define TXn_INTERFACE_SELECT			0x0034

#define TXn_RES_CODE_LANE_TX			0x003C
#define TXn_RES_CODE_LANE_RX			0x0040
#define TXn_RES_CODE_LANE_OFFSET_TX		0x0044
#define TXn_RES_CODE_LANE_OFFSET_RX		0x0048

#define TXn_DEBUG_BUS_SEL			0x0058
#define TXn_TRANSCEIVER_BIAS_EN			0x005C
#define TXn_HIGHZ_DRVR_EN			0x0060
#define TXn_TX_POL_INV				0x0064
#define TXn_PARRATE_REC_DETECT_IDLE_EN		0x0068

#define TXn_LANE_MODE_1				0x008C

#define TXn_TRAN_DRVR_EMP_EN			0x00C0
#define TXn_TX_INTERFACE_MODE			0x00C4

@@ -149,9 +156,12 @@
#define DP_PLL_POLL_TIMEOUT_US			10000

#define DP_VCO_RATE_8100MHz			8100000000ULL
#define DP_VCO_RATE_9720MHz			9720000000ULL
#define DP_VCO_RATE_10800MHz			10800000000ULL

#define DP_VCO_HSCLK_RATE_1620MHz		1620000000ULL
#define DP_VCO_HSCLK_RATE_2700MHz		2700000000ULL
#define DP_VCO_HSCLK_RATE_5400MHz		5400000000ULL

int dp_vco_set_rate(struct clk *c, unsigned long rate);
unsigned long dp_vco_get_rate(struct clk *c);
long dp_vco_round_rate(struct clk *c, unsigned long rate);