diff options
Diffstat (limited to 'drivers/phy/qualcomm')
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-edp.c | 221 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 819 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 251 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 360 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5.h | 13 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h | 333 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 270 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 468 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.h | 1 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qusb2.c | 27 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 273 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-usb-hsic.c | 6 |
12 files changed, 1892 insertions, 1150 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index 7e3570789845..fc8ca0f3018d 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -70,8 +70,19 @@ #define TXn_TRAN_DRVR_EMP_EN 0x0078 +struct qcom_edp_cfg { + bool is_dp; + + /* DP PHY swing and pre_emphasis tables */ + const u8 (*swing_hbr_rbr)[4][4]; + const u8 (*swing_hbr3_hbr2)[4][4]; + const u8 (*pre_emphasis_hbr_rbr)[4][4]; + const u8 (*pre_emphasis_hbr3_hbr2)[4][4]; +}; + struct qcom_edp { struct device *dev; + const struct qcom_edp_cfg *cfg; struct phy *phy; @@ -89,10 +100,84 @@ struct qcom_edp { struct regulator_bulk_data supplies[2]; }; +static const u8 dp_swing_hbr_rbr[4][4] = { + { 0x08, 0x0f, 0x16, 0x1f }, + { 0x11, 0x1e, 0x1f, 0xff }, + { 0x16, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff } +}; + +static const u8 dp_pre_emp_hbr_rbr[4][4] = { + { 0x00, 0x0d, 0x14, 0x1a }, + { 0x00, 0x0e, 0x15, 0xff }, + { 0x00, 0x0e, 0xff, 0xff }, + { 0x03, 0xff, 0xff, 0xff } +}; + +static const u8 dp_swing_hbr2_hbr3[4][4] = { + { 0x02, 0x12, 0x16, 0x1a }, + { 0x09, 0x19, 0x1f, 0xff }, + { 0x10, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff } +}; + +static const u8 dp_pre_emp_hbr2_hbr3[4][4] = { + { 0x00, 0x0c, 0x15, 0x1b }, + { 0x02, 0x0e, 0x16, 0xff }, + { 0x02, 0x11, 0xff, 0xff }, + { 0x04, 0xff, 0xff, 0xff } +}; + +static const struct qcom_edp_cfg dp_phy_cfg = { + .is_dp = true, + .swing_hbr_rbr = &dp_swing_hbr_rbr, + .swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3, + .pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr, + .pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3, +}; + +static const u8 edp_swing_hbr_rbr[4][4] = { + { 0x07, 0x0f, 0x16, 0x1f }, + { 0x0d, 0x16, 0x1e, 0xff }, + { 0x11, 0x1b, 0xff, 0xff }, + { 0x16, 0xff, 0xff, 0xff } +}; + +static const u8 edp_pre_emp_hbr_rbr[4][4] = { + { 0x05, 0x12, 0x17, 0x1d }, + { 0x05, 0x11, 0x18, 0xff }, + { 0x06, 0x11, 0xff, 0xff }, + { 0x00, 0xff, 0xff, 0xff } +}; + +static const u8 edp_swing_hbr2_hbr3[4][4] = { + { 0x0b, 0x11, 0x17, 0x1c }, + { 0x10, 0x19, 0x1f, 0xff }, + { 0x19, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff } +}; + +static const u8 edp_pre_emp_hbr2_hbr3[4][4] = { + { 0x08, 0x11, 0x17, 0x1b }, + { 0x00, 0x0c, 0x13, 0xff }, + { 0x05, 0x10, 0xff, 0xff }, + { 0x00, 0xff, 0xff, 0xff } +}; + +static const struct qcom_edp_cfg edp_phy_cfg = { + .is_dp = false, + .swing_hbr_rbr = &edp_swing_hbr_rbr, + .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3, + .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr, + .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3, +}; + static int qcom_edp_phy_init(struct phy *phy) { struct qcom_edp *edp = phy_get_drvdata(phy); + const struct qcom_edp_cfg *cfg = edp->cfg; int ret; + u8 cfg8; ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies); if (ret) @@ -117,6 +202,13 @@ static int qcom_edp_phy_init(struct phy *phy) DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, edp->edp + DP_PHY_PD_CTL); + if (cfg && cfg->is_dp) + cfg8 = 0xb7; + else + cfg8 = 0x37; + + writel(0xfc, edp->edp + DP_PHY_MODE); + writel(0x00, edp->edp + DP_PHY_AUX_CFG0); writel(0x13, edp->edp + DP_PHY_AUX_CFG1); writel(0x24, edp->edp + DP_PHY_AUX_CFG2); @@ -125,7 +217,7 @@ static int qcom_edp_phy_init(struct phy *phy) writel(0x26, edp->edp + DP_PHY_AUX_CFG5); writel(0x0a, edp->edp + DP_PHY_AUX_CFG6); writel(0x03, edp->edp + DP_PHY_AUX_CFG7); - writel(0x37, edp->edp + DP_PHY_AUX_CFG8); + writel(cfg8, edp->edp + DP_PHY_AUX_CFG8); writel(0x03, edp->edp + DP_PHY_AUX_CFG9); writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | @@ -142,14 +234,60 @@ out_disable_supplies: return ret; } +static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts) +{ + const struct qcom_edp_cfg *cfg = edp->cfg; + unsigned int v_level = 0; + unsigned int p_level = 0; + u8 ldo_config; + u8 swing; + u8 emph; + int i; + + if (!cfg) + return 0; + + for (i = 0; i < dp_opts->lanes; i++) { + v_level = max(v_level, dp_opts->voltage[i]); + p_level = max(p_level, dp_opts->pre[i]); + } + + if (dp_opts->link_rate <= 2700) { + swing = (*cfg->swing_hbr_rbr)[v_level][p_level]; + emph = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level]; + } else { + swing = (*cfg->swing_hbr3_hbr2)[v_level][p_level]; + emph = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level]; + } + + if (swing == 0xff || emph == 0xff) + return -EINVAL; + + ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0; + + writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG); + writel(swing, edp->tx0 + TXn_TX_DRV_LVL); + writel(emph, edp->tx0 + TXn_TX_EMP_POST1_LVL); + + writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG); + writel(swing, edp->tx1 + TXn_TX_DRV_LVL); + writel(emph, edp->tx1 + TXn_TX_EMP_POST1_LVL); + + return 0; +} + static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts) { const struct phy_configure_opts_dp *dp_opts = &opts->dp; struct qcom_edp *edp = phy_get_drvdata(phy); + int ret = 0; memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts)); - return 0; + if (dp_opts->set_voltages) + ret = qcom_edp_set_voltages(edp, dp_opts); + + return ret; } static int qcom_edp_configure_ssc(const struct qcom_edp *edp) @@ -272,31 +410,30 @@ static int qcom_edp_configure_pll(const struct qcom_edp *edp) return 0; } -static int qcom_edp_set_vco_div(const struct qcom_edp *edp) +static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq) { const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; - unsigned long pixel_freq; u32 vco_div; switch (dp_opts->link_rate) { case 1620: vco_div = 0x1; - pixel_freq = 1620000000UL / 2; + *pixel_freq = 1620000000UL / 2; break; case 2700: vco_div = 0x1; - pixel_freq = 2700000000UL / 2; + *pixel_freq = 2700000000UL / 2; break; case 5400: vco_div = 0x2; - pixel_freq = 5400000000UL / 4; + *pixel_freq = 5400000000UL / 4; break; case 8100: vco_div = 0x0; - pixel_freq = 8100000000UL / 6; + *pixel_freq = 8100000000UL / 6; break; default: @@ -306,18 +443,20 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp) writel(vco_div, edp->edp + DP_PHY_VCO_DIV); - clk_set_rate(edp->dp_link_hw.clk, dp_opts->link_rate * 100000); - clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq); - return 0; } static int qcom_edp_phy_power_on(struct phy *phy) { const struct qcom_edp *edp = phy_get_drvdata(phy); + const struct qcom_edp_cfg *cfg = edp->cfg; + u32 bias0_en, drvr0_en, bias1_en, drvr1_en; + unsigned long pixel_freq; + u8 ldo_config; int timeout; int ret; u32 val; + u8 cfg1; writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | @@ -330,8 +469,11 @@ static int qcom_edp_phy_power_on(struct phy *phy) if (timeout) return timeout; - writel(0x01, edp->tx0 + TXn_LDO_CONFIG); - writel(0x01, edp->tx1 + TXn_LDO_CONFIG); + + ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0; + + writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG); + writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG); writel(0x00, edp->tx0 + TXn_LANE_MODE_1); writel(0x00, edp->tx1 + TXn_LANE_MODE_1); @@ -363,7 +505,7 @@ static int qcom_edp_phy_power_on(struct phy *phy) writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN); writel(0x04, edp->tx1 + TXn_TX_BAND); - ret = qcom_edp_set_vco_div(edp); + ret = qcom_edp_set_vco_div(edp, &pixel_freq); if (ret) return ret; @@ -398,19 +540,46 @@ static int qcom_edp_phy_power_on(struct phy *phy) writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL); writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL); - writel(0x4, edp->tx0 + TXn_HIGHZ_DRVR_EN); - writel(0x3, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN); - writel(0x4, edp->tx1 + TXn_HIGHZ_DRVR_EN); - writel(0x0, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN); - writel(0x3, edp->edp + DP_PHY_CFG_1); + if (edp->dp_opts.lanes == 1) { + bias0_en = 0x01; + bias1_en = 0x00; + drvr0_en = 0x06; + drvr1_en = 0x07; + cfg1 = 0x1; + } else if (edp->dp_opts.lanes == 2) { + bias0_en = 0x03; + bias1_en = 0x00; + drvr0_en = 0x04; + drvr1_en = 0x07; + cfg1 = 0x3; + } else { + bias0_en = 0x03; + bias1_en = 0x03; + drvr0_en = 0x04; + drvr1_en = 0x04; + cfg1 = 0xf; + } + + writel(drvr0_en, edp->tx0 + TXn_HIGHZ_DRVR_EN); + writel(bias0_en, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN); + writel(drvr1_en, edp->tx1 + TXn_HIGHZ_DRVR_EN); + writel(bias1_en, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN); + writel(cfg1, edp->edp + DP_PHY_CFG_1); writel(0x18, edp->edp + DP_PHY_CFG); usleep_range(100, 1000); writel(0x19, edp->edp + DP_PHY_CFG); - return readl_poll_timeout(edp->edp + DP_PHY_STATUS, - val, val & BIT(1), 500, 10000); + ret = readl_poll_timeout(edp->edp + DP_PHY_STATUS, + val, val & BIT(1), 500, 10000); + if (ret) + return ret; + + clk_set_rate(edp->dp_link_hw.clk, edp->dp_opts.link_rate * 100000); + clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq); + + return 0; } static int qcom_edp_phy_power_off(struct phy *phy) @@ -571,21 +740,24 @@ static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np) { struct clk_hw_onecell_data *data; struct clk_init_data init = { }; + char name[64]; int ret; data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL); if (!data) return -ENOMEM; + snprintf(name, sizeof(name), "%s::link_clk", dev_name(edp->dev)); init.ops = &qcom_edp_dp_link_clk_ops; - init.name = "edp_phy_pll_link_clk"; + init.name = name; edp->dp_link_hw.init = &init; ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw); if (ret) return ret; + snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(edp->dev)); init.ops = &qcom_edp_dp_pixel_clk_ops; - init.name = "edp_phy_pll_vco_div_clk"; + init.name = name; edp->dp_pixel_hw.init = &init; ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw); if (ret) @@ -610,6 +782,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev) return -ENOMEM; edp->dev = dev; + edp->cfg = of_device_get_match_data(&pdev->dev); edp->edp = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(edp->edp)) @@ -670,6 +843,8 @@ static int qcom_edp_phy_probe(struct platform_device *pdev) static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,sc7280-edp-phy" }, { .compatible = "qcom,sc8180x-edp-phy" }, + { .compatible = "qcom,sc8280xp-dp-phy", .data = &dp_phy_cfg }, + { .compatible = "qcom,sc8280xp-edp-phy", .data = &edp_phy_cfg }, { } }; MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 4b1828976104..9807c4d935cd 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -28,16 +28,11 @@ #define SW_RESET BIT(0) /* QPHY_POWER_DOWN_CONTROL */ #define SW_PWRDN BIT(0) -#define REFCLK_DRV_DSBL BIT(1) /* QPHY_START_CONTROL bits */ #define SERDES_START BIT(0) #define PCS_START BIT(1) -#define PLL_READY_GATE_EN BIT(3) /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) -#define PHYSTATUS_4_20 BIT(7) -/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ -#define PCS_READY BIT(0) /* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ /* DP PHY soft reset */ @@ -71,11 +66,6 @@ #define POWER_DOWN_DELAY_US_MIN 10 #define POWER_DOWN_DELAY_US_MAX 11 -#define MAX_PROP_NAME 32 - -/* Define the assumed distance between lanes for underspecified device trees. */ -#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 - struct qmp_phy_init_tbl { unsigned int offset; unsigned int val; @@ -115,22 +105,14 @@ struct qmp_phy_init_tbl { /* set of registers with offsets different per-PHY */ enum qphy_reg_layout { - /* Common block control registers */ - QPHY_COM_SW_RESET, - QPHY_COM_POWER_DOWN_CONTROL, - QPHY_COM_START_CONTROL, - QPHY_COM_PCS_READY_STATUS, /* PCS registers */ QPHY_SW_RESET, QPHY_START_CTRL, - QPHY_PCS_READY_STATUS, QPHY_PCS_STATUS, QPHY_PCS_AUTONOMOUS_MODE_CTRL, QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, QPHY_PCS_POWER_DOWN_CONTROL, - /* PCS_MISC registers */ - QPHY_PCS_MISC_TYPEC_CTRL, /* Keep last to ensure regs_layout arrays are properly initialized */ QPHY_LAYOUT_SIZE }; @@ -606,6 +588,160 @@ static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), }; +static const struct qmp_phy_init_tbl qmp_v5_dp_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), +}; + +static const struct qmp_phy_init_tbl qmp_v5_5nm_dp_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_LANE_MODE_3, 0x51), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_TRANSCEIVER_BIAS_EN, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_VMODE_CTRL1, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_PRE_STALL_LDO_BOOST_EN, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_INTERFACE_SELECT, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_CLKBUF_ENABLE, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_RESET_TSYNC_EN, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_TRAN_DRVR_EMP_EN, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_TX_BAND, 0x01), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xfd), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0xfd), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MSB_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MSB_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0xd5), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xd5), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0xd4), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xd4), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x13), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x60), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x76), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE0, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE1, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAXVAL2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SVS_MODE_CLK_SEL, 0x0a), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb43dp_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_LANE_MODE_1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_LANE_MODE_2, 0xc2), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_LANE_MODE_3, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX, 0x0a), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb43dp_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_SIGDET_CNTRL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_SIGDET_ENABLES, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B0, 0xd2), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B1, 0xd2), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B2, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B3, 0x21), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B4, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B5, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B6, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B7, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B0, 0x6b), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B1, 0x63), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B2, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B3, 0x23), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B4, 0x35), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B5, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B6, 0x8e), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_MODE_RATE2_B7, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_IVCM_CAL_CODE_OVERRIDE, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_IVCM_CAL_CTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_SUMMER_CAL_SPD_MODE, 0x1b), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_UCDR_PI_CONTROLS, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE2, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_RX_IVCM_POSTCAL_OFFSET, 0x7c), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_VGA_CAL_CNTRL1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_VGA_CAL_MAN_VAL, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_DFE_DAC_ENABLE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_DFE_3, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_GM_CAL, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE2, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE2, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V5_5NM_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x3f), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb43dp_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xd0), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_CONFIG, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), +}; /* list of regulators */ struct qmp_regulator_data { @@ -618,14 +754,69 @@ static struct qmp_regulator_data qmp_phy_vreg_l[] = { { .name = "vdda-pll", .enable_load = 36000 }, }; +static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { + { 0x00, 0x0c, 0x15, 0x1a }, + { 0x02, 0x0e, 0x16, 0xff }, + { 0x02, 0x11, 0xff, 0xff }, + { 0x04, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { + { 0x02, 0x12, 0x16, 0x1a }, + { 0x09, 0x19, 0x1f, 0xff }, + { 0x10, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { + { 0x00, 0x0c, 0x14, 0x19 }, + { 0x00, 0x0b, 0x12, 0xff }, + { 0x00, 0x0b, 0xff, 0xff }, + { 0x04, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { + { 0x08, 0x0f, 0x16, 0x1f }, + { 0x11, 0x1e, 0x1f, 0xff }, + { 0x19, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v5_pre_emphasis_hbr3_hbr2[4][4] = { + { 0x20, 0x2c, 0x35, 0x3b }, + { 0x22, 0x2e, 0x36, 0xff }, + { 0x22, 0x31, 0xff, 0xff }, + { 0x24, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v5_voltage_swing_hbr3_hbr2[4][4] = { + { 0x22, 0x32, 0x36, 0x3a }, + { 0x29, 0x39, 0x3f, 0xff }, + { 0x30, 0x3f, 0xff, 0xff }, + { 0x3f, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v5_pre_emphasis_hbr_rbr[4][4] = { + { 0x20, 0x2d, 0x34, 0x3a }, + { 0x20, 0x2e, 0x35, 0xff }, + { 0x20, 0x2e, 0xff, 0xff }, + { 0x24, 0xff, 0xff, 0xff } +}; + +static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = { + { 0x28, 0x2f, 0x36, 0x3f }, + { 0x31, 0x3e, 0x3f, 0xff }, + { 0x36, 0x3f, 0xff, 0xff }, + { 0x3f, 0xff, 0xff, 0xff } +}; + struct qmp_phy; /* struct qmp_phy_cfg - per-PHY initialization config */ struct qmp_phy_cfg { /* phy-type - PCIE/UFS/USB */ unsigned int type; - /* number of lanes provided by phy */ - int nlanes; + int lanes; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; @@ -649,6 +840,12 @@ struct qmp_phy_cfg { const struct qmp_phy_init_tbl *serdes_tbl_hbr3; int serdes_tbl_hbr3_num; + /* DP PHY swing and pre_emphasis tables */ + const u8 (*swing_hbr_rbr)[4][4]; + const u8 (*swing_hbr3_hbr2)[4][4]; + const u8 (*pre_emphasis_hbr_rbr)[4][4]; + const u8 (*pre_emphasis_hbr3_hbr2)[4][4]; + /* DP PHY callbacks */ int (*configure_dp_phy)(struct qmp_phy *qphy); void (*configure_dp_tx)(struct qmp_phy *qphy); @@ -679,11 +876,6 @@ struct qmp_phy_cfg { int pwrdn_delay_min; int pwrdn_delay_max; - /* true, if PHY has a separate DP_COM control block */ - bool has_phy_dp_com_ctrl; - /* true, if PHY has secondary tx/rx lanes to be configured */ - bool is_dual_lane_phy; - /* Offset from PCS to PCS_USB region */ unsigned int pcs_usb_offset; @@ -708,9 +900,7 @@ struct qmp_phy_combo_cfg { * @pcs_misc: iomapped memory space for lane's pcs_misc * @pcs_usb: iomapped memory space for lane's pcs_usb * @pipe_clk: pipe clock - * @index: lane index * @qmp: QMP phy to which this lane belongs - * @lane_rst: lane's reset controller * @mode: current PHY mode * @dp_aux_cfg: Display port aux config * @dp_opts: Display port optional config @@ -728,9 +918,7 @@ struct qmp_phy { void __iomem *pcs_misc; void __iomem *pcs_usb; struct clk *pipe_clk; - unsigned int index; struct qcom_qmp *qmp; - struct reset_control *lane_rst; enum phy_mode mode; unsigned int dp_aux_cfg; struct phy_configure_opts_dp dp_opts; @@ -784,6 +972,8 @@ static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); +static int qcom_qmp_v5_phy_configure_dp_phy(struct qmp_phy *qphy); + static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) { u32 reg; @@ -833,7 +1023,7 @@ static const char * const sc7180_usb3phy_reset_l[] = { static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v3_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), @@ -858,14 +1048,11 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, - - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sc7180_dpphy_cfg = { .type = PHY_TYPE_DP, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v3_dp_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), @@ -881,6 +1068,11 @@ static const struct qmp_phy_cfg sc7180_dpphy_cfg = { .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), + .swing_hbr_rbr = &qmp_dp_v3_voltage_swing_hbr_rbr, + .pre_emphasis_hbr_rbr = &qmp_dp_v3_pre_emphasis_hbr_rbr, + .swing_hbr3_hbr2 = &qmp_dp_v3_voltage_swing_hbr3_hbr2, + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v3_pre_emphasis_hbr3_hbr2, + .clk_list = qmp_v3_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), .reset_list = sc7180_usb3phy_reset_l, @@ -889,9 +1081,6 @@ static const struct qmp_phy_cfg sc7180_dpphy_cfg = { .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = qmp_v3_usb3phy_regs_layout, - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, - .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, @@ -903,9 +1092,43 @@ static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { .dp_cfg = &sc7180_dpphy_cfg, }; +static const struct qmp_phy_cfg sdm845_usb3phy_cfg = { + .type = PHY_TYPE_USB3, + .lanes = 2, + + .serdes_tbl = qmp_v3_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), + .tx_tbl = qmp_v3_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), + .rx_tbl = qmp_v3_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), + .pcs_tbl = qmp_v3_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), + .clk_list = qmp_v3_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), + .reset_list = msm8996_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +}; + +static const struct qmp_phy_combo_cfg sdm845_usb3dpphy_cfg = { + .usb_cfg = &sdm845_usb3phy_cfg, + .dp_cfg = &sc7180_dpphy_cfg, +}; + static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = sm8150_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), @@ -934,14 +1157,11 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, - - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { .type = PHY_TYPE_DP, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v4_dp_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), @@ -957,6 +1177,11 @@ static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), + .swing_hbr_rbr = &qmp_dp_v3_voltage_swing_hbr_rbr, + .pre_emphasis_hbr_rbr = &qmp_dp_v3_pre_emphasis_hbr_rbr, + .swing_hbr3_hbr2 = &qmp_dp_v3_voltage_swing_hbr3_hbr2, + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v3_pre_emphasis_hbr3_hbr2, + .clk_list = qmp_v3_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), .reset_list = sc7180_usb3phy_reset_l, @@ -965,9 +1190,6 @@ static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = qmp_v3_usb3phy_regs_layout, - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, - .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, @@ -979,9 +1201,81 @@ static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { .dp_cfg = &sc8180x_dpphy_cfg, }; +static const struct qmp_phy_cfg sc8280xp_usb43dp_usb_cfg = { + .type = PHY_TYPE_USB3, + .lanes = 2, + + .serdes_tbl = sc8280xp_usb43dp_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb43dp_serdes_tbl), + .tx_tbl = sc8280xp_usb43dp_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb43dp_tx_tbl), + .rx_tbl = sc8280xp_usb43dp_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb43dp_rx_tbl), + .pcs_tbl = sc8280xp_usb43dp_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sc8280xp_usb43dp_pcs_tbl), + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = msm8996_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x300, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +}; + +static const struct qmp_phy_cfg sc8280xp_usb43dp_dp_cfg = { + .type = PHY_TYPE_DP, + .lanes = 2, + + .serdes_tbl = qmp_v5_dp_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v5_dp_serdes_tbl), + .tx_tbl = qmp_v5_5nm_dp_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v5_5nm_dp_tx_tbl), + + .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), + .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), + .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), + .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, + .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), + + .swing_hbr_rbr = &qmp_dp_v5_voltage_swing_hbr_rbr, + .pre_emphasis_hbr_rbr = &qmp_dp_v5_pre_emphasis_hbr_rbr, + .swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2, + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2, + + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = msm8996_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v4_usb3phy_regs_layout, + + .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, + .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, + .configure_dp_phy = qcom_qmp_v5_phy_configure_dp_phy, + .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, +}; + +static const struct qmp_phy_combo_cfg sc8280xp_usb43dpphy_combo_cfg = { + .usb_cfg = &sc8280xp_usb43dp_usb_cfg, + .dp_cfg = &sc8280xp_usb43dp_dp_cfg, +}; + static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = sm8150_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), @@ -1009,14 +1303,11 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, - - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8250_dpphy_cfg = { .type = PHY_TYPE_DP, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v4_dp_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), @@ -1032,6 +1323,11 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = { .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), + .swing_hbr_rbr = &qmp_dp_v3_voltage_swing_hbr_rbr, + .pre_emphasis_hbr_rbr = &qmp_dp_v3_pre_emphasis_hbr_rbr, + .swing_hbr3_hbr2 = &qmp_dp_v3_voltage_swing_hbr3_hbr2, + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v3_pre_emphasis_hbr3_hbr2, + .clk_list = qmp_v4_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), .reset_list = msm8996_usb3phy_reset_l, @@ -1040,9 +1336,6 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = { .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = qmp_v4_usb3phy_regs_layout, - .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, - .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, @@ -1054,7 +1347,7 @@ static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { .dp_cfg = &sm8250_dpphy_cfg, }; -static void qcom_qmp_phy_combo_configure_lane(void __iomem *base, +static void qmp_combo_configure_lane(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num, @@ -1077,15 +1370,15 @@ static void qcom_qmp_phy_combo_configure_lane(void __iomem *base, } } -static void qcom_qmp_phy_combo_configure(void __iomem *base, +static void qmp_combo_configure(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num) { - qcom_qmp_phy_combo_configure_lane(base, regs, tbl, num, 0xff); + qmp_combo_configure_lane(base, regs, tbl, num, 0xff); } -static int qcom_qmp_phy_combo_serdes_init(struct qmp_phy *qphy) +static int qmp_combo_serdes_init(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *serdes = qphy->serdes; @@ -1093,27 +1386,27 @@ static int qcom_qmp_phy_combo_serdes_init(struct qmp_phy *qphy) const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; int serdes_tbl_num = cfg->serdes_tbl_num; - qcom_qmp_phy_combo_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); + qmp_combo_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); if (cfg->type == PHY_TYPE_DP) { switch (dp_opts->link_rate) { case 1620: - qcom_qmp_phy_combo_configure(serdes, cfg->regs, + qmp_combo_configure(serdes, cfg->regs, cfg->serdes_tbl_rbr, cfg->serdes_tbl_rbr_num); break; case 2700: - qcom_qmp_phy_combo_configure(serdes, cfg->regs, + qmp_combo_configure(serdes, cfg->regs, cfg->serdes_tbl_hbr, cfg->serdes_tbl_hbr_num); break; case 5400: - qcom_qmp_phy_combo_configure(serdes, cfg->regs, + qmp_combo_configure(serdes, cfg->regs, cfg->serdes_tbl_hbr2, cfg->serdes_tbl_hbr2_num); break; case 8100: - qcom_qmp_phy_combo_configure(serdes, cfg->regs, + qmp_combo_configure(serdes, cfg->regs, cfg->serdes_tbl_hbr3, cfg->serdes_tbl_hbr3_num); break; @@ -1169,38 +1462,11 @@ static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); } -static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { - { 0x00, 0x0c, 0x15, 0x1a }, - { 0x02, 0x0e, 0x16, 0xff }, - { 0x02, 0x11, 0xff, 0xff }, - { 0x04, 0xff, 0xff, 0xff } -}; - -static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { - { 0x02, 0x12, 0x16, 0x1a }, - { 0x09, 0x19, 0x1f, 0xff }, - { 0x10, 0x1f, 0xff, 0xff }, - { 0x1f, 0xff, 0xff, 0xff } -}; - -static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { - { 0x00, 0x0c, 0x14, 0x19 }, - { 0x00, 0x0b, 0x12, 0xff }, - { 0x00, 0x0b, 0xff, 0xff }, - { 0x04, 0xff, 0xff, 0xff } -}; - -static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { - { 0x08, 0x0f, 0x16, 0x1f }, - { 0x11, 0x1e, 0x1f, 0xff }, - { 0x19, 0x1f, 0xff, 0xff }, - { 0x1f, 0xff, 0xff, 0xff } -}; - -static int qcom_qmp_phy_combo_configure_dp_swing(struct qmp_phy *qphy, +static int qmp_combo_configure_dp_swing(struct qmp_phy *qphy, unsigned int drv_lvl_reg, unsigned int emp_post_reg) { const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; + const struct qmp_phy_cfg *cfg = qphy->cfg; unsigned int v_level = 0, p_level = 0; u8 voltage_swing_cfg, pre_emphasis_cfg; int i; @@ -1211,11 +1477,11 @@ static int qcom_qmp_phy_combo_configure_dp_swing(struct qmp_phy *qphy, } if (dp_opts->link_rate <= 2700) { - voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; - pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; + voltage_swing_cfg = (*cfg->swing_hbr_rbr)[v_level][p_level]; + pre_emphasis_cfg = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level]; } else { - voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; - pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; + voltage_swing_cfg = (*cfg->swing_hbr3_hbr2)[v_level][p_level]; + pre_emphasis_cfg = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level]; } /* TODO: Move check to config check */ @@ -1239,8 +1505,7 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; u32 bias_en, drvr_en; - if (qcom_qmp_phy_combo_configure_dp_swing(qphy, - QSERDES_V3_TX_TX_DRV_LVL, + if (qmp_combo_configure_dp_swing(qphy, QSERDES_V3_TX_TX_DRV_LVL, QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) return; @@ -1258,7 +1523,7 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); } -static bool qcom_qmp_phy_combo_configure_dp_mode(struct qmp_phy *qphy) +static bool qmp_combo_configure_dp_mode(struct qmp_phy *qphy) { u32 val; bool reverse = false; @@ -1295,7 +1560,7 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) u32 phy_vco_div, status; unsigned long pixel_freq; - qcom_qmp_phy_combo_configure_dp_mode(qphy); + qmp_combo_configure_dp_mode(qphy); writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); @@ -1415,23 +1680,20 @@ static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); - qcom_qmp_phy_combo_configure_dp_swing(qphy, - QSERDES_V4_TX_TX_DRV_LVL, + qmp_combo_configure_dp_swing(qphy, QSERDES_V4_TX_TX_DRV_LVL, QSERDES_V4_TX_TX_EMP_POST1_LVL); } -static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) +static int qcom_qmp_v45_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_combo_configure_dp_mode(qphy); + qmp_combo_configure_dp_mode(qphy); writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); @@ -1509,6 +1771,21 @@ static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) 10000)) return -ETIMEDOUT; + return 0; +} + +static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) +{ + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; + u32 bias0_en, drvr0_en, bias1_en, drvr1_en; + bool reverse = false; + u32 status; + int ret; + + ret = qcom_qmp_v45_phy_configure_dp_phy(qphy); + if (ret < 0) + return ret; + /* * At least for 7nm DP PHY this has to be done after enabling link * clock. @@ -1559,6 +1836,63 @@ static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) return 0; } +static int qcom_qmp_v5_phy_configure_dp_phy(struct qmp_phy *qphy) +{ + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; + u32 bias0_en, drvr0_en, bias1_en, drvr1_en; + bool reverse = false; + u32 status; + int ret; + + ret = qcom_qmp_v45_phy_configure_dp_phy(qphy); + if (ret < 0) + return ret; + + if (dp_opts->lanes == 1) { + bias0_en = reverse ? 0x3e : 0x1a; + drvr0_en = reverse ? 0x13 : 0x10; + bias1_en = reverse ? 0x15 : 0x3e; + drvr1_en = reverse ? 0x10 : 0x13; + } else if (dp_opts->lanes == 2) { + bias0_en = reverse ? 0x3f : 0x15; + drvr0_en = 0x10; + bias1_en = reverse ? 0x15 : 0x3f; + drvr1_en = 0x10; + } else { + bias0_en = 0x3f; + bias1_en = 0x3f; + drvr0_en = 0x10; + drvr1_en = 0x10; + } + + writel(drvr0_en, qphy->tx + QSERDES_V5_5NM_TX_HIGHZ_DRVR_EN); + writel(bias0_en, qphy->tx + QSERDES_V5_5NM_TX_TRANSCEIVER_BIAS_EN); + writel(drvr1_en, qphy->tx2 + QSERDES_V5_5NM_TX_HIGHZ_DRVR_EN); + writel(bias1_en, qphy->tx2 + QSERDES_V5_5NM_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_V5_5NM_TX_TX_POL_INV); + writel(0x0a, qphy->tx2 + QSERDES_V5_5NM_TX_TX_POL_INV); + + writel(0x27, qphy->tx + QSERDES_V5_5NM_TX_TX_DRV_LVL); + writel(0x27, qphy->tx2 + QSERDES_V5_5NM_TX_TX_DRV_LVL); + + writel(0x20, qphy->tx + QSERDES_V5_5NM_TX_TX_EMP_POST1_LVL); + writel(0x20, qphy->tx2 + QSERDES_V5_5NM_TX_TX_EMP_POST1_LVL); + + return 0; +} + /* * We need to calibrate the aux setting here as many times * as the caller tries @@ -1603,7 +1937,7 @@ static int qcom_qmp_dp_phy_calibrate(struct phy *phy) return 0; } -static int qcom_qmp_phy_combo_com_init(struct qmp_phy *qphy) +static int qmp_combo_com_init(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -1640,28 +1974,25 @@ static int qcom_qmp_phy_combo_com_init(struct qmp_phy *qphy) if (ret) goto err_assert_reset; - if (cfg->has_phy_dp_com_ctrl) { - qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, - SW_PWRDN); - /* override hardware control for reset of qmp phy */ - qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, - SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | - SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); + qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN); - /* Default type-c orientation, i.e CC1 */ - qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); + /* override hardware control for reset of qmp phy */ + qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, + SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | + SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); - qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, - USB3_MODE | DP_MODE); + /* Default type-c orientation, i.e CC1 */ + qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); - /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ - qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, - SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | - SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); + qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE); - qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); - qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); - } + /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ + qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, + SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | + SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); + + qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); + qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) qphy_setbits(pcs, @@ -1685,7 +2016,7 @@ err_unlock: return ret; } -static int qcom_qmp_phy_combo_com_exit(struct qmp_phy *qphy) +static int qmp_combo_com_exit(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -1709,7 +2040,7 @@ static int qcom_qmp_phy_combo_com_exit(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_combo_init(struct phy *phy) +static int qmp_combo_init(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -1717,7 +2048,7 @@ static int qcom_qmp_phy_combo_init(struct phy *phy) int ret; dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - ret = qcom_qmp_phy_combo_com_init(qphy); + ret = qmp_combo_com_init(qphy); if (ret) return ret; @@ -1727,7 +2058,7 @@ static int qcom_qmp_phy_combo_init(struct phy *phy) return 0; } -static int qcom_qmp_phy_combo_power_on(struct phy *phy) +static int qmp_combo_power_on(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -1739,7 +2070,7 @@ static int qcom_qmp_phy_combo_power_on(struct phy *phy) unsigned int mask, val, ready; int ret; - qcom_qmp_phy_combo_serdes_init(qphy); + qmp_combo_serdes_init(qphy); ret = clk_prepare_enable(qphy->pipe_clk); if (ret) { @@ -1748,33 +2079,29 @@ static int qcom_qmp_phy_combo_power_on(struct phy *phy) } /* Tx, Rx, and PCS configurations */ - qcom_qmp_phy_combo_configure_lane(tx, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 1); + qmp_combo_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); - /* Configuration for other LANE for USB-DP combo PHY */ - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_combo_configure_lane(qphy->tx2, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_combo_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl, + cfg->tx_tbl_num, 2); } /* Configure special DP tx tunings */ if (cfg->type == PHY_TYPE_DP) cfg->configure_dp_tx(qphy); - qcom_qmp_phy_combo_configure_lane(rx, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 1); + qmp_combo_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_combo_configure_lane(qphy->rx2, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_combo_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl, + cfg->rx_tbl_num, 2); } /* Configure link rate, swing, etc. */ - if (cfg->type == PHY_TYPE_DP) { + if (cfg->type == PHY_TYPE_DP) cfg->configure_dp_phy(qphy); - } else { - qcom_qmp_phy_combo_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); - } + else + qmp_combo_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ret = reset_control_deassert(qmp->ufs_reset); if (ret) @@ -1808,7 +2135,7 @@ err_disable_pipe_clk: return ret; } -static int qcom_qmp_phy_combo_power_off(struct phy *phy) +static int qmp_combo_power_off(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -1838,42 +2165,41 @@ static int qcom_qmp_phy_combo_power_off(struct phy *phy) return 0; } -static int qcom_qmp_phy_combo_exit(struct phy *phy) +static int qmp_combo_exit(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); - qcom_qmp_phy_combo_com_exit(qphy); + qmp_combo_com_exit(qphy); return 0; } -static int qcom_qmp_phy_combo_enable(struct phy *phy) +static int qmp_combo_enable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_combo_init(phy); + ret = qmp_combo_init(phy); if (ret) return ret; - ret = qcom_qmp_phy_combo_power_on(phy); + ret = qmp_combo_power_on(phy); if (ret) - qcom_qmp_phy_combo_exit(phy); + qmp_combo_exit(phy); return ret; } -static int qcom_qmp_phy_combo_disable(struct phy *phy) +static int qmp_combo_disable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_combo_power_off(phy); + ret = qmp_combo_power_off(phy); if (ret) return ret; - return qcom_qmp_phy_combo_exit(phy); + return qmp_combo_exit(phy); } -static int qcom_qmp_phy_combo_set_mode(struct phy *phy, - enum phy_mode mode, int submode) +static int qmp_combo_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct qmp_phy *qphy = phy_get_drvdata(phy); @@ -1882,7 +2208,7 @@ static int qcom_qmp_phy_combo_set_mode(struct phy *phy, return 0; } -static void qcom_qmp_phy_combo_enable_autonomous_mode(struct qmp_phy *qphy) +static void qmp_combo_enable_autonomous_mode(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; @@ -1911,7 +2237,7 @@ static void qcom_qmp_phy_combo_enable_autonomous_mode(struct qmp_phy *qphy) qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); } -static void qcom_qmp_phy_combo_disable_autonomous_mode(struct qmp_phy *qphy) +static void qmp_combo_disable_autonomous_mode(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs_usb; @@ -1929,7 +2255,7 @@ static void qcom_qmp_phy_combo_disable_autonomous_mode(struct qmp_phy *qphy) qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); } -static int __maybe_unused qcom_qmp_phy_combo_runtime_suspend(struct device *dev) +static int __maybe_unused qmp_combo_runtime_suspend(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct qmp_phy *qphy = qmp->phys[0]; @@ -1946,7 +2272,7 @@ static int __maybe_unused qcom_qmp_phy_combo_runtime_suspend(struct device *dev) return 0; } - qcom_qmp_phy_combo_enable_autonomous_mode(qphy); + qmp_combo_enable_autonomous_mode(qphy); clk_disable_unprepare(qphy->pipe_clk); clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); @@ -1954,7 +2280,7 @@ static int __maybe_unused qcom_qmp_phy_combo_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused qcom_qmp_phy_combo_runtime_resume(struct device *dev) +static int __maybe_unused qmp_combo_runtime_resume(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct qmp_phy *qphy = qmp->phys[0]; @@ -1983,12 +2309,12 @@ static int __maybe_unused qcom_qmp_phy_combo_runtime_resume(struct device *dev) return ret; } - qcom_qmp_phy_combo_disable_autonomous_mode(qphy); + qmp_combo_disable_autonomous_mode(qphy); return 0; } -static int qcom_qmp_phy_combo_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_combo_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_vregs; @@ -2020,7 +2346,7 @@ static int qcom_qmp_phy_combo_vreg_init(struct device *dev, const struct qmp_phy return 0; } -static int qcom_qmp_phy_combo_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_combo_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int i; @@ -2041,7 +2367,7 @@ static int qcom_qmp_phy_combo_reset_init(struct device *dev, const struct qmp_ph return 0; } -static int qcom_qmp_phy_combo_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_combo_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_clks; @@ -2309,33 +2635,31 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); } -static const struct phy_ops qcom_qmp_phy_combo_usb_ops = { - .init = qcom_qmp_phy_combo_enable, - .exit = qcom_qmp_phy_combo_disable, - .set_mode = qcom_qmp_phy_combo_set_mode, +static const struct phy_ops qmp_combo_usb_ops = { + .init = qmp_combo_enable, + .exit = qmp_combo_disable, + .set_mode = qmp_combo_set_mode, .owner = THIS_MODULE, }; -static const struct phy_ops qcom_qmp_phy_combo_dp_ops = { - .init = qcom_qmp_phy_combo_init, +static const struct phy_ops qmp_combo_dp_ops = { + .init = qmp_combo_init, .configure = qcom_qmp_dp_phy_configure, - .power_on = qcom_qmp_phy_combo_power_on, + .power_on = qmp_combo_power_on, .calibrate = qcom_qmp_dp_phy_calibrate, - .power_off = qcom_qmp_phy_combo_power_off, - .exit = qcom_qmp_phy_combo_exit, - .set_mode = qcom_qmp_phy_combo_set_mode, + .power_off = qmp_combo_power_off, + .exit = qmp_combo_exit, + .set_mode = qmp_combo_set_mode, .owner = THIS_MODULE, }; -static -int qcom_qmp_phy_combo_create(struct device *dev, struct device_node *np, int id, +static int qmp_combo_create(struct device *dev, struct device_node *np, int id, void __iomem *serdes, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct phy *generic_phy; struct qmp_phy *qphy; const struct phy_ops *ops; - char prop_name[MAX_PROP_NAME]; int ret; qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); @@ -2350,49 +2674,39 @@ int qcom_qmp_phy_combo_create(struct device *dev, struct device_node *np, int id * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 * For single lane PHYs: pcs_misc (optional) -> 3. */ - qphy->tx = of_iomap(np, 0); - if (!qphy->tx) - return -ENOMEM; + qphy->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); - qphy->rx = of_iomap(np, 1); - if (!qphy->rx) - return -ENOMEM; + qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); - qphy->pcs = of_iomap(np, 2); - if (!qphy->pcs) - return -ENOMEM; + qphy->pcs = devm_of_iomap(dev, np, 2, NULL); + if (IS_ERR(qphy->pcs)) + return PTR_ERR(qphy->pcs); if (cfg->pcs_usb_offset) qphy->pcs_usb = qphy->pcs + cfg->pcs_usb_offset; - /* - * If this is a dual-lane PHY, then there should be registers for the - * second lane. Some old device trees did not specify this, so fall - * back to old legacy behavior of assuming they can be reached at an - * offset from the first lane. - */ - if (cfg->is_dual_lane_phy) { - qphy->tx2 = of_iomap(np, 3); - qphy->rx2 = of_iomap(np, 4); - if (!qphy->tx2 || !qphy->rx2) { - dev_warn(dev, - "Underspecified device tree, falling back to legacy register regions\n"); - - /* In the old version, pcs_misc is at index 3. */ - qphy->pcs_misc = qphy->tx2; - qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; - qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; + if (cfg->lanes >= 2) { + qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); + if (IS_ERR(qphy->tx2)) + return PTR_ERR(qphy->tx2); - } else { - qphy->pcs_misc = of_iomap(np, 5); - } + qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); + if (IS_ERR(qphy->rx2)) + return PTR_ERR(qphy->rx2); + qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); } else { - qphy->pcs_misc = of_iomap(np, 3); + qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); } - if (!qphy->pcs_misc) + if (IS_ERR(qphy->pcs_misc)) { dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + qphy->pcs_misc = NULL; + } /* * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 @@ -2401,24 +2715,19 @@ int qcom_qmp_phy_combo_create(struct device *dev, struct device_node *np, int id * Otherwise, we initialize pipe clock to NULL for * all phys that don't need this. */ - snprintf(prop_name, sizeof(prop_name), "pipe%d", id); - qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); + qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); if (IS_ERR(qphy->pipe_clk)) { - if (cfg->type == PHY_TYPE_USB3) { - ret = PTR_ERR(qphy->pipe_clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, - "failed to get lane%d pipe_clk, %d\n", - id, ret); - return ret; - } + if (cfg->type == PHY_TYPE_USB3) + return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), + "failed to get lane%d pipe_clk\n", + id); qphy->pipe_clk = NULL; } if (cfg->type == PHY_TYPE_DP) - ops = &qcom_qmp_phy_combo_dp_ops; + ops = &qmp_combo_dp_ops; else - ops = &qcom_qmp_phy_combo_usb_ops; + ops = &qmp_combo_usb_ops; generic_phy = devm_phy_create(dev, np, ops); if (IS_ERR(generic_phy)) { @@ -2428,7 +2737,6 @@ int qcom_qmp_phy_combo_create(struct device *dev, struct device_node *np, int id } qphy->phy = generic_phy; - qphy->index = id; qphy->qmp = qmp; qmp->phys[id] = qphy; phy_set_drvdata(generic_phy, qphy); @@ -2436,12 +2744,16 @@ int qcom_qmp_phy_combo_create(struct device *dev, struct device_node *np, int id return 0; } -static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { +static const struct of_device_id qmp_combo_of_match_table[] = { { .compatible = "qcom,sc7180-qmp-usb3-dp-phy", .data = &sc7180_usb3dpphy_cfg, }, { + .compatible = "qcom,sdm845-qmp-usb3-dp-phy", + .data = &sdm845_usb3dpphy_cfg, + }, + { .compatible = "qcom,sm8250-qmp-usb3-dp-phy", .data = &sm8250_usb3dpphy_cfg, }, @@ -2449,16 +2761,20 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", .data = &sc8180x_usb3dpphy_cfg, }, + { + .compatible = "qcom,sc8280xp-qmp-usb43dp-phy", + .data = &sc8280xp_usb43dpphy_combo_cfg, + }, { } }; -MODULE_DEVICE_TABLE(of, qcom_qmp_combo_phy_of_match_table); +MODULE_DEVICE_TABLE(of, qmp_combo_of_match_table); -static const struct dev_pm_ops qcom_qmp_phy_combo_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_qmp_phy_combo_runtime_suspend, - qcom_qmp_phy_combo_runtime_resume, NULL) +static const struct dev_pm_ops qmp_combo_pm_ops = { + SET_RUNTIME_PM_OPS(qmp_combo_runtime_suspend, + qmp_combo_runtime_resume, NULL) }; -static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) +static int qmp_combo_probe(struct platform_device *pdev) { struct qcom_qmp *qmp; struct device *dev = &pdev->dev; @@ -2494,12 +2810,9 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) if (IS_ERR(serdes)) return PTR_ERR(serdes); - /* per PHY dp_com; if PHY has dp_com control block */ - if (cfg->has_phy_dp_com_ctrl) { - qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(qmp->dp_com)) - return PTR_ERR(qmp->dp_com); - } + qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(qmp->dp_com)) + return PTR_ERR(qmp->dp_com); /* Only two serdes for combo PHY */ dp_serdes = devm_platform_ioremap_resource(pdev, 2); @@ -2511,21 +2824,18 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) mutex_init(&qmp->phy_mutex); - ret = qcom_qmp_phy_combo_clk_init(dev, cfg); + ret = qmp_combo_clk_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_combo_reset_init(dev, cfg); + ret = qmp_combo_reset_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_combo_vreg_init(dev, cfg); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + ret = qmp_combo_vreg_init(dev, cfg); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); num = of_get_available_child_count(dev->of_node); /* do we have a rogue child node ? */ @@ -2537,7 +2847,9 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) return -ENOMEM; pm_runtime_set_active(dev); - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; /* * Prevent runtime pm from being ON by default. Users can enable * it using power/control in sysfs. @@ -2551,7 +2863,7 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) serdes = dp_serdes; /* Create per-lane phy */ - ret = qcom_qmp_phy_combo_create(dev, child, id, serdes, cfg); + ret = qmp_combo_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -2569,7 +2881,7 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) serdes = usb_serdes; /* Create per-lane phy */ - ret = qcom_qmp_phy_combo_create(dev, child, id, serdes, cfg); + ret = qmp_combo_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -2592,29 +2904,24 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_info(dev, "Registered Qcom-QMP phy\n"); - else - pm_runtime_disable(dev); return PTR_ERR_OR_ZERO(phy_provider); err_node_put: - pm_runtime_disable(dev); of_node_put(child); return ret; } -static struct platform_driver qcom_qmp_phy_combo_driver = { - .probe = qcom_qmp_phy_combo_probe, +static struct platform_driver qmp_combo_driver = { + .probe = qmp_combo_probe, .driver = { .name = "qcom-qmp-combo-phy", - .pm = &qcom_qmp_phy_combo_pm_ops, - .of_match_table = qcom_qmp_combo_phy_of_match_table, + .pm = &qmp_combo_pm_ops, + .of_match_table = qmp_combo_of_match_table, }, }; -module_platform_driver(qcom_qmp_phy_combo_driver); +module_platform_driver(qmp_combo_driver); MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); MODULE_DESCRIPTION("Qualcomm QMP USB+DP combo PHY driver"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c index be6a94439b6c..461f0b5d464a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c @@ -36,46 +36,13 @@ /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) #define PHYSTATUS_4_20 BIT(7) -/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ +/* QPHY_COM_PCS_READY_STATUS bit */ #define PCS_READY BIT(0) -/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ -/* DP PHY soft reset */ -#define SW_DPPHY_RESET BIT(0) -/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ -#define SW_DPPHY_RESET_MUX BIT(1) -/* USB3 PHY soft reset */ -#define SW_USB3PHY_RESET BIT(2) -/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ -#define SW_USB3PHY_RESET_MUX BIT(3) - -/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ -#define USB3_MODE BIT(0) /* enables USB3 mode */ -#define DP_MODE BIT(1) /* enables DP mode */ - -/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ -#define ARCVR_DTCT_EN BIT(0) -#define ALFPS_DTCT_EN BIT(1) -#define ARCVR_DTCT_EVENT_SEL BIT(4) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ -#define IRQ_CLEAR BIT(0) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ -#define RCVR_DETECT BIT(0) - -/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ -#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ - #define PHY_INIT_COMPLETE_TIMEOUT 10000 #define POWER_DOWN_DELAY_US_MIN 10 #define POWER_DOWN_DELAY_US_MAX 11 -#define MAX_PROP_NAME 32 - -/* Define the assumed distance between lanes for underspecified device trees. */ -#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 - struct qmp_phy_init_tbl { unsigned int offset; unsigned int val; @@ -123,14 +90,8 @@ enum qphy_reg_layout { /* PCS registers */ QPHY_SW_RESET, QPHY_START_CTRL, - QPHY_PCS_READY_STATUS, QPHY_PCS_STATUS, - QPHY_PCS_AUTONOMOUS_MODE_CTRL, - QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, - QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, QPHY_PCS_POWER_DOWN_CONTROL, - /* PCS_MISC registers */ - QPHY_PCS_MISC_TYPEC_CTRL, /* Keep last to ensure regs_layout arrays are properly initialized */ QPHY_LAYOUT_SIZE }; @@ -223,36 +184,20 @@ static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V2_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), }; -struct qmp_phy; - /* struct qmp_phy_cfg - per-PHY initialization config */ struct qmp_phy_cfg { - /* phy-type - PCIE/UFS/USB */ - unsigned int type; - /* number of lanes provided by phy */ - int nlanes; + /* number of PHYs provided by this block */ + int num_phys; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; int serdes_tbl_num; - const struct qmp_phy_init_tbl *serdes_tbl_sec; - int serdes_tbl_num_sec; const struct qmp_phy_init_tbl *tx_tbl; int tx_tbl_num; - const struct qmp_phy_init_tbl *tx_tbl_sec; - int tx_tbl_num_sec; const struct qmp_phy_init_tbl *rx_tbl; int rx_tbl_num; - const struct qmp_phy_init_tbl *rx_tbl_sec; - int rx_tbl_num_sec; const struct qmp_phy_init_tbl *pcs_tbl; int pcs_tbl_num; - const struct qmp_phy_init_tbl *pcs_tbl_sec; - int pcs_tbl_num_sec; - const struct qmp_phy_init_tbl *pcs_misc_tbl; - int pcs_misc_tbl_num; - const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; - int pcs_misc_tbl_num_sec; /* clock ids to be requested */ const char * const *clk_list; @@ -289,12 +234,10 @@ struct qmp_phy_cfg { * @tx: iomapped memory space for lane's tx * @rx: iomapped memory space for lane's rx * @pcs: iomapped memory space for lane's pcs - * @pcs_misc: iomapped memory space for lane's pcs_misc * @pipe_clk: pipe clock * @index: lane index * @qmp: QMP phy to which this lane belongs * @lane_rst: lane's reset controller - * @mode: current PHY mode */ struct qmp_phy { struct phy *phy; @@ -303,12 +246,10 @@ struct qmp_phy { void __iomem *tx; void __iomem *rx; void __iomem *pcs; - void __iomem *pcs_misc; struct clk *pipe_clk; unsigned int index; struct qcom_qmp *qmp; struct reset_control *lane_rst; - enum phy_mode mode; }; /** @@ -377,8 +318,7 @@ static const char * const qmp_phy_vreg_l[] = { }; static const struct qmp_phy_cfg msm8996_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 3, + .num_phys = 3, .serdes_tbl = msm8996_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), @@ -406,7 +346,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, }; -static void qcom_qmp_phy_pcie_msm8996_configure_lane(void __iomem *base, +static void qmp_pcie_msm8996_configure_lane(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num, @@ -429,15 +369,15 @@ static void qcom_qmp_phy_pcie_msm8996_configure_lane(void __iomem *base, } } -static void qcom_qmp_phy_pcie_msm8996_configure(void __iomem *base, +static void qmp_pcie_msm8996_configure(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num) { - qcom_qmp_phy_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff); + qmp_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff); } -static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) +static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -448,11 +388,7 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) unsigned int mask, val; int ret; - qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); - if (cfg->serdes_tbl_sec) - qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, - cfg->serdes_tbl_num_sec); - + qmp_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], @@ -472,7 +408,7 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_pcie_msm8996_com_init(struct qmp_phy *qphy) +static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -525,7 +461,7 @@ err_unlock: return ret; } -static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy) +static int qmp_pcie_msm8996_com_exit(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -555,21 +491,21 @@ static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_pcie_msm8996_init(struct phy *phy) +static int qmp_pcie_msm8996_init(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; int ret; dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - ret = qcom_qmp_phy_pcie_msm8996_com_init(qphy); + ret = qmp_pcie_msm8996_com_init(qphy); if (ret) return ret; return 0; } -static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) +static int qmp_pcie_msm8996_power_on(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -577,12 +513,11 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) void __iomem *tx = qphy->tx; void __iomem *rx = qphy->rx; void __iomem *pcs = qphy->pcs; - void __iomem *pcs_misc = qphy->pcs_misc; void __iomem *status; unsigned int mask, val, ready; int ret; - qcom_qmp_phy_pcie_msm8996_serdes_init(qphy); + qmp_pcie_msm8996_serdes_init(qphy); ret = reset_control_deassert(qphy->lane_rst); if (ret) { @@ -598,28 +533,13 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) } /* Tx, Rx, and PCS configurations */ - qcom_qmp_phy_pcie_msm8996_configure_lane(tx, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 1); - if (cfg->tx_tbl_sec) - qcom_qmp_phy_pcie_msm8996_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, - cfg->tx_tbl_num_sec, 1); - - qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 1); - if (cfg->rx_tbl_sec) - qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs, - cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); - - qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); - if (cfg->pcs_tbl_sec) - qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, - cfg->pcs_tbl_num_sec); - - qcom_qmp_phy_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, - cfg->pcs_misc_tbl_num); - if (cfg->pcs_misc_tbl_sec) - qcom_qmp_phy_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, - cfg->pcs_misc_tbl_num_sec); + qmp_pcie_msm8996_configure_lane(tx, cfg->regs, cfg->tx_tbl, + cfg->tx_tbl_num, 1); + + qmp_pcie_msm8996_configure_lane(rx, cfg->regs, cfg->rx_tbl, + cfg->rx_tbl_num, 1); + + qmp_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); /* * Pull out PHY from POWER DOWN state. @@ -657,7 +577,7 @@ err_reset_lane: return ret; } -static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) +static int qmp_pcie_msm8996_power_off(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -682,53 +602,43 @@ static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) return 0; } -static int qcom_qmp_phy_pcie_msm8996_exit(struct phy *phy) +static int qmp_pcie_msm8996_exit(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); reset_control_assert(qphy->lane_rst); - qcom_qmp_phy_pcie_msm8996_com_exit(qphy); + qmp_pcie_msm8996_com_exit(qphy); return 0; } -static int qcom_qmp_phy_pcie_msm8996_enable(struct phy *phy) +static int qmp_pcie_msm8996_enable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_pcie_msm8996_init(phy); + ret = qmp_pcie_msm8996_init(phy); if (ret) return ret; - ret = qcom_qmp_phy_pcie_msm8996_power_on(phy); + ret = qmp_pcie_msm8996_power_on(phy); if (ret) - qcom_qmp_phy_pcie_msm8996_exit(phy); + qmp_pcie_msm8996_exit(phy); return ret; } -static int qcom_qmp_phy_pcie_msm8996_disable(struct phy *phy) +static int qmp_pcie_msm8996_disable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_pcie_msm8996_power_off(phy); + ret = qmp_pcie_msm8996_power_off(phy); if (ret) return ret; - return qcom_qmp_phy_pcie_msm8996_exit(phy); + return qmp_pcie_msm8996_exit(phy); } -static int qcom_qmp_phy_pcie_msm8996_set_mode(struct phy *phy, - enum phy_mode mode, int submode) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - - qphy->mode = mode; - - return 0; -} - -static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_vregs; @@ -744,7 +654,7 @@ static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct return devm_regulator_bulk_get(dev, num, qmp->vregs); } -static int qcom_qmp_phy_pcie_msm8996_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_msm8996_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int i; @@ -765,7 +675,7 @@ static int qcom_qmp_phy_pcie_msm8996_reset_init(struct device *dev, const struct return 0; } -static int qcom_qmp_phy_pcie_msm8996_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_msm8996_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_clks; @@ -841,10 +751,9 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); } -static const struct phy_ops qcom_qmp_phy_pcie_msm8996_ops = { - .power_on = qcom_qmp_phy_pcie_msm8996_enable, - .power_off = qcom_qmp_phy_pcie_msm8996_disable, - .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, +static const struct phy_ops qmp_pcie_msm8996_ops = { + .power_on = qmp_pcie_msm8996_enable, + .power_off = qmp_pcie_msm8996_disable, .owner = THIS_MODULE, }; @@ -853,14 +762,12 @@ static void qcom_qmp_reset_control_put(void *data) reset_control_put(data); } -static -int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, int id, +static int qmp_pcie_msm8996_create(struct device *dev, struct device_node *np, int id, void __iomem *serdes, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct phy *generic_phy; struct qmp_phy *qphy; - char prop_name[MAX_PROP_NAME]; int ret; qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); @@ -872,36 +779,26 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, /* * Get memory resources for each phy lane: * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. - * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 - * For single lane PHYs: pcs_misc (optional) -> 3. */ - qphy->tx = of_iomap(np, 0); - if (!qphy->tx) - return -ENOMEM; - - qphy->rx = of_iomap(np, 1); - if (!qphy->rx) - return -ENOMEM; - - qphy->pcs = of_iomap(np, 2); - if (!qphy->pcs) - return -ENOMEM; + qphy->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); - qphy->pcs_misc = of_iomap(np, 3); + qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); - if (!qphy->pcs_misc) - dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + qphy->pcs = devm_of_iomap(dev, np, 2, NULL); + if (IS_ERR(qphy->pcs)) + return PTR_ERR(qphy->pcs); - snprintf(prop_name, sizeof(prop_name), "pipe%d", id); - qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); + qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); if (IS_ERR(qphy->pipe_clk)) { return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), "failed to get lane%d pipe clock\n", id); } - /* Get lane reset, if any */ - snprintf(prop_name, sizeof(prop_name), "lane%d", id); - qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); + qphy->lane_rst = of_reset_control_get_exclusive_by_index(np, 0); if (IS_ERR(qphy->lane_rst)) { dev_err(dev, "failed to get lane%d reset\n", id); return PTR_ERR(qphy->lane_rst); @@ -911,7 +808,7 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, if (ret) return ret; - generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_msm8996_ops); + generic_phy = devm_phy_create(dev, np, &qmp_pcie_msm8996_ops); if (IS_ERR(generic_phy)) { ret = PTR_ERR(generic_phy); dev_err(dev, "failed to create qphy %d\n", ret); @@ -927,16 +824,16 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, return 0; } -static const struct of_device_id qcom_qmp_phy_pcie_msm8996_of_match_table[] = { +static const struct of_device_id qmp_pcie_msm8996_of_match_table[] = { { .compatible = "qcom,msm8996-qmp-pcie-phy", .data = &msm8996_pciephy_cfg, }, { }, }; -MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_msm8996_of_match_table); +MODULE_DEVICE_TABLE(of, qmp_pcie_msm8996_of_match_table); -static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) +static int qmp_pcie_msm8996_probe(struct platform_device *pdev) { struct qcom_qmp *qmp; struct device *dev = &pdev->dev; @@ -964,25 +861,22 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) if (IS_ERR(serdes)) return PTR_ERR(serdes); - expected_phys = cfg->nlanes; + expected_phys = cfg->num_phys; mutex_init(&qmp->phy_mutex); - ret = qcom_qmp_phy_pcie_msm8996_clk_init(dev, cfg); + ret = qmp_pcie_msm8996_clk_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_pcie_msm8996_reset_init(dev, cfg); + ret = qmp_pcie_msm8996_reset_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_pcie_msm8996_vreg_init(dev, cfg); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + ret = qmp_pcie_msm8996_vreg_init(dev, cfg); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); num = of_get_available_child_count(dev->of_node); /* do we have a rogue child node ? */ @@ -993,18 +887,10 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) if (!qmp->phys) return -ENOMEM; - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - /* - * Prevent runtime pm from being ON by default. Users can enable - * it using power/control in sysfs. - */ - pm_runtime_forbid(dev); - id = 0; for_each_available_child_of_node(dev->of_node, child) { /* Create per-lane phy */ - ret = qcom_qmp_phy_pcie_msm8996_create(dev, child, id, serdes, cfg); + ret = qmp_pcie_msm8996_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -1026,28 +912,23 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_info(dev, "Registered Qcom-QMP phy\n"); - else - pm_runtime_disable(dev); return PTR_ERR_OR_ZERO(phy_provider); err_node_put: - pm_runtime_disable(dev); of_node_put(child); return ret; } -static struct platform_driver qcom_qmp_phy_pcie_msm8996_driver = { - .probe = qcom_qmp_phy_pcie_msm8996_probe, +static struct platform_driver qmp_pcie_msm8996_driver = { + .probe = qmp_pcie_msm8996_probe, .driver = { .name = "qcom-qmp-msm8996-pcie-phy", - .of_match_table = qcom_qmp_phy_pcie_msm8996_of_match_table, + .of_match_table = qmp_pcie_msm8996_of_match_table, }, }; -module_platform_driver(qcom_qmp_phy_pcie_msm8996_driver); +module_platform_driver(qmp_pcie_msm8996_driver); MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); MODULE_DESCRIPTION("Qualcomm QMP MSM8996 PCIe PHY driver"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 2d65e1f56bfc..5be5348fbb26 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -32,49 +32,11 @@ /* QPHY_START_CONTROL bits */ #define SERDES_START BIT(0) #define PCS_START BIT(1) -#define PLL_READY_GATE_EN BIT(3) /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) #define PHYSTATUS_4_20 BIT(7) -/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ -#define PCS_READY BIT(0) - -/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ -/* DP PHY soft reset */ -#define SW_DPPHY_RESET BIT(0) -/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ -#define SW_DPPHY_RESET_MUX BIT(1) -/* USB3 PHY soft reset */ -#define SW_USB3PHY_RESET BIT(2) -/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ -#define SW_USB3PHY_RESET_MUX BIT(3) - -/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ -#define USB3_MODE BIT(0) /* enables USB3 mode */ -#define DP_MODE BIT(1) /* enables DP mode */ - -/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ -#define ARCVR_DTCT_EN BIT(0) -#define ALFPS_DTCT_EN BIT(1) -#define ARCVR_DTCT_EVENT_SEL BIT(4) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ -#define IRQ_CLEAR BIT(0) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ -#define RCVR_DETECT BIT(0) - -/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ -#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ #define PHY_INIT_COMPLETE_TIMEOUT 10000 -#define POWER_DOWN_DELAY_US_MIN 10 -#define POWER_DOWN_DELAY_US_MAX 11 - -#define MAX_PROP_NAME 32 - -/* Define the assumed distance between lanes for underspecified device trees. */ -#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 struct qmp_phy_init_tbl { unsigned int offset; @@ -123,14 +85,8 @@ enum qphy_reg_layout { /* PCS registers */ QPHY_SW_RESET, QPHY_START_CTRL, - QPHY_PCS_READY_STATUS, QPHY_PCS_STATUS, - QPHY_PCS_AUTONOMOUS_MODE_CTRL, - QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, - QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, QPHY_PCS_POWER_DOWN_CONTROL, - /* PCS_MISC registers */ - QPHY_PCS_MISC_TYPEC_CTRL, /* Keep last to ensure regs_layout arrays are properly initialized */ QPHY_LAYOUT_SIZE }; @@ -1344,14 +1300,9 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), }; -struct qmp_phy; - /* struct qmp_phy_cfg - per-PHY initialization config */ struct qmp_phy_cfg { - /* phy-type - PCIE/UFS/USB */ - unsigned int type; - /* number of lanes provided by phy */ - int nlanes; + int lanes; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; @@ -1390,7 +1341,6 @@ struct qmp_phy_cfg { unsigned int start_ctrl; unsigned int pwrdn_ctrl; - unsigned int mask_com_pcs_ready; /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ unsigned int phy_status; @@ -1400,9 +1350,6 @@ struct qmp_phy_cfg { int pwrdn_delay_min; int pwrdn_delay_max; - /* true, if PHY has secondary tx/rx lanes to be configured */ - bool is_dual_lane_phy; - /* QMP PHY pipe clock interface rate */ unsigned long pipe_clock_rate; }; @@ -1420,9 +1367,7 @@ struct qmp_phy_cfg { * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) * @pcs_misc: iomapped memory space for lane's pcs_misc * @pipe_clk: pipe clock - * @index: lane index * @qmp: QMP phy to which this lane belongs - * @mode: current PHY mode */ struct qmp_phy { struct phy *phy; @@ -1435,9 +1380,7 @@ struct qmp_phy { void __iomem *rx2; void __iomem *pcs_misc; struct clk *pipe_clk; - unsigned int index; struct qcom_qmp *qmp; - enum phy_mode mode; }; /** @@ -1514,8 +1457,7 @@ static const char * const sdm845_pciephy_reset_l[] = { }; static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = ipq8074_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), @@ -1543,8 +1485,7 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { }; static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = ipq8074_pcie_gen3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_serdes_tbl), @@ -1573,8 +1514,7 @@ static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { }; static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = ipq6018_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), @@ -1603,8 +1543,7 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { }; static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), @@ -1634,8 +1573,7 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { }; static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), @@ -1663,8 +1601,7 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { }; static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), @@ -1702,8 +1639,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { }; static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), @@ -1735,15 +1671,13 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, .phy_status = PHYSTATUS, - .is_dual_lane_phy = true, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ .pwrdn_delay_max = 1005, /* us */ }; static const struct qmp_phy_cfg msm8998_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = msm8998_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), @@ -1767,8 +1701,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = { }; static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), @@ -1797,8 +1730,7 @@ static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { }; static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), @@ -1822,15 +1754,13 @@ static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS_4_20, - .is_dual_lane_phy = true, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ .pwrdn_delay_max = 1005, /* us */ }; static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), @@ -1860,8 +1790,7 @@ static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { }; static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), @@ -1885,13 +1814,12 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, .phy_status = PHYSTATUS_4_20, - .is_dual_lane_phy = true, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ .pwrdn_delay_max = 1005, /* us */ }; -static void qcom_qmp_phy_pcie_configure_lane(void __iomem *base, +static void qmp_pcie_configure_lane(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num, @@ -1914,31 +1842,30 @@ static void qcom_qmp_phy_pcie_configure_lane(void __iomem *base, } } -static void qcom_qmp_phy_pcie_configure(void __iomem *base, - const unsigned int *regs, - const struct qmp_phy_init_tbl tbl[], - int num) +static void qmp_pcie_configure(void __iomem *base, + const unsigned int *regs, + const struct qmp_phy_init_tbl tbl[], + int num) { - qcom_qmp_phy_pcie_configure_lane(base, regs, tbl, num, 0xff); + qmp_pcie_configure_lane(base, regs, tbl, num, 0xff); } -static int qcom_qmp_phy_pcie_serdes_init(struct qmp_phy *qphy) +static int qmp_pcie_serdes_init(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *serdes = qphy->serdes; const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; int serdes_tbl_num = cfg->serdes_tbl_num; - qcom_qmp_phy_pcie_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); - if (cfg->serdes_tbl_sec) - qcom_qmp_phy_pcie_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, - cfg->serdes_tbl_num_sec); + qmp_pcie_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); + qmp_pcie_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, cfg->serdes_tbl_num_sec); return 0; } -static int qcom_qmp_phy_pcie_com_init(struct qmp_phy *qphy) +static int qmp_pcie_init(struct phy *phy) { + struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs = qphy->pcs; @@ -1985,8 +1912,9 @@ err_disable_regulators: return ret; } -static int qcom_qmp_phy_pcie_com_exit(struct qmp_phy *qphy) +static int qmp_pcie_exit(struct phy *phy) { + struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -1999,21 +1927,7 @@ static int qcom_qmp_phy_pcie_com_exit(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_pcie_init(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - struct qcom_qmp *qmp = qphy->qmp; - int ret; - dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - - ret = qcom_qmp_phy_pcie_com_init(qphy); - if (ret) - return ret; - - return 0; -} - -static int qcom_qmp_phy_pcie_power_on(struct phy *phy) +static int qmp_pcie_power_on(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -2026,7 +1940,7 @@ static int qcom_qmp_phy_pcie_power_on(struct phy *phy) unsigned int mask, val, ready; int ret; - qcom_qmp_phy_pcie_serdes_init(qphy); + qmp_pcie_serdes_init(qphy); ret = clk_prepare_enable(qphy->pipe_clk); if (ret) { @@ -2035,47 +1949,31 @@ static int qcom_qmp_phy_pcie_power_on(struct phy *phy) } /* Tx, Rx, and PCS configurations */ - qcom_qmp_phy_pcie_configure_lane(tx, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 1); - if (cfg->tx_tbl_sec) - qcom_qmp_phy_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, - cfg->tx_tbl_num_sec, 1); - - /* Configuration for other LANE for USB-DP combo PHY */ - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_pcie_configure_lane(qphy->tx2, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 2); - if (cfg->tx_tbl_sec) - qcom_qmp_phy_pcie_configure_lane(qphy->tx2, cfg->regs, - cfg->tx_tbl_sec, - cfg->tx_tbl_num_sec, 2); + qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); + qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, cfg->tx_tbl_num_sec, 1); + + if (cfg->lanes >= 2) { + qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl, + cfg->tx_tbl_num, 2); + qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl_sec, + cfg->tx_tbl_num_sec, 2); } - qcom_qmp_phy_pcie_configure_lane(rx, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 1); - if (cfg->rx_tbl_sec) - qcom_qmp_phy_pcie_configure_lane(rx, cfg->regs, - cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); - - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_pcie_configure_lane(qphy->rx2, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 2); - if (cfg->rx_tbl_sec) - qcom_qmp_phy_pcie_configure_lane(qphy->rx2, cfg->regs, - cfg->rx_tbl_sec, - cfg->rx_tbl_num_sec, 2); + qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); + qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); + + if (cfg->lanes >= 2) { + qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl, + cfg->rx_tbl_num, 2); + qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl_sec, + cfg->rx_tbl_num_sec, 2); } - qcom_qmp_phy_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); - if (cfg->pcs_tbl_sec) - qcom_qmp_phy_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, - cfg->pcs_tbl_num_sec); + qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); + qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, cfg->pcs_tbl_num_sec); - qcom_qmp_phy_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, - cfg->pcs_misc_tbl_num); - if (cfg->pcs_misc_tbl_sec) - qcom_qmp_phy_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, - cfg->pcs_misc_tbl_num_sec); + qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, cfg->pcs_misc_tbl_num); + qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, cfg->pcs_misc_tbl_num_sec); /* * Pull out PHY from POWER DOWN state. @@ -2111,7 +2009,7 @@ err_disable_pipe_clk: return ret; } -static int qcom_qmp_phy_pcie_power_off(struct phy *phy) +static int qmp_pcie_power_off(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -2136,51 +2034,33 @@ static int qcom_qmp_phy_pcie_power_off(struct phy *phy) return 0; } -static int qcom_qmp_phy_pcie_exit(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - - qcom_qmp_phy_pcie_com_exit(qphy); - - return 0; -} - -static int qcom_qmp_phy_pcie_enable(struct phy *phy) +static int qmp_pcie_enable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_pcie_init(phy); + ret = qmp_pcie_init(phy); if (ret) return ret; - ret = qcom_qmp_phy_pcie_power_on(phy); + ret = qmp_pcie_power_on(phy); if (ret) - qcom_qmp_phy_pcie_exit(phy); + qmp_pcie_exit(phy); return ret; } -static int qcom_qmp_phy_pcie_disable(struct phy *phy) +static int qmp_pcie_disable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_pcie_power_off(phy); + ret = qmp_pcie_power_off(phy); if (ret) return ret; - return qcom_qmp_phy_pcie_exit(phy); -} - -static int qcom_qmp_phy_pcie_set_mode(struct phy *phy, - enum phy_mode mode, int submode) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - qphy->mode = mode; - - return 0; + return qmp_pcie_exit(phy); } -static int qcom_qmp_phy_pcie_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_vregs; @@ -2196,7 +2076,7 @@ static int qcom_qmp_phy_pcie_vreg_init(struct device *dev, const struct qmp_phy_ return devm_regulator_bulk_get(dev, num, qmp->vregs); } -static int qcom_qmp_phy_pcie_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int i; @@ -2217,7 +2097,7 @@ static int qcom_qmp_phy_pcie_reset_init(struct device *dev, const struct qmp_phy return 0; } -static int qcom_qmp_phy_pcie_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_pcie_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_clks; @@ -2300,21 +2180,18 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); } -static const struct phy_ops qcom_qmp_phy_pcie_ops = { - .power_on = qcom_qmp_phy_pcie_enable, - .power_off = qcom_qmp_phy_pcie_disable, - .set_mode = qcom_qmp_phy_pcie_set_mode, +static const struct phy_ops qmp_pcie_ops = { + .power_on = qmp_pcie_enable, + .power_off = qmp_pcie_disable, .owner = THIS_MODULE, }; -static -int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id, +static int qmp_pcie_create(struct device *dev, struct device_node *np, int id, void __iomem *serdes, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct phy *generic_phy; struct qmp_phy *qphy; - char prop_name[MAX_PROP_NAME]; int ret; qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); @@ -2329,59 +2206,51 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id, * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 * For single lane PHYs: pcs_misc (optional) -> 3. */ - qphy->tx = of_iomap(np, 0); - if (!qphy->tx) - return -ENOMEM; + qphy->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); - qphy->rx = of_iomap(np, 1); - if (!qphy->rx) - return -ENOMEM; + if (of_device_is_compatible(dev->of_node, "qcom,sdm845-qhp-pcie-phy")) + qphy->rx = qphy->tx; + else + qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); - qphy->pcs = of_iomap(np, 2); - if (!qphy->pcs) - return -ENOMEM; + qphy->pcs = devm_of_iomap(dev, np, 2, NULL); + if (IS_ERR(qphy->pcs)) + return PTR_ERR(qphy->pcs); - /* - * If this is a dual-lane PHY, then there should be registers for the - * second lane. Some old device trees did not specify this, so fall - * back to old legacy behavior of assuming they can be reached at an - * offset from the first lane. - */ - if (cfg->is_dual_lane_phy) { - qphy->tx2 = of_iomap(np, 3); - qphy->rx2 = of_iomap(np, 4); - if (!qphy->tx2 || !qphy->rx2) { - dev_warn(dev, - "Underspecified device tree, falling back to legacy register regions\n"); - - /* In the old version, pcs_misc is at index 3. */ - qphy->pcs_misc = qphy->tx2; - qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; - qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; - - } else { - qphy->pcs_misc = of_iomap(np, 5); - } + if (cfg->lanes >= 2) { + qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); + if (IS_ERR(qphy->tx2)) + return PTR_ERR(qphy->tx2); + qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); + if (IS_ERR(qphy->rx2)) + return PTR_ERR(qphy->rx2); + + qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); } else { - qphy->pcs_misc = of_iomap(np, 3); + qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); } - if (!qphy->pcs_misc && + if (IS_ERR(qphy->pcs_misc) && of_device_is_compatible(dev->of_node, "qcom,ipq6018-qmp-pcie-phy")) qphy->pcs_misc = qphy->pcs + 0x400; - if (!qphy->pcs_misc) - dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + if (IS_ERR(qphy->pcs_misc)) { + if (cfg->pcs_misc_tbl || cfg->pcs_misc_tbl_sec) + return PTR_ERR(qphy->pcs_misc); + } - snprintf(prop_name, sizeof(prop_name), "pipe%d", id); - qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); + qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); if (IS_ERR(qphy->pipe_clk)) { return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), "failed to get lane%d pipe clock\n", id); } - generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_ops); + generic_phy = devm_phy_create(dev, np, &qmp_pcie_ops); if (IS_ERR(generic_phy)) { ret = PTR_ERR(generic_phy); dev_err(dev, "failed to create qphy %d\n", ret); @@ -2389,7 +2258,6 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id, } qphy->phy = generic_phy; - qphy->index = id; qphy->qmp = qmp; qmp->phys[id] = qphy; phy_set_drvdata(generic_phy, qphy); @@ -2397,7 +2265,7 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id, return 0; } -static const struct of_device_id qcom_qmp_phy_pcie_of_match_table[] = { +static const struct of_device_id qmp_pcie_of_match_table[] = { { .compatible = "qcom,msm8998-qmp-pcie-phy", .data = &msm8998_pciephy_cfg, @@ -2440,9 +2308,9 @@ static const struct of_device_id qcom_qmp_phy_pcie_of_match_table[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_of_match_table); +MODULE_DEVICE_TABLE(of, qmp_pcie_of_match_table); -static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev) +static int qmp_pcie_probe(struct platform_device *pdev) { struct qcom_qmp *qmp; struct device *dev = &pdev->dev; @@ -2470,21 +2338,18 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev) if (IS_ERR(serdes)) return PTR_ERR(serdes); - ret = qcom_qmp_phy_pcie_clk_init(dev, cfg); + ret = qmp_pcie_clk_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_pcie_reset_init(dev, cfg); + ret = qmp_pcie_reset_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_pcie_vreg_init(dev, cfg); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + ret = qmp_pcie_vreg_init(dev, cfg); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); num = of_get_available_child_count(dev->of_node); /* do we have a rogue child node ? */ @@ -2495,18 +2360,10 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev) if (!qmp->phys) return -ENOMEM; - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - /* - * Prevent runtime pm from being ON by default. Users can enable - * it using power/control in sysfs. - */ - pm_runtime_forbid(dev); - id = 0; for_each_available_child_of_node(dev->of_node, child) { /* Create per-lane phy */ - ret = qcom_qmp_phy_pcie_create(dev, child, id, serdes, cfg); + ret = qmp_pcie_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -2528,28 +2385,23 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev) } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_info(dev, "Registered Qcom-QMP phy\n"); - else - pm_runtime_disable(dev); return PTR_ERR_OR_ZERO(phy_provider); err_node_put: - pm_runtime_disable(dev); of_node_put(child); return ret; } -static struct platform_driver qcom_qmp_phy_pcie_driver = { - .probe = qcom_qmp_phy_pcie_probe, +static struct platform_driver qmp_pcie_driver = { + .probe = qmp_pcie_probe, .driver = { .name = "qcom-qmp-pcie-phy", - .of_match_table = qcom_qmp_phy_pcie_of_match_table, + .of_match_table = qmp_pcie_of_match_table, }, }; -module_platform_driver(qcom_qmp_phy_pcie_driver); +module_platform_driver(qmp_pcie_driver); MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); MODULE_DESCRIPTION("Qualcomm QMP PCIe PHY driver"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5.h index 61a44519f969..04f260711ea1 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5.h @@ -7,11 +7,24 @@ #define QCOM_PHY_QMP_PCS_V5_H_ /* Only for QMP V5 PHY - USB/PCIe PCS registers */ +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG1 0x0c4 +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG2 0x0c8 +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG3 0x0cc +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG6 0x0d8 #define QPHY_V5_PCS_REFGEN_REQ_CONFIG1 0x0dc #define QPHY_V5_PCS_G3S2_PRE_GAIN 0x170 #define QPHY_V5_PCS_RX_SIGDET_LVL 0x188 +#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L 0x190 +#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H 0x194 #define QPHY_V5_PCS_RATE_SLEW_CNTRL1 0x198 +#define QPHY_V5_PCS_CDR_RESET_TIME 0x1b0 +#define QPHY_V5_PCS_RX_CONFIG 0x1b0 +#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG1 0x1c0 +#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG2 0x1c4 +#define QPHY_V5_PCS_PCS_TX_RX_CONFIG 0x1d0 +#define QPHY_V5_PCS_EQ_CONFIG1 0x1dc #define QPHY_V5_PCS_EQ_CONFIG2 0x1e0 #define QPHY_V5_PCS_EQ_CONFIG3 0x1e4 +#define QPHY_V5_PCS_EQ_CONFIG5 0x1ec #endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h new file mode 100644 index 000000000000..a1c088bd5158 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V5_5NM_H_ +#define QCOM_PHY_QMP_QSERDES_TXRX_V5_5NM_H_ + +/* Only for QMP V5 5NM PHY - TX registers */ +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX 0x30 +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX 0x34 +#define QSERDES_V5_5NM_TX_LANE_MODE_1 0x78 +#define QSERDES_V5_5NM_TX_LANE_MODE_2 0x7c +#define QSERDES_V5_5NM_TX_LANE_MODE_3 0x80 +#define QSERDES_V5_5NM_TX_BIST_MODE_LANENO 0x00 +#define QSERDES_V5_5NM_TX_BIST_INVERT 0x04 +#define QSERDES_V5_5NM_TX_CLKBUF_ENABLE 0x08 +#define QSERDES_V5_5NM_TX_TX_EMP_POST1_LVL 0x0c +#define QSERDES_V5_5NM_TX_TX_IDLE_LVL_LARGE_AMP 0x10 +#define QSERDES_V5_5NM_TX_TX_DRV_LVL 0x14 +#define QSERDES_V5_5NM_TX_TX_DRV_LVL_OFFSET 0x18 +#define QSERDES_V5_5NM_TX_RESET_TSYNC_EN 0x1c +#define QSERDES_V5_5NM_TX_PRE_STALL_LDO_BOOST_EN 0x20 +#define QSERDES_V5_5NM_TX_LPB_EN 0x24 +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_TX 0x28 +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_RX 0x2c +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX 0x30 +#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX 0x34 +#define QSERDES_V5_5NM_TX_PERL_LENGTH1 0x38 +#define QSERDES_V5_5NM_TX_PERL_LENGTH2 0x3c +#define QSERDES_V5_5NM_TX_SERDES_BYP_EN_OUT 0x40 +#define QSERDES_V5_5NM_TX_DEBUG_BUS_SEL 0x44 +#define QSERDES_V5_5NM_TX_TRANSCEIVER_BIAS_EN 0x48 +#define QSERDES_V5_5NM_TX_HIGHZ_DRVR_EN 0x4c +#define QSERDES_V5_5NM_TX_TX_POL_INV 0x50 +#define QSERDES_V5_5NM_TX_PARRATE_REC_DETECT_IDLE_EN 0x54 +#define QSERDES_V5_5NM_TX_BIST_PATTERN1 0x58 +#define QSERDES_V5_5NM_TX_BIST_PATTERN2 0x5c +#define QSERDES_V5_5NM_TX_BIST_PATTERN3 0x60 +#define QSERDES_V5_5NM_TX_BIST_PATTERN4 0x64 +#define QSERDES_V5_5NM_TX_BIST_PATTERN5 0x68 +#define QSERDES_V5_5NM_TX_BIST_PATTERN6 0x6c +#define QSERDES_V5_5NM_TX_BIST_PATTERN7 0x70 +#define QSERDES_V5_5NM_TX_BIST_PATTERN8 0x74 +#define QSERDES_V5_5NM_TX_LANE_MODE_1 0x78 +#define QSERDES_V5_5NM_TX_LANE_MODE_2 0x7c +#define QSERDES_V5_5NM_TX_LANE_MODE_3 0x80 +#define QSERDES_V5_5NM_TX_ATB_SEL1 0x84 +#define QSERDES_V5_5NM_TX_ATB_SEL2 0x88 +#define QSERDES_V5_5NM_TX_RCV_DETECT_LVL 0x8c +#define QSERDES_V5_5NM_TX_RCV_DETECT_LVL_2 0x90 +#define QSERDES_V5_5NM_TX_PRBS_SEED1 0x94 +#define QSERDES_V5_5NM_TX_PRBS_SEED2 0x98 +#define QSERDES_V5_5NM_TX_PRBS_SEED3 0x9c +#define QSERDES_V5_5NM_TX_PRBS_SEED4 0xa0 +#define QSERDES_V5_5NM_TX_RESET_GEN 0xa4 +#define QSERDES_V5_5NM_TX_RESET_GEN_MUXES 0xa8 +#define QSERDES_V5_5NM_TX_TRAN_DRVR_EMP_EN 0xac +#define QSERDES_V5_5NM_TX_VMODE_CTRL1 0xb0 +#define QSERDES_V5_5NM_TX_ALOG_OBSV_BUS_CTRL_1 0xb4 +#define QSERDES_V5_5NM_TX_BIST_STATUS 0xb8 +#define QSERDES_V5_5NM_TX_BIST_ERROR_COUNT1 0xbc +#define QSERDES_V5_5NM_TX_BIST_ERROR_COUNT2 0xc0 +#define QSERDES_V5_5NM_TX_ALOG_OBSV_BUS_STATUS_1 0xc4 +#define QSERDES_V5_5NM_TX_LANE_DIG_CONFIG 0xc8 +#define QSERDES_V5_5NM_TX_PI_QEC_CTRL 0xcc +#define QSERDES_V5_5NM_TX_PRE_EMPH 0xd0 +#define QSERDES_V5_5NM_TX_SW_RESET 0xd4 +#define QSERDES_V5_5NM_TX_TX_BAND 0xd8 +#define QSERDES_V5_5NM_TX_SLEW_CNTL0 0xdc +#define QSERDES_V5_5NM_TX_SLEW_CNTL1 0xe0 +#define QSERDES_V5_5NM_TX_INTERFACE_SELECT 0xe4 +#define QSERDES_V5_5NM_TX_DIG_BKUP_CTRL 0xe8 +#define QSERDES_V5_5NM_TX_DEBUG_BUS0 0xec +#define QSERDES_V5_5NM_TX_DEBUG_BUS1 0xf0 +#define QSERDES_V5_5NM_TX_DEBUG_BUS2 0xf4 +#define QSERDES_V5_5NM_TX_DEBUG_BUS3 0xf8 +#define QSERDES_V5_5NM_TX_TX_BKUP_RO_BUS 0xfc + +/* Only for QMP V5 5NM PHY - RX registers */ +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE0 0x000 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE1 0x004 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE2 0x008 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE3 0x00c +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE0 0x010 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE1 0x014 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE2 0x018 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE3 0x01c +#define QSERDES_V5_5NM_RX_UCDR_SO_SATURATION 0x020 +#define QSERDES_V5_5NM_RX_UCDR_FO_TO_SO_DELAY 0x024 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE0 0x028 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE0 0x02c +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE1 0x030 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE1 0x034 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE2 0x038 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE2 0x03c +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE3 0x040 +#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE3 0x044 +#define QSERDES_V5_5NM_RX_UCDR_PI_CTRL1 0x048 +#define QSERDES_V5_5NM_RX_UCDR_PI_CTRL2 0x04c +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE0 0x050 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE1 0x054 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE2 0x058 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE3 0x05c +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE0 0x060 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE1 0x064 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE2 0x068 +#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE3 0x06c +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE0 0x070 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE1 0x074 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE2 0x078 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE3 0x07c +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE0 0x080 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE1 0x084 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE2 0x088 +#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE3 0x08c +#define QSERDES_V5_5NM_RX_RXCLK_DIV2_CTRL 0x090 +#define QSERDES_V5_5NM_RX_RX_BAND 0x094 +#define QSERDES_V5_5NM_RX_RX_TERM_BW 0x098 +#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE0 0x09c +#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE1 0x0a0 +#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE2 0x0a4 +#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE3 0x0a8 +#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE0 0x0ac +#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE1 0x0b0 +#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE2 0x0b4 +#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE3 0x0b8 +#define QSERDES_V5_5NM_RX_UCDR_PI_CONTROLS 0x0bc +#define QSERDES_V5_5NM_RX_UCDR_PD_DATA_FILTER_ENABLES 0x0c0 +#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE0 0x0c4 +#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE1 0x0c8 +#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE2 0x0cc +#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3 0x0d0 +#define QSERDES_V5_5NM_RX_AUX_CONTROL 0x0d4 +#define QSERDES_V5_5NM_RX_AUXDATA_TB 0x0d8 +#define QSERDES_V5_5NM_RX_RCLK_AUXDATA_SEL 0x0dc +#define QSERDES_V5_5NM_RX_EOM_CTRL 0x0e0 +#define QSERDES_V5_5NM_RX_AC_JTAG_ENABLE 0x0e4 +#define QSERDES_V5_5NM_RX_AC_JTAG_INITP 0x0e8 +#define QSERDES_V5_5NM_RX_AC_JTAG_INITN 0x0ec +#define QSERDES_V5_5NM_RX_AC_JTAG_LVL 0x0f0 +#define QSERDES_V5_5NM_RX_AC_JTAG_MODE 0x0f4 +#define QSERDES_V5_5NM_RX_AC_JTAG_RESET 0x0f8 +#define QSERDES_V5_5NM_RX_RX_RCVR_IQ_EN 0x0fc +#define QSERDES_V5_5NM_RX_RX_Q_EN_RATES 0x100 +#define QSERDES_V5_5NM_RX_RX_IDAC_I0_DC_OFFSETS 0x104 +#define QSERDES_V5_5NM_RX_RX_IDAC_I0BAR_DC_OFFSETS 0x108 +#define QSERDES_V5_5NM_RX_RX_IDAC_I1_DC_OFFSETS 0x10c +#define QSERDES_V5_5NM_RX_RX_IDAC_I1BAR_DC_OFFSETS 0x110 +#define QSERDES_V5_5NM_RX_RX_IDAC_Q_DC_OFFSETS 0x114 +#define QSERDES_V5_5NM_RX_RX_IDAC_QBAR_DC_OFFSETS 0x118 +#define QSERDES_V5_5NM_RX_RX_IDAC_A_DC_OFFSETS 0x11c +#define QSERDES_V5_5NM_RX_RX_IDAC_ABAR_DC_OFFSETS 0x120 +#define QSERDES_V5_5NM_RX_RX_IDAC_EN 0x124 +#define QSERDES_V5_5NM_RX_RX_IDAC_ENABLES 0x128 +#define QSERDES_V5_5NM_RX_RX_IDAC_SIGN 0x12c +#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CODE_OVERRIDE 0x130 +#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CTRL1 0x134 +#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CTRL2 0x138 +#define QSERDES_V5_5NM_RX_RX_IVCM_POSTCAL_OFFSET 0x13c +#define QSERDES_V5_5NM_RX_RX_SUMMER_CAL_SPD_MODE 0x140 +#define QSERDES_V5_5NM_RX_RX_HIGHZ_PARRATE 0x144 +#define QSERDES_V5_5NM_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x148 +#define QSERDES_V5_5NM_RX_DFE_1 0x14c +#define QSERDES_V5_5NM_RX_DFE_2 0x150 +#define QSERDES_V5_5NM_RX_DFE_3 0x154 +#define QSERDES_V5_5NM_RX_DFE_4 0x158 +#define QSERDES_V5_5NM_RX_DFE_TAP3_CTRL 0x15c +#define QSERDES_V5_5NM_RX_DFE_TAP3_MANVAL_KTAP 0x160 +#define QSERDES_V5_5NM_RX_DFE_TAP4_CTRL 0x164 +#define QSERDES_V5_5NM_RX_DFE_TAP4_MANVAL_KTAP 0x168 +#define QSERDES_V5_5NM_RX_DFE_TAP5_CTRL 0x16c +#define QSERDES_V5_5NM_RX_DFE_TAP5_MANVAL_KTAP 0x170 +#define QSERDES_V5_5NM_RX_TX_ADPT_CTRL 0x174 +#define QSERDES_V5_5NM_RX_DFE_DAC_ENABLE1 0x178 +#define QSERDES_V5_5NM_RX_DFE_DAC_ENABLE2 0x17c +#define QSERDES_V5_5NM_RX_TX_ADAPT_PRE_THRESH1 0x180 +#define QSERDES_V5_5NM_RX_TX_ADAPT_PRE_THRESH2 0x184 +#define QSERDES_V5_5NM_RX_TX_ADAPT_POST_THRESH1 0x188 +#define QSERDES_V5_5NM_RX_TX_ADAPT_POST_THRESH2 0x18c +#define QSERDES_V5_5NM_RX_TX_ADAPT_MAIN_THRESH1 0x190 +#define QSERDES_V5_5NM_RX_TX_ADAPT_MAIN_THRESH2 0x194 +#define QSERDES_V5_5NM_RX_VGA_CAL_CNTRL1 0x198 +#define QSERDES_V5_5NM_RX_VGA_CAL_CNTRL2 0x19c +#define QSERDES_V5_5NM_RX_VGA_CAL_MAN_VAL 0x1a0 +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_CNTRL1 0x1a4 +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_CNTRL2 0x1a8 +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE0 0x1ac +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE1 0x1b0 +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE2 0x1b4 +#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE3 0x1b8 +#define QSERDES_V5_5NM_RX_GM_CAL 0x1bc +#define QSERDES_V5_5NM_RX_RX_VGA_GAIN2_BLK1 0x1c0 +#define QSERDES_V5_5NM_RX_RX_VGA_GAIN2_BLK2 0x1c4 +#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL2 0x1c8 +#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL3 0x1cc +#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL4 0x1d0 +#define QSERDES_V5_5NM_RX_RX_IDAC_TSETTLE_LOW 0x1d4 +#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_LSB 0x1d8 +#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_MSB 0x1dc +#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1e0 +#define QSERDES_V5_5NM_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x1e4 +#define QSERDES_V5_5NM_RX_SIGDET_ENABLES 0x1e8 +#define QSERDES_V5_5NM_RX_SIGDET_CNTRL 0x1ec +#define QSERDES_V5_5NM_RX_SIGDET_LVL 0x1f0 +#define QSERDES_V5_5NM_RX_SIGDET_DEGLITCH_CNTRL 0x1f4 +#define QSERDES_V5_5NM_RX_CDR_FREEZE_UP_DN 0x1f8 +#define QSERDES_V5_5NM_RX_CDR_RESET_OVERRIDE 0x1fc +#define QSERDES_V5_5NM_RX_RX_INTERFACE_MODE 0x200 +#define QSERDES_V5_5NM_RX_JITTER_GEN_MODE 0x204 +#define QSERDES_V5_5NM_RX_SJ_AMP1 0x208 +#define QSERDES_V5_5NM_RX_SJ_AMP2 0x20c +#define QSERDES_V5_5NM_RX_SJ_PER1 0x210 +#define QSERDES_V5_5NM_RX_SJ_PER2 0x214 +#define QSERDES_V5_5NM_RX_PPM_OFFSET1 0x218 +#define QSERDES_V5_5NM_RX_PPM_OFFSET2 0x21c +#define QSERDES_V5_5NM_RX_SIGN_PPM_PERIOD1 0x220 +#define QSERDES_V5_5NM_RX_SIGN_PPM_PERIOD2 0x224 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B0 0x228 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B1 0x22c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B2 0x230 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B3 0x234 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B4 0x238 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B5 0x23c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B6 0x240 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B7 0x244 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B0 0x248 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B1 0x24c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B2 0x250 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B3 0x254 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B4 0x258 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B5 0x25c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B6 0x260 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B7 0x264 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B0 0x268 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B1 0x26c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B2 0x270 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B3 0x274 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B4 0x278 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B5 0x27c +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B6 0x280 +#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B7 0x284 +#define QSERDES_V5_5NM_RX_PHPRE_CTRL 0x288 +#define QSERDES_V5_5NM_RX_PHPRE_INITVAL 0x28c +#define QSERDES_V5_5NM_RX_DFE_EN_TIMER 0x290 +#define QSERDES_V5_5NM_RX_DFE_CTLE_POST_CAL_OFFSET 0x294 +#define QSERDES_V5_5NM_RX_DCC_CTRL1 0x298 +#define QSERDES_V5_5NM_RX_DCC_CTRL2 0x29c +#define QSERDES_V5_5NM_RX_DCC_OFFSET 0x2a0 +#define QSERDES_V5_5NM_RX_DCC_CMUX_POSTCAL_OFFSET 0x2a4 +#define QSERDES_V5_5NM_RX_DCC_CMUX_CAL_CTRL1 0x2a8 +#define QSERDES_V5_5NM_RX_DCC_CMUX_CAL_CTRL2 0x2ac +#define QSERDES_V5_5NM_RX_ALOG_OBSV_BUS_CTRL_1 0x2b0 +#define QSERDES_V5_5NM_RX_RX_MARG_CTRL1 0x2b4 +#define QSERDES_V5_5NM_RX_RX_MARG_CTRL2 0x2b8 +#define QSERDES_V5_5NM_RX_RX_MARG_CTRL3 0x2bc +#define QSERDES_V5_5NM_RX_RX_MARG_CTRL_4 0x2c0 +#define QSERDES_V5_5NM_RX_RX_MARG_CFG_RATE_0_1 0x2c4 +#define QSERDES_V5_5NM_RX_RX_MARG_CFG_RATE_2_3 0x2c8 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_CTRL1 0x2cc +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_CTRL2 0x2d0 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH1_RATE210 0x2d4 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH1_RATE3 0x2d8 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH2_RATE210 0x2dc +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH2_RATE3 0x2e0 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH3_RATE210 0x2e4 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH3_RATE3 0x2e8 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH4_RATE210 0x2ec +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH4_RATE3 0x2f0 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH5_RATE210 0x2f4 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH5_RATE3 0x2f8 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH6_RATE210 0x2fc +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH6_RATE3 0x300 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH7_RATE210 0x304 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH7_RATE3 0x308 +#define QSERDES_V5_5NM_RX_Q_PI_INTRINSIC_BIAS_RATE10 0x30c +#define QSERDES_V5_5NM_RX_Q_PI_INTRINSIC_BIAS_RATE32 0x310 +#define QSERDES_V5_5NM_RX_RX_MARG_VERTICAL_CTRL 0x314 +#define QSERDES_V5_5NM_RX_RX_MARG_VERTICAL_CODE 0x318 +#define QSERDES_V5_5NM_RX_RES_CODE_THRESH_HIGH_AND_BYP 0x31c +#define QSERDES_V5_5NM_RX_RES_CODE_THRESH_LOW 0x320 +#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL1 0x324 +#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL2 0x328 +#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL3 0x32c +#define QSERDES_V5_5NM_RX_PI_CTRL1 0x330 +#define QSERDES_V5_5NM_RX_PI_CTRL2 0x334 +#define QSERDES_V5_5NM_RX_PI_QUAD 0x338 +#define QSERDES_V5_5NM_RX_QPI_CTRL1 0x33c +#define QSERDES_V5_5NM_RX_QPI_CTRL2 0x340 +#define QSERDES_V5_5NM_RX_QPI_QUAD 0x344 +#define QSERDES_V5_5NM_RX_IDATA1 0x348 +#define QSERDES_V5_5NM_RX_IDATA2 0x34c +#define QSERDES_V5_5NM_RX_IDATA3 0x350 +#define QSERDES_V5_5NM_RX_AC_JTAG_OUTP 0x354 +#define QSERDES_V5_5NM_RX_AC_JTAG_OUTN 0x358 +#define QSERDES_V5_5NM_RX_RX_SIGDET 0x35c +#define QSERDES_V5_5NM_RX_ALOG_OBSV_BUS_STATUS_1 0x360 +#define QSERDES_V5_5NM_RX_READ_EQCODE 0x364 +#define QSERDES_V5_5NM_RX_READ_OFFSETCODE 0x368 +#define QSERDES_V5_5NM_RX_IA_ERROR_COUNTER_LOW 0x36c +#define QSERDES_V5_5NM_RX_IA_ERROR_COUNTER_HIGH 0x370 +#define QSERDES_V5_5NM_RX_VGA_READ_CODE 0x374 +#define QSERDES_V5_5NM_RX_VTHRESH_READ_CODE 0x378 +#define QSERDES_V5_5NM_RX_DFE_TAP1_READ_CODE 0x37c +#define QSERDES_V5_5NM_RX_DFE_TAP2_READ_CODE 0x380 +#define QSERDES_V5_5NM_RX_DFE_TAP3_READ_CODE 0x384 +#define QSERDES_V5_5NM_RX_DFE_TAP4_READ_CODE 0x388 +#define QSERDES_V5_5NM_RX_DFE_TAP5_READ_CODE 0x38c +#define QSERDES_V5_5NM_RX_IDAC_STATUS_I0 0x390 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_I0BAR 0x394 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_I1 0x398 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_I1BAR 0x39c +#define QSERDES_V5_5NM_RX_IDAC_STATUS_Q 0x3a0 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_QBAR 0x3a4 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_A 0x3a8 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_ABAR 0x3ac +#define QSERDES_V5_5NM_RX_IDAC_STATUS_SM_ON 0x3b0 +#define QSERDES_V5_5NM_RX_IDAC_STATUS_SIGNERROR 0x3b4 +#define QSERDES_V5_5NM_RX_IVCM_CAL_STATUS 0x3b8 +#define QSERDES_V5_5NM_RX_IVCM_CAL_DEBUG_STATUS 0x3bc +#define QSERDES_V5_5NM_RX_DCC_CAL_STATUS 0x3c0 +#define QSERDES_V5_5NM_RX_DCC_READ_CODE_STATUS 0x3c4 +#define QSERDES_V5_5NM_RX_RX_MARG_DEBUG1_STATUS 0x3c8 +#define QSERDES_V5_5NM_RX_RX_MARG_DEBUG2_STATUS 0x3cc +#define QSERDES_V5_5NM_RX_RX_MARG_READ_CODE_STATUS 0x3d0 +#define QSERDES_V5_5NM_RX_EOM_ERR_CNT_LSB_STATUS 0x3d4 +#define QSERDES_V5_5NM_RX_EOM_ERR_CNT_MSB_STATUS 0x3d8 +#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_TUNE_STATUS 0x3dc +#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS1_STATUS 0x3e0 +#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS2_STATUS 0x3e4 +#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS3_STATUS 0x3e8 + +#endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c index c8583f5a54bd..c08d34ad1313 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c @@ -28,53 +28,15 @@ #define SW_RESET BIT(0) /* QPHY_POWER_DOWN_CONTROL */ #define SW_PWRDN BIT(0) -#define REFCLK_DRV_DSBL BIT(1) /* QPHY_START_CONTROL bits */ #define SERDES_START BIT(0) #define PCS_START BIT(1) -#define PLL_READY_GATE_EN BIT(3) /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) -#define PHYSTATUS_4_20 BIT(7) -/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ +/* QPHY_PCS_READY_STATUS bit */ #define PCS_READY BIT(0) -/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ -/* DP PHY soft reset */ -#define SW_DPPHY_RESET BIT(0) -/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ -#define SW_DPPHY_RESET_MUX BIT(1) -/* USB3 PHY soft reset */ -#define SW_USB3PHY_RESET BIT(2) -/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ -#define SW_USB3PHY_RESET_MUX BIT(3) - -/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ -#define USB3_MODE BIT(0) /* enables USB3 mode */ -#define DP_MODE BIT(1) /* enables DP mode */ - -/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ -#define ARCVR_DTCT_EN BIT(0) -#define ALFPS_DTCT_EN BIT(1) -#define ARCVR_DTCT_EVENT_SEL BIT(4) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ -#define IRQ_CLEAR BIT(0) - -/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ -#define RCVR_DETECT BIT(0) - -/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ -#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ - #define PHY_INIT_COMPLETE_TIMEOUT 10000 -#define POWER_DOWN_DELAY_US_MIN 10 -#define POWER_DOWN_DELAY_US_MAX 11 - -#define MAX_PROP_NAME 32 - -/* Define the assumed distance between lanes for underspecified device trees. */ -#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 struct qmp_phy_init_tbl { unsigned int offset; @@ -115,22 +77,11 @@ struct qmp_phy_init_tbl { /* set of registers with offsets different per-PHY */ enum qphy_reg_layout { - /* Common block control registers */ - QPHY_COM_SW_RESET, - QPHY_COM_POWER_DOWN_CONTROL, - QPHY_COM_START_CONTROL, - QPHY_COM_PCS_READY_STATUS, /* PCS registers */ QPHY_SW_RESET, QPHY_START_CTRL, QPHY_PCS_READY_STATUS, - QPHY_PCS_STATUS, - QPHY_PCS_AUTONOMOUS_MODE_CTRL, - QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, - QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, QPHY_PCS_POWER_DOWN_CONTROL, - /* PCS_MISC registers */ - QPHY_PCS_MISC_TYPEC_CTRL, /* Keep last to ensure regs_layout arrays are properly initialized */ QPHY_LAYOUT_SIZE }; @@ -580,14 +531,9 @@ static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), }; -struct qmp_phy; - /* struct qmp_phy_cfg - per-PHY initialization config */ struct qmp_phy_cfg { - /* phy-type - PCIE/UFS/USB */ - unsigned int type; - /* number of lanes provided by phy */ - int nlanes; + int lanes; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; @@ -614,9 +560,6 @@ struct qmp_phy_cfg { /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ unsigned int phy_status; - /* true, if PHY has secondary tx/rx lanes to be configured */ - bool is_dual_lane_phy; - /* true, if PCS block has no separate SW_RESET register */ bool no_pcs_sw_reset; }; @@ -633,9 +576,7 @@ struct qmp_phy_cfg { * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) * @pcs_misc: iomapped memory space for lane's pcs_misc - * @index: lane index * @qmp: QMP phy to which this lane belongs - * @mode: current PHY mode */ struct qmp_phy { struct phy *phy; @@ -647,9 +588,7 @@ struct qmp_phy { void __iomem *tx2; void __iomem *rx2; void __iomem *pcs_misc; - unsigned int index; struct qcom_qmp *qmp; - enum phy_mode mode; }; /** @@ -719,8 +658,7 @@ static const char * const qmp_phy_vreg_l[] = { }; static const struct qmp_phy_cfg msm8996_ufs_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 1, + .lanes = 1, .serdes_tbl = msm8996_ufs_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), @@ -745,8 +683,7 @@ static const struct qmp_phy_cfg msm8996_ufs_cfg = { }; static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sdm845_ufsphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), @@ -766,13 +703,11 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - .is_dual_lane_phy = true, .no_pcs_sw_reset = true, }; static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm6115_ufsphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), @@ -795,8 +730,7 @@ static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { }; static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sm8150_ufsphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), @@ -815,13 +749,10 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sm8350_ufsphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), @@ -840,13 +771,10 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { - .type = PHY_TYPE_UFS, - .nlanes = 2, + .lanes = 2, .serdes_tbl = sm8350_ufsphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), @@ -865,11 +793,9 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - - .is_dual_lane_phy = true, }; -static void qcom_qmp_phy_ufs_configure_lane(void __iomem *base, +static void qmp_ufs_configure_lane(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num, @@ -892,27 +818,27 @@ static void qcom_qmp_phy_ufs_configure_lane(void __iomem *base, } } -static void qcom_qmp_phy_ufs_configure(void __iomem *base, +static void qmp_ufs_configure(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num) { - qcom_qmp_phy_ufs_configure_lane(base, regs, tbl, num, 0xff); + qmp_ufs_configure_lane(base, regs, tbl, num, 0xff); } -static int qcom_qmp_phy_ufs_serdes_init(struct qmp_phy *qphy) +static int qmp_ufs_serdes_init(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *serdes = qphy->serdes; const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; int serdes_tbl_num = cfg->serdes_tbl_num; - qcom_qmp_phy_ufs_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); + qmp_ufs_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); return 0; } -static int qcom_qmp_phy_ufs_com_init(struct qmp_phy *qphy) +static int qmp_ufs_com_init(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -946,7 +872,7 @@ err_disable_regulators: return ret; } -static int qcom_qmp_phy_ufs_com_exit(struct qmp_phy *qphy) +static int qmp_ufs_com_exit(struct qmp_phy *qphy) { struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -960,7 +886,7 @@ static int qcom_qmp_phy_ufs_com_exit(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_ufs_init(struct phy *phy) +static int qmp_ufs_init(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -995,14 +921,14 @@ static int qcom_qmp_phy_ufs_init(struct phy *phy) return ret; } - ret = qcom_qmp_phy_ufs_com_init(qphy); + ret = qmp_ufs_com_init(qphy); if (ret) return ret; return 0; } -static int qcom_qmp_phy_ufs_power_on(struct phy *phy) +static int qmp_ufs_power_on(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -1014,27 +940,24 @@ static int qcom_qmp_phy_ufs_power_on(struct phy *phy) unsigned int mask, val, ready; int ret; - qcom_qmp_phy_ufs_serdes_init(qphy); + qmp_ufs_serdes_init(qphy); /* Tx, Rx, and PCS configurations */ - qcom_qmp_phy_ufs_configure_lane(tx, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 1); + qmp_ufs_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); - /* Configuration for other LANE for USB-DP combo PHY */ - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_ufs_configure_lane(qphy->tx2, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_ufs_configure_lane(qphy->tx2, cfg->regs, + cfg->tx_tbl, cfg->tx_tbl_num, 2); } - qcom_qmp_phy_ufs_configure_lane(rx, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 1); + qmp_ufs_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_ufs_configure_lane(qphy->rx2, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_ufs_configure_lane(qphy->rx2, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 2); } - qcom_qmp_phy_ufs_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); + qmp_ufs_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ret = reset_control_deassert(qmp->ufs_reset); if (ret) @@ -1060,7 +983,7 @@ static int qcom_qmp_phy_ufs_power_on(struct phy *phy) return 0; } -static int qcom_qmp_phy_ufs_power_off(struct phy *phy) +static int qmp_ufs_power_off(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -1084,51 +1007,41 @@ static int qcom_qmp_phy_ufs_power_off(struct phy *phy) return 0; } -static int qcom_qmp_phy_ufs_exit(struct phy *phy) +static int qmp_ufs_exit(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); - qcom_qmp_phy_ufs_com_exit(qphy); + qmp_ufs_com_exit(qphy); return 0; } -static int qcom_qmp_phy_ufs_enable(struct phy *phy) +static int qmp_ufs_enable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_ufs_init(phy); + ret = qmp_ufs_init(phy); if (ret) return ret; - ret = qcom_qmp_phy_ufs_power_on(phy); + ret = qmp_ufs_power_on(phy); if (ret) - qcom_qmp_phy_ufs_exit(phy); + qmp_ufs_exit(phy); return ret; } -static int qcom_qmp_phy_ufs_disable(struct phy *phy) +static int qmp_ufs_disable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_ufs_power_off(phy); + ret = qmp_ufs_power_off(phy); if (ret) return ret; - return qcom_qmp_phy_ufs_exit(phy); + return qmp_ufs_exit(phy); } -static int qcom_qmp_phy_ufs_set_mode(struct phy *phy, - enum phy_mode mode, int submode) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - - qphy->mode = mode; - - return 0; -} - -static int qcom_qmp_phy_ufs_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_ufs_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_vregs; @@ -1144,7 +1057,7 @@ static int qcom_qmp_phy_ufs_vreg_init(struct device *dev, const struct qmp_phy_c return devm_regulator_bulk_get(dev, num, qmp->vregs); } -static int qcom_qmp_phy_ufs_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_ufs_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_clks; @@ -1161,14 +1074,12 @@ static int qcom_qmp_phy_ufs_clk_init(struct device *dev, const struct qmp_phy_cf } static const struct phy_ops qcom_qmp_ufs_ops = { - .power_on = qcom_qmp_phy_ufs_enable, - .power_off = qcom_qmp_phy_ufs_disable, - .set_mode = qcom_qmp_phy_ufs_set_mode, + .power_on = qmp_ufs_enable, + .power_off = qmp_ufs_disable, .owner = THIS_MODULE, }; -static -int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id, +static int qmp_ufs_create(struct device *dev, struct device_node *np, int id, void __iomem *serdes, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); @@ -1188,45 +1099,33 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id, * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 * For single lane PHYs: pcs_misc (optional) -> 3. */ - qphy->tx = of_iomap(np, 0); - if (!qphy->tx) - return -ENOMEM; + qphy->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); - qphy->rx = of_iomap(np, 1); - if (!qphy->rx) - return -ENOMEM; + qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); - qphy->pcs = of_iomap(np, 2); - if (!qphy->pcs) - return -ENOMEM; + qphy->pcs = devm_of_iomap(dev, np, 2, NULL); + if (IS_ERR(qphy->pcs)) + return PTR_ERR(qphy->pcs); - /* - * If this is a dual-lane PHY, then there should be registers for the - * second lane. Some old device trees did not specify this, so fall - * back to old legacy behavior of assuming they can be reached at an - * offset from the first lane. - */ - if (cfg->is_dual_lane_phy) { - qphy->tx2 = of_iomap(np, 3); - qphy->rx2 = of_iomap(np, 4); - if (!qphy->tx2 || !qphy->rx2) { - dev_warn(dev, - "Underspecified device tree, falling back to legacy register regions\n"); - - /* In the old version, pcs_misc is at index 3. */ - qphy->pcs_misc = qphy->tx2; - qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; - qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; - - } else { - qphy->pcs_misc = of_iomap(np, 5); - } + if (cfg->lanes >= 2) { + qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); + if (IS_ERR(qphy->tx2)) + return PTR_ERR(qphy->tx2); + + qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); + if (IS_ERR(qphy->rx2)) + return PTR_ERR(qphy->rx2); + qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); } else { - qphy->pcs_misc = of_iomap(np, 3); + qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); } - if (!qphy->pcs_misc) + if (IS_ERR(qphy->pcs_misc)) dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); generic_phy = devm_phy_create(dev, np, &qcom_qmp_ufs_ops); @@ -1237,7 +1136,6 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id, } qphy->phy = generic_phy; - qphy->index = id; qphy->qmp = qmp; qmp->phys[id] = qphy; phy_set_drvdata(generic_phy, qphy); @@ -1245,7 +1143,7 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id, return 0; } -static const struct of_device_id qcom_qmp_phy_ufs_of_match_table[] = { +static const struct of_device_id qmp_ufs_of_match_table[] = { { .compatible = "qcom,msm8996-qmp-ufs-phy", .data = &msm8996_ufs_cfg, @@ -1282,9 +1180,9 @@ static const struct of_device_id qcom_qmp_phy_ufs_of_match_table[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, qcom_qmp_phy_ufs_of_match_table); +MODULE_DEVICE_TABLE(of, qmp_ufs_of_match_table); -static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev) +static int qmp_ufs_probe(struct platform_device *pdev) { struct qcom_qmp *qmp; struct device *dev = &pdev->dev; @@ -1312,17 +1210,14 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev) if (IS_ERR(serdes)) return PTR_ERR(serdes); - ret = qcom_qmp_phy_ufs_clk_init(dev, cfg); + ret = qmp_ufs_clk_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_ufs_vreg_init(dev, cfg); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + ret = qmp_ufs_vreg_init(dev, cfg); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); num = of_get_available_child_count(dev->of_node); /* do we have a rogue child node ? */ @@ -1333,18 +1228,10 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev) if (!qmp->phys) return -ENOMEM; - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - /* - * Prevent runtime pm from being ON by default. Users can enable - * it using power/control in sysfs. - */ - pm_runtime_forbid(dev); - id = 0; for_each_available_child_of_node(dev->of_node, child) { /* Create per-lane phy */ - ret = qcom_qmp_phy_ufs_create(dev, child, id, serdes, cfg); + ret = qmp_ufs_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -1355,28 +1242,23 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev) } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_info(dev, "Registered Qcom-QMP phy\n"); - else - pm_runtime_disable(dev); return PTR_ERR_OR_ZERO(phy_provider); err_node_put: - pm_runtime_disable(dev); of_node_put(child); return ret; } -static struct platform_driver qcom_qmp_phy_ufs_driver = { - .probe = qcom_qmp_phy_ufs_probe, +static struct platform_driver qmp_ufs_driver = { + .probe = qmp_ufs_probe, .driver = { .name = "qcom-qmp-ufs-phy", - .of_match_table = qcom_qmp_phy_ufs_of_match_table, + .of_match_table = qmp_ufs_of_match_table, }, }; -module_platform_driver(qcom_qmp_phy_ufs_driver); +module_platform_driver(qmp_ufs_driver); MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); MODULE_DESCRIPTION("Qualcomm QMP UFS PHY driver"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index 1d270356a97f..b84c0d4b5754 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -28,16 +28,11 @@ #define SW_RESET BIT(0) /* QPHY_POWER_DOWN_CONTROL */ #define SW_PWRDN BIT(0) -#define REFCLK_DRV_DSBL BIT(1) /* QPHY_START_CONTROL bits */ #define SERDES_START BIT(0) #define PCS_START BIT(1) -#define PLL_READY_GATE_EN BIT(3) /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) -#define PHYSTATUS_4_20 BIT(7) -/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ -#define PCS_READY BIT(0) /* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ /* DP PHY soft reset */ @@ -71,11 +66,6 @@ #define POWER_DOWN_DELAY_US_MIN 10 #define POWER_DOWN_DELAY_US_MAX 11 -#define MAX_PROP_NAME 32 - -/* Define the assumed distance between lanes for underspecified device trees. */ -#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 - struct qmp_phy_init_tbl { unsigned int offset; unsigned int val; @@ -115,15 +105,9 @@ struct qmp_phy_init_tbl { /* set of registers with offsets different per-PHY */ enum qphy_reg_layout { - /* Common block control registers */ - QPHY_COM_SW_RESET, - QPHY_COM_POWER_DOWN_CONTROL, - QPHY_COM_START_CONTROL, - QPHY_COM_PCS_READY_STATUS, /* PCS registers */ QPHY_SW_RESET, QPHY_START_CTRL, - QPHY_PCS_READY_STATUS, QPHY_PCS_STATUS, QPHY_PCS_AUTONOMOUS_MODE_CTRL, QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, @@ -1338,14 +1322,114 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), }; -struct qmp_phy; +static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), +}; + +static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xd0), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), +}; /* struct qmp_phy_cfg - per-PHY initialization config */ struct qmp_phy_cfg { - /* phy-type - PCIE/UFS/USB */ - unsigned int type; - /* number of lanes provided by phy */ - int nlanes; + int lanes; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; @@ -1385,8 +1469,6 @@ struct qmp_phy_cfg { /* true, if PHY has a separate DP_COM control block */ bool has_phy_dp_com_ctrl; - /* true, if PHY has secondary tx/rx lanes to be configured */ - bool is_dual_lane_phy; /* Offset from PCS to PCS_USB region */ unsigned int pcs_usb_offset; @@ -1406,7 +1488,6 @@ struct qmp_phy_cfg { * @pcs_misc: iomapped memory space for lane's pcs_misc * @pcs_usb: iomapped memory space for lane's pcs_usb * @pipe_clk: pipe clock - * @index: lane index * @qmp: QMP phy to which this lane belongs * @mode: current PHY mode */ @@ -1422,7 +1503,6 @@ struct qmp_phy { void __iomem *pcs_misc; void __iomem *pcs_usb; struct clk *pipe_clk; - unsigned int index; struct qcom_qmp *qmp; enum phy_mode mode; }; @@ -1520,8 +1600,7 @@ static const char * const qmp_phy_vreg_l[] = { }; static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = ipq8074_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), @@ -1545,8 +1624,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { }; static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = msm8996_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), @@ -1570,8 +1648,7 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { }; static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v3_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), @@ -1598,12 +1675,10 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qmp_v3_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), @@ -1630,12 +1705,38 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, +}; + +static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = { + .lanes = 1, + + .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl), + .tx_tbl = sc8280xp_usb3_uniphy_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl), + .rx_tbl = sc8280xp_usb3_uniphy_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), + .pcs_tbl = sc8280xp_usb3_uniphy_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_pcs_tbl), + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = msm8996_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v4_usb3phy_regs_layout, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, }; static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), @@ -1663,8 +1764,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = msm8998_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), @@ -1685,13 +1785,10 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = sm8150_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), @@ -1722,12 +1819,10 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), @@ -1758,8 +1853,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = sm8150_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), @@ -1789,12 +1883,10 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), @@ -1825,8 +1917,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), @@ -1857,8 +1948,7 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), @@ -1889,8 +1979,7 @@ static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = sm8150_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), @@ -1920,12 +2009,10 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, .has_phy_dp_com_ctrl = true, - .is_dual_lane_phy = true, }; static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 1, .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), @@ -1956,8 +2043,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { }; static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { - .type = PHY_TYPE_USB3, - .nlanes = 1, + .lanes = 2, .serdes_tbl = qcm2290_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), @@ -1978,11 +2064,9 @@ static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, .phy_status = PHYSTATUS, - - .is_dual_lane_phy = true, }; -static void qcom_qmp_phy_usb_configure_lane(void __iomem *base, +static void qmp_usb_configure_lane(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num, @@ -2005,28 +2089,29 @@ static void qcom_qmp_phy_usb_configure_lane(void __iomem *base, } } -static void qcom_qmp_phy_usb_configure(void __iomem *base, +static void qmp_usb_configure(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], int num) { - qcom_qmp_phy_usb_configure_lane(base, regs, tbl, num, 0xff); + qmp_usb_configure_lane(base, regs, tbl, num, 0xff); } -static int qcom_qmp_phy_usb_serdes_init(struct qmp_phy *qphy) +static int qmp_usb_serdes_init(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *serdes = qphy->serdes; const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; int serdes_tbl_num = cfg->serdes_tbl_num; - qcom_qmp_phy_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); + qmp_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); return 0; } -static int qcom_qmp_phy_usb_com_init(struct qmp_phy *qphy) +static int qmp_usb_init(struct phy *phy) { + struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs = qphy->pcs; @@ -2097,8 +2182,9 @@ err_disable_regulators: return ret; } -static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy) +static int qmp_usb_exit(struct phy *phy) { + struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -2111,21 +2197,7 @@ static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy) return 0; } -static int qcom_qmp_phy_usb_init(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - struct qcom_qmp *qmp = qphy->qmp; - int ret; - dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - - ret = qcom_qmp_phy_usb_com_init(qphy); - if (ret) - return ret; - - return 0; -} - -static int qcom_qmp_phy_usb_power_on(struct phy *phy) +static int qmp_usb_power_on(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; @@ -2137,7 +2209,7 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) unsigned int mask, val, ready; int ret; - qcom_qmp_phy_usb_serdes_init(qphy); + qmp_usb_serdes_init(qphy); ret = clk_prepare_enable(qphy->pipe_clk); if (ret) { @@ -2146,25 +2218,22 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) } /* Tx, Rx, and PCS configurations */ - qcom_qmp_phy_usb_configure_lane(tx, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 1); + qmp_usb_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); - /* Configuration for other LANE for USB-DP combo PHY */ - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_usb_configure_lane(qphy->tx2, cfg->regs, - cfg->tx_tbl, cfg->tx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_usb_configure_lane(qphy->tx2, cfg->regs, + cfg->tx_tbl, cfg->tx_tbl_num, 2); } - qcom_qmp_phy_usb_configure_lane(rx, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 1); + qmp_usb_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); - if (cfg->is_dual_lane_phy) { - qcom_qmp_phy_usb_configure_lane(qphy->rx2, cfg->regs, - cfg->rx_tbl, cfg->rx_tbl_num, 2); + if (cfg->lanes >= 2) { + qmp_usb_configure_lane(qphy->rx2, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 2); } /* Configure link rate, swing, etc. */ - qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); + qmp_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); if (cfg->has_pwrdn_delay) usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); @@ -2194,7 +2263,7 @@ err_disable_pipe_clk: return ret; } -static int qcom_qmp_phy_usb_power_off(struct phy *phy) +static int qmp_usb_power_off(struct phy *phy) { struct qmp_phy *qphy = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qphy->cfg; @@ -2219,42 +2288,32 @@ static int qcom_qmp_phy_usb_power_off(struct phy *phy) return 0; } -static int qcom_qmp_phy_usb_exit(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - - qcom_qmp_phy_usb_com_exit(qphy); - - return 0; -} - -static int qcom_qmp_phy_usb_enable(struct phy *phy) +static int qmp_usb_enable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_usb_init(phy); + ret = qmp_usb_init(phy); if (ret) return ret; - ret = qcom_qmp_phy_usb_power_on(phy); + ret = qmp_usb_power_on(phy); if (ret) - qcom_qmp_phy_usb_exit(phy); + qmp_usb_exit(phy); return ret; } -static int qcom_qmp_phy_usb_disable(struct phy *phy) +static int qmp_usb_disable(struct phy *phy) { int ret; - ret = qcom_qmp_phy_usb_power_off(phy); + ret = qmp_usb_power_off(phy); if (ret) return ret; - return qcom_qmp_phy_usb_exit(phy); + return qmp_usb_exit(phy); } -static int qcom_qmp_phy_usb_set_mode(struct phy *phy, - enum phy_mode mode, int submode) +static int qmp_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct qmp_phy *qphy = phy_get_drvdata(phy); @@ -2263,7 +2322,7 @@ static int qcom_qmp_phy_usb_set_mode(struct phy *phy, return 0; } -static void qcom_qmp_phy_usb_enable_autonomous_mode(struct qmp_phy *qphy) +static void qmp_usb_enable_autonomous_mode(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; @@ -2292,7 +2351,7 @@ static void qcom_qmp_phy_usb_enable_autonomous_mode(struct qmp_phy *qphy) qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); } -static void qcom_qmp_phy_usb_disable_autonomous_mode(struct qmp_phy *qphy) +static void qmp_usb_disable_autonomous_mode(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; @@ -2310,7 +2369,7 @@ static void qcom_qmp_phy_usb_disable_autonomous_mode(struct qmp_phy *qphy) qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); } -static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev) +static int __maybe_unused qmp_usb_runtime_suspend(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct qmp_phy *qphy = qmp->phys[0]; @@ -2318,16 +2377,12 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev) dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); - /* Supported only for USB3 PHY and luckily USB3 is the first phy */ - if (cfg->type != PHY_TYPE_USB3) - return 0; - if (!qphy->phy->init_count) { dev_vdbg(dev, "PHY not initialized, bailing out\n"); return 0; } - qcom_qmp_phy_usb_enable_autonomous_mode(qphy); + qmp_usb_enable_autonomous_mode(qphy); clk_disable_unprepare(qphy->pipe_clk); clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); @@ -2335,7 +2390,7 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev) +static int __maybe_unused qmp_usb_runtime_resume(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct qmp_phy *qphy = qmp->phys[0]; @@ -2344,10 +2399,6 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev) dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); - /* Supported only for USB3 PHY and luckily USB3 is the first phy */ - if (cfg->type != PHY_TYPE_USB3) - return 0; - if (!qphy->phy->init_count) { dev_vdbg(dev, "PHY not initialized, bailing out\n"); return 0; @@ -2364,12 +2415,12 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev) return ret; } - qcom_qmp_phy_usb_disable_autonomous_mode(qphy); + qmp_usb_disable_autonomous_mode(qphy); return 0; } -static int qcom_qmp_phy_usb_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_usb_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_vregs; @@ -2385,7 +2436,7 @@ static int qcom_qmp_phy_usb_vreg_init(struct device *dev, const struct qmp_phy_c return devm_regulator_bulk_get(dev, num, qmp->vregs); } -static int qcom_qmp_phy_usb_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_usb_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int i; @@ -2406,7 +2457,7 @@ static int qcom_qmp_phy_usb_reset_init(struct device *dev, const struct qmp_phy_ return 0; } -static int qcom_qmp_phy_usb_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) +static int qmp_usb_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); int num = cfg->num_clks; @@ -2482,23 +2533,47 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); } -static const struct phy_ops qcom_qmp_phy_usb_ops = { - .init = qcom_qmp_phy_usb_enable, - .exit = qcom_qmp_phy_usb_disable, - .set_mode = qcom_qmp_phy_usb_set_mode, +static const struct phy_ops qmp_usb_ops = { + .init = qmp_usb_enable, + .exit = qmp_usb_disable, + .set_mode = qmp_usb_set_mode, .owner = THIS_MODULE, }; +static void __iomem *qmp_usb_iomap(struct device *dev, struct device_node *np, + int index, bool exclusive) +{ + struct resource res; + + if (!exclusive) { + if (of_address_to_resource(np, index, &res)) + return IOMEM_ERR_PTR(-EINVAL); + + return devm_ioremap(dev, res.start, resource_size(&res)); + } + + return devm_of_iomap(dev, np, index, NULL); +} + static -int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, +int qmp_usb_create(struct device *dev, struct device_node *np, int id, void __iomem *serdes, const struct qmp_phy_cfg *cfg) { struct qcom_qmp *qmp = dev_get_drvdata(dev); struct phy *generic_phy; struct qmp_phy *qphy; - char prop_name[MAX_PROP_NAME]; + bool exclusive = true; int ret; + /* + * FIXME: These bindings should be fixed to not rely on overlapping + * mappings for PCS. + */ + if (of_device_is_compatible(dev->of_node, "qcom,sdx65-qmp-usb3-uni-phy")) + exclusive = false; + if (of_device_is_compatible(dev->of_node, "qcom,sm8350-qmp-usb3-uni-phy")) + exclusive = false; + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); if (!qphy) return -ENOMEM; @@ -2511,58 +2586,47 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 * For single lane PHYs: pcs_misc (optional) -> 3. */ - qphy->tx = of_iomap(np, 0); - if (!qphy->tx) - return -ENOMEM; + qphy->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); - qphy->rx = of_iomap(np, 1); - if (!qphy->rx) - return -ENOMEM; + qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); - qphy->pcs = of_iomap(np, 2); - if (!qphy->pcs) - return -ENOMEM; + qphy->pcs = qmp_usb_iomap(dev, np, 2, exclusive); + if (IS_ERR(qphy->pcs)) + return PTR_ERR(qphy->pcs); if (cfg->pcs_usb_offset) qphy->pcs_usb = qphy->pcs + cfg->pcs_usb_offset; - /* - * If this is a dual-lane PHY, then there should be registers for the - * second lane. Some old device trees did not specify this, so fall - * back to old legacy behavior of assuming they can be reached at an - * offset from the first lane. - */ - if (cfg->is_dual_lane_phy) { - qphy->tx2 = of_iomap(np, 3); - qphy->rx2 = of_iomap(np, 4); - if (!qphy->tx2 || !qphy->rx2) { - dev_warn(dev, - "Underspecified device tree, falling back to legacy register regions\n"); - - /* In the old version, pcs_misc is at index 3. */ - qphy->pcs_misc = qphy->tx2; - qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; - qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; - - } else { - qphy->pcs_misc = of_iomap(np, 5); - } + if (cfg->lanes >= 2) { + qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); + if (IS_ERR(qphy->tx2)) + return PTR_ERR(qphy->tx2); + qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); + if (IS_ERR(qphy->rx2)) + return PTR_ERR(qphy->rx2); + + qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); } else { - qphy->pcs_misc = of_iomap(np, 3); + qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); } - if (!qphy->pcs_misc) + if (IS_ERR(qphy->pcs_misc)) { dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + qphy->pcs_misc = NULL; + } - snprintf(prop_name, sizeof(prop_name), "pipe%d", id); - qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); + qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); if (IS_ERR(qphy->pipe_clk)) { return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), "failed to get lane%d pipe clock\n", id); } - generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_usb_ops); + generic_phy = devm_phy_create(dev, np, &qmp_usb_ops); if (IS_ERR(generic_phy)) { ret = PTR_ERR(generic_phy); dev_err(dev, "failed to create qphy %d\n", ret); @@ -2570,7 +2634,6 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, } qphy->phy = generic_phy; - qphy->index = id; qphy->qmp = qmp; qmp->phys[id] = qphy; phy_set_drvdata(generic_phy, qphy); @@ -2578,7 +2641,7 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, return 0; } -static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = { +static const struct of_device_id qmp_usb_of_match_table[] = { { .compatible = "qcom,ipq8074-qmp-usb3-phy", .data = &ipq8074_usb3phy_cfg, @@ -2595,6 +2658,9 @@ static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = { .compatible = "qcom,sc8180x-qmp-usb3-phy", .data = &sm8150_usb3phy_cfg, }, { + .compatible = "qcom,sc8280xp-qmp-usb3-uni-phy", + .data = &sc8280xp_usb3_uniphy_cfg, + }, { .compatible = "qcom,sdm845-qmp-usb3-phy", .data = &qmp_v3_usb3phy_cfg, }, { @@ -2636,14 +2702,14 @@ static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, qcom_qmp_phy_usb_of_match_table); +MODULE_DEVICE_TABLE(of, qmp_usb_of_match_table); -static const struct dev_pm_ops qcom_qmp_phy_usb_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_qmp_phy_usb_runtime_suspend, - qcom_qmp_phy_usb_runtime_resume, NULL) +static const struct dev_pm_ops qmp_usb_pm_ops = { + SET_RUNTIME_PM_OPS(qmp_usb_runtime_suspend, + qmp_usb_runtime_resume, NULL) }; -static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) +static int qmp_usb_probe(struct platform_device *pdev) { struct qcom_qmp *qmp; struct device *dev = &pdev->dev; @@ -2678,21 +2744,18 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) return PTR_ERR(qmp->dp_com); } - ret = qcom_qmp_phy_usb_clk_init(dev, cfg); + ret = qmp_usb_clk_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_usb_reset_init(dev, cfg); + ret = qmp_usb_reset_init(dev, cfg); if (ret) return ret; - ret = qcom_qmp_phy_usb_vreg_init(dev, cfg); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + ret = qmp_usb_vreg_init(dev, cfg); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); num = of_get_available_child_count(dev->of_node); /* do we have a rogue child node ? */ @@ -2704,7 +2767,9 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) return -ENOMEM; pm_runtime_set_active(dev); - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; /* * Prevent runtime pm from being ON by default. Users can enable * it using power/control in sysfs. @@ -2714,7 +2779,7 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) id = 0; for_each_available_child_of_node(dev->of_node, child) { /* Create per-lane phy */ - ret = qcom_qmp_phy_usb_create(dev, child, id, serdes, cfg); + ret = qmp_usb_create(dev, child, id, serdes, cfg); if (ret) { dev_err(dev, "failed to create lane%d phy, %d\n", id, ret); @@ -2736,29 +2801,24 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_info(dev, "Registered Qcom-QMP phy\n"); - else - pm_runtime_disable(dev); return PTR_ERR_OR_ZERO(phy_provider); err_node_put: - pm_runtime_disable(dev); of_node_put(child); return ret; } -static struct platform_driver qcom_qmp_phy_usb_driver = { - .probe = qcom_qmp_phy_usb_probe, +static struct platform_driver qmp_usb_driver = { + .probe = qmp_usb_probe, .driver = { .name = "qcom-qmp-usb-phy", - .pm = &qcom_qmp_phy_usb_pm_ops, - .of_match_table = qcom_qmp_phy_usb_of_match_table, + .pm = &qmp_usb_pm_ops, + .of_match_table = qmp_usb_of_match_table, }, }; -module_platform_driver(qcom_qmp_phy_usb_driver); +module_platform_driver(qmp_usb_driver); MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); MODULE_DESCRIPTION("Qualcomm QMP USB PHY driver"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index b139c8af5e8b..26274e3c0cf9 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -19,6 +19,7 @@ #include "phy-qcom-qmp-qserdes-com-v5.h" #include "phy-qcom-qmp-qserdes-txrx-v5.h" #include "phy-qcom-qmp-qserdes-txrx-v5_20.h" +#include "phy-qcom-qmp-qserdes-txrx-v5_5nm.h" #include "phy-qcom-qmp-qserdes-pll.h" diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 7529a7e6e5df..2ef638b32e8f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -973,20 +973,14 @@ static int qusb2_phy_probe(struct platform_device *pdev) return PTR_ERR(qphy->base); qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb"); - if (IS_ERR(qphy->cfg_ahb_clk)) { - ret = PTR_ERR(qphy->cfg_ahb_clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get cfg ahb clk, %d\n", ret); - return ret; - } + if (IS_ERR(qphy->cfg_ahb_clk)) + return dev_err_probe(dev, PTR_ERR(qphy->cfg_ahb_clk), + "failed to get cfg ahb clk\n"); qphy->ref_clk = devm_clk_get(dev, "ref"); - if (IS_ERR(qphy->ref_clk)) { - ret = PTR_ERR(qphy->ref_clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get ref clk, %d\n", ret); - return ret; - } + if (IS_ERR(qphy->ref_clk)) + return dev_err_probe(dev, PTR_ERR(qphy->ref_clk), + "failed to get ref clk\n"); qphy->iface_clk = devm_clk_get_optional(dev, "iface"); if (IS_ERR(qphy->iface_clk)) @@ -1003,12 +997,9 @@ static int qusb2_phy_probe(struct platform_device *pdev) qphy->vregs[i].supply = qusb2_phy_vreg_names[i]; ret = devm_regulator_bulk_get(dev, num, qphy->vregs); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); /* Get the specific init parameters of QMP phy */ qphy->cfg = of_device_get_match_data(dev); diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c index 5d203784f75d..a59063596214 100644 --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c @@ -52,6 +52,12 @@ #define USB2_SUSPEND_N BIT(2) #define USB2_SUSPEND_N_SEL BIT(3) +#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0 (0x6c) +#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1 (0x70) +#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2 (0x74) +#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3 (0x78) +#define PARAM_OVRD_MASK 0xFF + #define USB2_PHY_USB_PHY_CFG0 (0x94) #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0) #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1) @@ -60,12 +66,47 @@ #define REFCLK_SEL_MASK GENMASK(1, 0) #define REFCLK_SEL_DEFAULT (0x2 << 0) +#define HS_DISCONNECT_MASK GENMASK(2, 0) +#define SQUELCH_DETECTOR_MASK GENMASK(7, 5) + +#define HS_AMPLITUDE_MASK GENMASK(3, 0) +#define PREEMPHASIS_DURATION_MASK BIT(5) +#define PREEMPHASIS_AMPLITUDE_MASK GENMASK(7, 6) + +#define HS_RISE_FALL_MASK GENMASK(1, 0) +#define HS_CROSSOVER_VOLTAGE_MASK GENMASK(3, 2) +#define HS_OUTPUT_IMPEDANCE_MASK GENMASK(5, 4) + +#define LS_FS_OUTPUT_IMPEDANCE_MASK GENMASK(3, 0) + static const char * const qcom_snps_hsphy_vreg_names[] = { "vdda-pll", "vdda33", "vdda18", }; #define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names) +struct override_param { + s32 value; + u8 reg_val; +}; + +struct override_param_map { + const char *prop_name; + const struct override_param *param_table; + u8 table_size; + u8 reg_offset; + u8 param_mask; +}; + +struct phy_override_seq { + bool need_update; + u8 offset; + u8 value; + u8 mask; +}; + +#define NUM_HSPHY_TUNING_PARAMS (9) + /** * struct qcom_snps_hsphy - snps hs phy attributes * @@ -91,6 +132,7 @@ struct qcom_snps_hsphy { bool phy_initialized; enum phy_mode mode; + struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS]; }; static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset, @@ -173,10 +215,158 @@ static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode, return 0; } +static const struct override_param hs_disconnect_sc7280[] = { + { -272, 0 }, + { 0, 1 }, + { 317, 2 }, + { 630, 3 }, + { 973, 4 }, + { 1332, 5 }, + { 1743, 6 }, + { 2156, 7 }, +}; + +static const struct override_param squelch_det_threshold_sc7280[] = { + { -2090, 7 }, + { -1560, 6 }, + { -1030, 5 }, + { -530, 4 }, + { 0, 3 }, + { 530, 2 }, + { 1060, 1 }, + { 1590, 0 }, +}; + +static const struct override_param hs_amplitude_sc7280[] = { + { -660, 0 }, + { -440, 1 }, + { -220, 2 }, + { 0, 3 }, + { 230, 4 }, + { 440, 5 }, + { 650, 6 }, + { 890, 7 }, + { 1110, 8 }, + { 1330, 9 }, + { 1560, 10 }, + { 1780, 11 }, + { 2000, 12 }, + { 2220, 13 }, + { 2430, 14 }, + { 2670, 15 }, +}; + +static const struct override_param preemphasis_duration_sc7280[] = { + { 10000, 1 }, + { 20000, 0 }, +}; + +static const struct override_param preemphasis_amplitude_sc7280[] = { + { 10000, 1 }, + { 20000, 2 }, + { 30000, 3 }, + { 40000, 0 }, +}; + +static const struct override_param hs_rise_fall_time_sc7280[] = { + { -4100, 3 }, + { 0, 2 }, + { 2810, 1 }, + { 5430, 0 }, +}; + +static const struct override_param hs_crossover_voltage_sc7280[] = { + { -31000, 1 }, + { 0, 3 }, + { 28000, 2 }, +}; + +static const struct override_param hs_output_impedance_sc7280[] = { + { -2300000, 3 }, + { 0, 2 }, + { 2600000, 1 }, + { 6100000, 0 }, +}; + +static const struct override_param ls_fs_output_impedance_sc7280[] = { + { -1053, 15 }, + { -557, 7 }, + { 0, 3 }, + { 612, 1 }, + { 1310, 0 }, +}; + +static const struct override_param_map sc7280_snps_7nm_phy[] = { + { + "qcom,hs-disconnect-bp", + hs_disconnect_sc7280, + ARRAY_SIZE(hs_disconnect_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0, + HS_DISCONNECT_MASK + }, + { + "qcom,squelch-detector-bp", + squelch_det_threshold_sc7280, + ARRAY_SIZE(squelch_det_threshold_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0, + SQUELCH_DETECTOR_MASK + }, + { + "qcom,hs-amplitude-bp", + hs_amplitude_sc7280, + ARRAY_SIZE(hs_amplitude_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1, + HS_AMPLITUDE_MASK + }, + { + "qcom,pre-emphasis-duration-bp", + preemphasis_duration_sc7280, + ARRAY_SIZE(preemphasis_duration_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1, + PREEMPHASIS_DURATION_MASK, + }, + { + "qcom,pre-emphasis-amplitude-bp", + preemphasis_amplitude_sc7280, + ARRAY_SIZE(preemphasis_amplitude_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1, + PREEMPHASIS_AMPLITUDE_MASK, + }, + { + "qcom,hs-rise-fall-time-bp", + hs_rise_fall_time_sc7280, + ARRAY_SIZE(hs_rise_fall_time_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2, + HS_RISE_FALL_MASK + }, + { + "qcom,hs-crossover-voltage-microvolt", + hs_crossover_voltage_sc7280, + ARRAY_SIZE(hs_crossover_voltage_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2, + HS_CROSSOVER_VOLTAGE_MASK + }, + { + "qcom,hs-output-impedance-micro-ohms", + hs_output_impedance_sc7280, + ARRAY_SIZE(hs_output_impedance_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2, + HS_OUTPUT_IMPEDANCE_MASK, + }, + { + "qcom,ls-fs-output-impedance-bp", + ls_fs_output_impedance_sc7280, + ARRAY_SIZE(ls_fs_output_impedance_sc7280), + USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3, + LS_FS_OUTPUT_IMPEDANCE_MASK, + }, + {}, +}; + static int qcom_snps_hsphy_init(struct phy *phy) { struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); - int ret; + int ret, i; dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__); @@ -223,6 +413,14 @@ static int qcom_snps_hsphy_init(struct phy *phy) qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1, VBUSVLDEXT0, VBUSVLDEXT0); + for (i = 0; i < ARRAY_SIZE(hsphy->update_seq_cfg); i++) { + if (hsphy->update_seq_cfg[i].need_update) + qcom_snps_hsphy_write_mask(hsphy->base, + hsphy->update_seq_cfg[i].offset, + hsphy->update_seq_cfg[i].mask, + hsphy->update_seq_cfg[i].value); + } + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2, VREGBYPASS, VREGBYPASS); @@ -280,7 +478,10 @@ static const struct phy_ops qcom_snps_hsphy_gen_ops = { static const struct of_device_id qcom_snps_hsphy_of_match_table[] = { { .compatible = "qcom,sm8150-usb-hs-phy", }, { .compatible = "qcom,usb-snps-hs-5nm-phy", }, - { .compatible = "qcom,usb-snps-hs-7nm-phy", }, + { + .compatible = "qcom,usb-snps-hs-7nm-phy", + .data = &sc7280_snps_7nm_phy, + }, { .compatible = "qcom,usb-snps-femto-v2-phy", }, { } }; @@ -291,6 +492,55 @@ static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = { qcom_snps_hsphy_runtime_resume, NULL) }; +static void qcom_snps_hsphy_override_param_update_val( + const struct override_param_map map, + s32 dt_val, struct phy_override_seq *seq_entry) +{ + int i; + + /* + * Param table for each param is in increasing order + * of dt values. We need to iterate over the list to + * select the entry that matches the dt value and pick + * up the corresponding register value. + */ + for (i = 0; i < map.table_size - 1; i++) { + if (map.param_table[i].value == dt_val) + break; + } + + seq_entry->need_update = true; + seq_entry->offset = map.reg_offset; + seq_entry->mask = map.param_mask; + seq_entry->value = map.param_table[i].reg_val << __ffs(map.param_mask); +} + +static void qcom_snps_hsphy_read_override_param_seq(struct device *dev) +{ + struct device_node *node = dev->of_node; + s32 val; + int ret, i; + struct qcom_snps_hsphy *hsphy; + const struct override_param_map *cfg = of_device_get_match_data(dev); + + if (!cfg) + return; + + hsphy = dev_get_drvdata(dev); + + for (i = 0; cfg[i].prop_name != NULL; i++) { + ret = of_property_read_s32(node, cfg[i].prop_name, &val); + if (ret) + continue; + + qcom_snps_hsphy_override_param_update_val(cfg[i], val, + &hsphy->update_seq_cfg[i]); + dev_dbg(&hsphy->phy->dev, "Read param: %s dt_val: %d reg_val: 0x%x\n", + cfg[i].prop_name, val, hsphy->update_seq_cfg[i].value); + + } +} + static int qcom_snps_hsphy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -309,12 +559,9 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev) return PTR_ERR(hsphy->base); hsphy->ref_clk = devm_clk_get(dev, "ref"); - if (IS_ERR(hsphy->ref_clk)) { - ret = PTR_ERR(hsphy->ref_clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get ref clk, %d\n", ret); - return ret; - } + if (IS_ERR(hsphy->ref_clk)) + return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk), + "failed to get ref clk\n"); hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(hsphy->phy_reset)) { @@ -327,12 +574,9 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev) hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i]; ret = devm_regulator_bulk_get(dev, num, hsphy->vregs); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get regulator supplies: %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -352,6 +596,7 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev) dev_set_drvdata(dev, hsphy); phy_set_drvdata(generic_phy, hsphy); + qcom_snps_hsphy_read_override_param_seq(dev); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (!IS_ERR(phy_provider)) diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c index 716a77748ed8..20f6dd37c7c1 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c @@ -54,8 +54,10 @@ static int qcom_usb_hsic_phy_power_on(struct phy *phy) /* Configure pins for HSIC functionality */ pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT); - if (IS_ERR(pins_default)) - return PTR_ERR(pins_default); + if (IS_ERR(pins_default)) { + ret = PTR_ERR(pins_default); + goto err_ulpi; + } ret = pinctrl_select_state(uphy->pctl, pins_default); if (ret) |