in qualcomm/phy-qcom-qmp.c [4813:4950]
static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy)
{
const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
u32 phy_vco_div, status;
unsigned long pixel_freq;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
bool reverse;
writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1);
reverse = qcom_qmp_phy_configure_dp_mode(qphy);
writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL);
switch (dp_opts->link_rate) {
case 1620:
phy_vco_div = 0x1;
pixel_freq = 1620000000UL / 2;
break;
case 2700:
phy_vco_div = 0x1;
pixel_freq = 2700000000UL / 2;
break;
case 5400:
phy_vco_div = 0x2;
pixel_freq = 5400000000UL / 4;
break;
case 8100:
phy_vco_div = 0x0;
pixel_freq = 8100000000UL / 6;
break;
default:
/* Other link rates aren't supported */
return -EINVAL;
}
writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV);
clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG);
writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG);
writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL);
if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS,
status,
((status & BIT(0)) > 0),
500,
10000))
return -ETIMEDOUT;
if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
status,
((status & BIT(0)) > 0),
500,
10000))
return -ETIMEDOUT;
if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
status,
((status & BIT(1)) > 0),
500,
10000))
return -ETIMEDOUT;
writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
status,
((status & BIT(0)) > 0),
500,
10000))
return -ETIMEDOUT;
if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
status,
((status & BIT(1)) > 0),
500,
10000))
return -ETIMEDOUT;
/*
* At least for 7nm DP PHY this has to be done after enabling link
* clock.
*/
if (dp_opts->lanes == 1) {
bias0_en = reverse ? 0x3e : 0x15;
bias1_en = reverse ? 0x15 : 0x3e;
drvr0_en = reverse ? 0x13 : 0x10;
drvr1_en = reverse ? 0x10 : 0x13;
} else if (dp_opts->lanes == 2) {
bias0_en = reverse ? 0x3f : 0x15;
bias1_en = reverse ? 0x15 : 0x3f;
drvr0_en = 0x10;
drvr1_en = 0x10;
} else {
bias0_en = 0x3f;
bias1_en = 0x3f;
drvr0_en = 0x10;
drvr1_en = 0x10;
}
writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN);
writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN);
writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG);
udelay(2000);
writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
status,
((status & BIT(1)) > 0),
500,
10000))
return -ETIMEDOUT;
writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV);
writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV);
writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL);
writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL);
writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL);
writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL);
return 0;
}