Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: qcom-qmp: add support for sm8250-usb3-dp phy

Add support for QMP V4 Combo USB3+DP PHY (for SM8250 platform).

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20210331151614.3810197-6-dmitry.baryshkov@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Dmitry Baryshkov and committed by
Vinod Koul
aff188fe 5c393917

+412 -22
+374 -20
drivers/phy/qualcomm/phy-qcom-qmp.c
··· 1840 1840 QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), 1841 1841 }; 1842 1842 1843 + static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { 1844 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), 1845 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), 1846 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), 1847 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), 1848 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), 1849 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), 1850 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), 1851 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), 1852 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), 1853 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), 1854 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), 1855 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), 1856 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), 1857 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), 1858 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), 1859 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), 1860 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), 1861 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), 1862 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), 1863 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), 1864 + }; 1865 + 1866 + static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { 1867 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), 1868 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), 1869 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), 1870 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), 1871 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), 1872 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), 1873 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), 1874 + }; 1875 + 1876 + static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { 1877 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), 1878 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), 1879 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), 1880 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), 1881 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), 1882 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), 1883 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), 1884 + }; 1885 + 1886 + static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { 1887 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), 1888 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), 1889 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), 1890 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), 1891 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), 1892 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), 1893 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), 1894 + }; 1895 + 1896 + static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { 1897 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), 1898 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), 1899 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), 1900 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), 1901 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), 1902 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), 1903 + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), 1904 + }; 1905 + 1906 + static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { 1907 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), 1908 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), 1909 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), 1910 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), 1911 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), 1912 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), 1913 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), 1914 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), 1915 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), 1916 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), 1917 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), 1918 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), 1919 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), 1920 + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), 1921 + }; 1922 + 1843 1923 static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { 1844 1924 QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), 1845 1925 QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ··· 2515 2435 static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); 2516 2436 static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); 2517 2437 static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); 2438 + 2439 + static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); 2440 + static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); 2441 + static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); 2442 + static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); 2518 2443 2519 2444 static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) 2520 2445 { ··· 3226 3141 .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, 3227 3142 }; 3228 3143 3144 + static const struct qmp_phy_cfg sm8250_dpphy_cfg = { 3145 + .type = PHY_TYPE_DP, 3146 + .nlanes = 1, 3147 + 3148 + .serdes_tbl = qmp_v4_dp_serdes_tbl, 3149 + .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), 3150 + .tx_tbl = qmp_v4_dp_tx_tbl, 3151 + .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), 3152 + 3153 + .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, 3154 + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), 3155 + .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, 3156 + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), 3157 + .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, 3158 + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), 3159 + .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, 3160 + .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), 3161 + 3162 + .clk_list = qmp_v4_phy_clk_l, 3163 + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), 3164 + .reset_list = msm8996_usb3phy_reset_l, 3165 + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), 3166 + .vreg_list = qmp_phy_vreg_l, 3167 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 3168 + .regs = qmp_v4_usb3phy_regs_layout, 3169 + 3170 + .has_phy_dp_com_ctrl = true, 3171 + .is_dual_lane_phy = true, 3172 + 3173 + .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, 3174 + .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, 3175 + .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, 3176 + .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, 3177 + }; 3178 + 3179 + static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { 3180 + .usb_cfg = &sm8250_usb3phy_cfg, 3181 + .dp_cfg = &sm8250_dpphy_cfg, 3182 + }; 3183 + 3229 3184 static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { 3230 3185 .type = PHY_TYPE_USB3, 3231 3186 .nlanes = 1, ··· 3546 3421 { 0x1f, 0xff, 0xff, 0xff } 3547 3422 }; 3548 3423 3549 - static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) 3424 + static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, 3425 + unsigned int drv_lvl_reg, unsigned int emp_post_reg) 3550 3426 { 3551 3427 const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; 3552 3428 unsigned int v_level = 0, p_level = 0; 3553 - u32 bias_en, drvr_en; 3554 3429 u8 voltage_swing_cfg, pre_emphasis_cfg; 3555 3430 int i; 3556 3431 3557 3432 for (i = 0; i < dp_opts->lanes; i++) { 3558 3433 v_level = max(v_level, dp_opts->voltage[i]); 3559 3434 p_level = max(p_level, dp_opts->pre[i]); 3560 - } 3561 - 3562 - if (dp_opts->lanes == 1) { 3563 - bias_en = 0x3e; 3564 - drvr_en = 0x13; 3565 - } else { 3566 - bias_en = 0x3f; 3567 - drvr_en = 0x10; 3568 3435 } 3569 3436 3570 3437 if (dp_opts->link_rate <= 2700) { ··· 3569 3452 3570 3453 /* TODO: Move check to config check */ 3571 3454 if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) 3572 - return; 3455 + return -EINVAL; 3573 3456 3574 3457 /* Enable MUX to use Cursor values from these registers */ 3575 3458 voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; 3576 3459 pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; 3577 3460 3578 - writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL); 3579 - writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); 3580 - writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL); 3581 - writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); 3461 + writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); 3462 + writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); 3463 + writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); 3464 + writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); 3465 + 3466 + return 0; 3467 + } 3468 + 3469 + static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) 3470 + { 3471 + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; 3472 + u32 bias_en, drvr_en; 3473 + 3474 + if (qcom_qmp_phy_configure_dp_swing(qphy, 3475 + QSERDES_V3_TX_TX_DRV_LVL, 3476 + QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) 3477 + return; 3478 + 3479 + if (dp_opts->lanes == 1) { 3480 + bias_en = 0x3e; 3481 + drvr_en = 0x13; 3482 + } else { 3483 + bias_en = 0x3f; 3484 + drvr_en = 0x10; 3485 + } 3582 3486 3583 3487 writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); 3584 3488 writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ··· 3607 3469 writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); 3608 3470 } 3609 3471 3610 - static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) 3472 + static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) 3611 3473 { 3612 - const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; 3613 - const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; 3614 - u32 val, phy_vco_div, status; 3615 - unsigned long pixel_freq; 3474 + u32 val; 3475 + bool reverse = false; 3616 3476 3617 3477 val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 3618 3478 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ··· 3633 3497 writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); 3634 3498 3635 3499 writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); 3500 + 3501 + return reverse; 3502 + } 3503 + 3504 + static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) 3505 + { 3506 + const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; 3507 + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; 3508 + u32 phy_vco_div, status; 3509 + unsigned long pixel_freq; 3510 + 3511 + qcom_qmp_phy_configure_dp_mode(qphy); 3512 + 3636 3513 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); 3637 3514 writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); 3638 3515 ··· 3717 3568 static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) 3718 3569 { 3719 3570 static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; 3571 + u8 val; 3572 + 3573 + qphy->dp_aux_cfg++; 3574 + qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); 3575 + val = cfg1_settings[qphy->dp_aux_cfg]; 3576 + 3577 + writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); 3578 + 3579 + return 0; 3580 + } 3581 + 3582 + static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) 3583 + { 3584 + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 3585 + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, 3586 + qphy->pcs + QSERDES_DP_PHY_PD_CTL); 3587 + 3588 + /* Turn on BIAS current for PHY/PLL */ 3589 + writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); 3590 + 3591 + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); 3592 + writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); 3593 + writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); 3594 + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); 3595 + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); 3596 + writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); 3597 + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); 3598 + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); 3599 + writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); 3600 + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); 3601 + qphy->dp_aux_cfg = 0; 3602 + 3603 + writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | 3604 + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | 3605 + PHY_AUX_REQ_ERR_MASK, 3606 + qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); 3607 + } 3608 + 3609 + static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) 3610 + { 3611 + /* Program default values before writing proper values */ 3612 + writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); 3613 + writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); 3614 + 3615 + writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); 3616 + writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); 3617 + 3618 + qcom_qmp_phy_configure_dp_swing(qphy, 3619 + QSERDES_V4_TX_TX_DRV_LVL, 3620 + QSERDES_V4_TX_TX_EMP_POST1_LVL); 3621 + } 3622 + 3623 + static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) 3624 + { 3625 + const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; 3626 + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; 3627 + u32 phy_vco_div, status; 3628 + unsigned long pixel_freq; 3629 + u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 3630 + bool reverse; 3631 + 3632 + writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); 3633 + 3634 + reverse = qcom_qmp_phy_configure_dp_mode(qphy); 3635 + 3636 + writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); 3637 + writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); 3638 + 3639 + writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); 3640 + writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); 3641 + 3642 + switch (dp_opts->link_rate) { 3643 + case 1620: 3644 + phy_vco_div = 0x1; 3645 + pixel_freq = 1620000000UL / 2; 3646 + break; 3647 + case 2700: 3648 + phy_vco_div = 0x1; 3649 + pixel_freq = 2700000000UL / 2; 3650 + break; 3651 + case 5400: 3652 + phy_vco_div = 0x2; 3653 + pixel_freq = 5400000000UL / 4; 3654 + break; 3655 + case 8100: 3656 + phy_vco_div = 0x0; 3657 + pixel_freq = 8100000000UL / 6; 3658 + break; 3659 + default: 3660 + /* Other link rates aren't supported */ 3661 + return -EINVAL; 3662 + } 3663 + writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); 3664 + 3665 + clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); 3666 + clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); 3667 + 3668 + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); 3669 + writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); 3670 + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); 3671 + writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); 3672 + 3673 + writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); 3674 + 3675 + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, 3676 + status, 3677 + ((status & BIT(0)) > 0), 3678 + 500, 3679 + 10000)) 3680 + return -ETIMEDOUT; 3681 + 3682 + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, 3683 + status, 3684 + ((status & BIT(0)) > 0), 3685 + 500, 3686 + 10000)) 3687 + return -ETIMEDOUT; 3688 + 3689 + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, 3690 + status, 3691 + ((status & BIT(1)) > 0), 3692 + 500, 3693 + 10000)) 3694 + return -ETIMEDOUT; 3695 + 3696 + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); 3697 + 3698 + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, 3699 + status, 3700 + ((status & BIT(0)) > 0), 3701 + 500, 3702 + 10000)) 3703 + return -ETIMEDOUT; 3704 + 3705 + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, 3706 + status, 3707 + ((status & BIT(1)) > 0), 3708 + 500, 3709 + 10000)) 3710 + return -ETIMEDOUT; 3711 + 3712 + /* 3713 + * At least for 7nm DP PHY this has to be done after enabling link 3714 + * clock. 3715 + */ 3716 + 3717 + if (dp_opts->lanes == 1) { 3718 + bias0_en = reverse ? 0x3e : 0x15; 3719 + bias1_en = reverse ? 0x15 : 0x3e; 3720 + drvr0_en = reverse ? 0x13 : 0x10; 3721 + drvr1_en = reverse ? 0x10 : 0x13; 3722 + } else if (dp_opts->lanes == 2) { 3723 + bias0_en = reverse ? 0x3f : 0x15; 3724 + bias1_en = reverse ? 0x15 : 0x3f; 3725 + drvr0_en = 0x10; 3726 + drvr1_en = 0x10; 3727 + } else { 3728 + bias0_en = 0x3f; 3729 + bias1_en = 0x3f; 3730 + drvr0_en = 0x10; 3731 + drvr1_en = 0x10; 3732 + } 3733 + 3734 + writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); 3735 + writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); 3736 + writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); 3737 + writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); 3738 + 3739 + writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); 3740 + udelay(2000); 3741 + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); 3742 + 3743 + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, 3744 + status, 3745 + ((status & BIT(1)) > 0), 3746 + 500, 3747 + 10000)) 3748 + return -ETIMEDOUT; 3749 + 3750 + writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); 3751 + writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); 3752 + 3753 + writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); 3754 + writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); 3755 + 3756 + writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); 3757 + writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); 3758 + 3759 + return 0; 3760 + } 3761 + 3762 + /* 3763 + * We need to calibrate the aux setting here as many times 3764 + * as the caller tries 3765 + */ 3766 + static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) 3767 + { 3768 + static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; 3720 3769 u8 val; 3721 3770 3722 3771 qphy->dp_aux_cfg++; ··· 4973 4626 .compatible = "qcom,sm8250-qmp-usb3-phy", 4974 4627 .data = &sm8250_usb3phy_cfg, 4975 4628 }, { 4629 + .compatible = "qcom,sm8250-qmp-usb3-dp-phy", 4630 + /* It's a combo phy */ 4631 + }, { 4976 4632 .compatible = "qcom,sm8250-qmp-usb3-uni-phy", 4977 4633 .data = &sm8250_usb3_uniphy_cfg, 4978 4634 }, { ··· 5008 4658 { 5009 4659 .compatible = "qcom,sc7180-qmp-usb3-dp-phy", 5010 4660 .data = &sc7180_usb3dpphy_cfg, 4661 + }, 4662 + { 4663 + .compatible = "qcom,sm8250-qmp-usb3-dp-phy", 4664 + .data = &sm8250_usb3dpphy_cfg, 5011 4665 }, 5012 4666 { } 5013 4667 };
+38 -2
drivers/phy/qualcomm/phy-qcom-qmp.h
··· 397 397 #define QSERDES_V3_DP_PHY_STATUS 0x0c0 398 398 399 399 /* Only for QMP V4 PHY - QSERDES COM registers */ 400 + #define QSERDES_V4_COM_BG_TIMER 0x00c 400 401 #define QSERDES_V4_COM_SSC_EN_CENTER 0x010 401 402 #define QSERDES_V4_COM_SSC_PER1 0x01c 402 403 #define QSERDES_V4_COM_SSC_PER2 0x020 ··· 405 404 #define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028 406 405 #define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030 407 406 #define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034 407 + #define QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN 0x044 408 408 #define QSERDES_V4_COM_CLK_ENABLE1 0x048 409 + #define QSERDES_V4_COM_SYS_CLK_CTRL 0x04c 409 410 #define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050 410 411 #define QSERDES_V4_COM_PLL_IVCO 0x058 411 412 #define QSERDES_V4_COM_CMN_IPTRIM 0x060 ··· 418 415 #define QSERDES_V4_COM_PLL_CCTRL_MODE0 0x084 419 416 #define QSERDES_V4_COM_PLL_CCTRL_MODE1 0x088 420 417 #define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094 418 + #define QSERDES_V4_COM_RESETSM_CNTRL 0x09c 421 419 #define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4 422 420 #define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac 423 421 #define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0 ··· 432 428 #define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8 433 429 #define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc 434 430 #define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0 431 + #define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0 0x0ec 432 + #define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0 0x0f0 433 + #define QSERDES_V4_COM_VCO_TUNE_CTRL 0x108 435 434 #define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c 436 435 #define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110 437 436 #define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114 438 437 #define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118 439 438 #define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c 440 439 #define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124 440 + #define QSERDES_V4_COM_CMN_STATUS 0x140 441 441 #define QSERDES_V4_COM_CLK_SELECT 0x154 442 442 #define QSERDES_V4_COM_HSCLK_SEL 0x158 443 443 #define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c 444 + #define QSERDES_V4_COM_CORECLK_DIV_MODE0 0x168 444 445 #define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c 446 + #define QSERDES_V4_COM_CORE_CLK_EN 0x174 447 + #define QSERDES_V4_COM_C_READY_STATUS 0x178 448 + #define QSERDES_V4_COM_CMN_CONFIG 0x17c 445 449 #define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184 446 450 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac 447 451 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0 ··· 458 446 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8 459 447 460 448 /* Only for QMP V4 PHY - TX registers */ 449 + #define QSERDES_V4_TX_CLKBUF_ENABLE 0x08 450 + #define QSERDES_V4_TX_TX_EMP_POST1_LVL 0x0c 451 + #define QSERDES_V4_TX_TX_DRV_LVL 0x14 452 + #define QSERDES_V4_TX_RESET_TSYNC_EN 0x1c 453 + #define QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN 0x20 454 + #define QSERDES_V4_TX_TX_BAND 0x24 455 + #define QSERDES_V4_TX_INTERFACE_SELECT 0x2c 461 456 #define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34 462 457 #define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38 463 458 #define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX 0x3c 464 459 #define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX 0x40 460 + #define QSERDES_V4_TX_TRANSCEIVER_BIAS_EN 0x54 461 + #define QSERDES_V4_TX_HIGHZ_DRVR_EN 0x58 462 + #define QSERDES_V4_TX_TX_POL_INV 0x5c 463 + #define QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN 0x60 465 464 #define QSERDES_V4_TX_LANE_MODE_1 0x84 466 465 #define QSERDES_V4_TX_LANE_MODE_2 0x88 467 466 #define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c 467 + #define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8 468 + #define QSERDES_V4_TX_TX_INTERFACE_MODE 0xbc 468 469 #define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8 469 470 #define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC 470 471 #define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0 471 472 #define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4 472 - #define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8 473 - #define QSERDES_V4_TX_PI_QEC_CTRL 0x104 473 + #define QSERDES_V4_TX_VMODE_CTRL1 0xe8 474 + #define QSERDES_V4_TX_PI_QEC_CTRL 0x104 474 475 475 476 /* Only for QMP V4 PHY - RX registers */ 476 477 #define QSERDES_V4_RX_UCDR_FO_GAIN 0x008 ··· 539 514 #define QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET 0x1b8 540 515 #define QSERDES_V4_RX_DCC_CTRL1 0x1bc 541 516 #define QSERDES_V4_RX_VTH_CODE 0x1c4 517 + 518 + /* Only for QMP V4 PHY - DP PHY registers */ 519 + #define QSERDES_V4_DP_PHY_CFG_1 0x014 520 + #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK 0x054 521 + #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_CLEAR 0x058 522 + #define QSERDES_V4_DP_PHY_VCO_DIV 0x070 523 + #define QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL 0x078 524 + #define QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL 0x09c 525 + #define QSERDES_V4_DP_PHY_SPARE0 0x0c8 526 + #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8 527 + #define QSERDES_V4_DP_PHY_STATUS 0x0dc 542 528 543 529 /* Only for QMP V4 PHY - UFS PCS registers */ 544 530 #define QPHY_V4_PCS_UFS_PHY_START 0x000