phy: qcom-qmp-combo: preparatory fixes (set 1/3)
Subsystems (3)
v2 cover phy: qcom-qmp-combo: preparatory fixes (set 1/3)
Here's a set of fixes for bugs founds while fixing the devicetree binding and adding (proper) support for SC8280XP to the combo driver.
The full series is over forty patches and I'll be posting these in three parts of which this is the first. In an effort to get all of these into 6.2, I'll also be submitting all three series before waiting for the previous ones to be applied.
The first fix below could possibly be considered 6.1-rc material, but I believe it's be fine to take all of these for 6.2.
Note that the next part of the series will do away with some of problems with this driver that led to the issues being fixed here (e.g. the split driver data and configuration).
Johan
Changes in v2
- fix SW_PWRDN typo in commit message (Dmitry)
- use the right commit for the runtime PM Fixes tag (Dmitry)
Johan Hovold (6):
phy: qcom-qmp-combo: fix out-of-bounds clock access
phy: qcom-qmp-combo: fix sdm845 reset
phy: qcom-qmp-combo: fix sc8180x reset
phy: qcom-qmp-combo: fix broken power on
phy: qcom-qmp-combo: fix runtime suspend
phy: qcom-qmp-combo: clean up common initialisation
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 91 +++++++++++------------ 1 file changed, 44 insertions(+), 47 deletions(-)
Signature · 1 line
2.37.4
PATCH v2 1/6 phy: qcom-qmp-combo: fix out-of-bounds clock access
The SM8250 only uses three clocks but the DP configuration erroneously described four clocks.
In case the DP part of the PHY is initialised before the USB part, this would lead to uninitialised memory beyond the bulk-clocks array to be treated as a clock pointer as the clocks are requested based on the USB configuration.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +2 -2
@@ -1270,8 +1270,8 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = { .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), + .clk_list = qmp_v4_sm8250_usbphy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), .vreg_list = qmp_phy_vreg_l,
Signature · 1 line
2.37.4
PATCH v2 2/6 phy: qcom-qmp-combo: fix sdm845 reset
In reply to Johan HovoldThe SDM845 has two resets but the DP configuration erroneously described only one.
In case the DP part of the PHY is initialised before the USB part (e.g. depending on probe order), then only the first reset would be asserted.
Add a dedicated configuration for SDM845 rather than reuse the incompatible SC7180 configuration.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 39 ++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +38 -1
@@ -1084,9 +1084,46 @@ static const struct qmp_phy_cfg sdm845_usb3phy_cfg = { .has_pwrdn_delay = true, }; +static const struct qmp_phy_cfg sdm845_dpphy_cfg = { + .type =PHY_TYPE_DP , + .lanes =2 , + + .serdes_tbl = qmp_v3_dp_serdes_tbl, + .serdes_tbl_num =ARRAY_SIZE (qmp_v3_dp_serdes_tbl), + .tx_tbl = qmp_v3_dp_tx_tbl, + .tx_tbl_num =ARRAY_SIZE (qmp_v3_dp_tx_tbl), + + .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, + .serdes_tbl_rbr_num =ARRAY_SIZE (qmp_v3_dp_serdes_tbl_rbr), + .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, + .serdes_tbl_hbr_num =ARRAY_SIZE (qmp_v3_dp_serdes_tbl_hbr), + .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, + .serdes_tbl_hbr2_num =ARRAY_SIZE (qmp_v3_dp_serdes_tbl_hbr2), + .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 = 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, + + .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, + .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, +}; +static const struct qmp_phy_combo_cfg sdm845_usb3dpphy_cfg = { .usb_cfg = &sdm845_usb3phy_cfg, - .dp_cfg = &sc7180_dpphy_cfg, + .dp_cfg = &sdm845_dpphy_cfg, };static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
Signature · 1 line
2.37.4
PATCH v2 3/6 phy: qcom-qmp-combo: fix sc8180x reset
In reply to Johan HovoldThe SC8180X has two resets but the DP configuration erroneously described only one.
In case the DP part of the PHY is initialised before the USB part (e.g. depending on probe order), then only the first reset would be asserted.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +2 -2
@@ -1177,8 +1177,8 @@ static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { .clk_list = qmp_v3_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), - .reset_list = sc7180_usb3phy_reset_l, - .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_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,
Signature · 1 line
2.37.4
PATCH v2 4/6 phy: qcom-qmp-combo: fix broken power on
In reply to Johan HovoldThe PHY is powered on during phy-init by setting the SW_PWRDN bit in the COM_POWER_DOWN_CTRL register and then setting the same bit in the in the PCS_POWER_DOWN_CONTROL register that belongs to the USB part of the PHY.
Currently, whether power on succeeds depends on probe order and having the USB part of the PHY be initialised first. In case the DP part of the PHY is instead initialised first, the intended power on of the USB block results in a corrupted DP_PHY register (e.g. DP_PHY_AUX_CFG8).
Add a pointer to the USB part of the PHY to the driver data and use that to power on the PHY also if the DP part of the PHY is initialised first.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +9 -2
@@ -932,6 +932,7 @@ struct qcom_qmp {struct regulator_bulk_data *vregs;struct qmp_phy **phys; +struct qmp_phy *usb_phy;struct mutex phy_mutex;int init_count;
@@ -1911,7 +1912,7 @@ static int qmp_combo_com_init(struct qmp_phy *qphy) {struct qcom_qmp *qmp = qphy->qmp;const struct qmp_phy_cfg *cfg = qphy->cfg; -void __iomem *pcs = qphy->pcs; +struct qmp_phy *usb_phy = qmp->usb_phy;void __iomem *dp_com = qmp->dp_com;int ret;
@@ -1963,7 +1964,8 @@ static int qmp_combo_com_init(struct qmp_phy *qphy)qphy_clrbits (dp_com,QPHY_V3_DP_COM_SWI_CTRL ,0x03 );qphy_clrbits (dp_com,QPHY_V3_DP_COM_SW_RESET ,SW_RESET ); -qphy_setbits (pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL ],SW_PWRDN ); +qphy_setbits (usb_phy->pcs, usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL ], +SW_PWRDN );mutex_unlock (&qmp->phy_mutex);
@@ -2831,6 +2833,8 @@ static int qmp_combo_probe(struct platform_device *pdev) goto err_node_put; } + qmp->usb_phy = qmp->phys[id]; +/* * Register the pipe clock provided by phy. * See function description to see details of this pipe clock.
@@ -2846,6 +2850,9 @@ static int qmp_combo_probe(struct platform_device *pdev) id++; } +if (!qmp->usb_phy) +return -EINVAL ; + phy_provider =devm_of_phy_provider_register (dev, of_phy_simple_xlate);return PTR_ERR_OR_ZERO (phy_provider);
Signature · 1 line
2.37.4
PATCH v2 5/6 phy: qcom-qmp-combo: fix runtime suspend
In reply to Johan HovoldDrop the confused runtime-suspend type check which effectively broke runtime PM if the DP child node happens to be parsed before the USB child node during probe (e.g. due to order of child nodes in the devicetree).
Instead use the new driver data USB PHY pointer to access the USB configuration and resources.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +2 -10
@@ -2207,15 +2207,11 @@ static void qmp_combo_disable_autonomous_mode(struct qmp_phy *qphy)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 ]; +struct qmp_phy *qphy = qmp->usb_phy;const struct qmp_phy_cfg *cfg = qphy->cfg;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 (!qmp->init_count) {dev_vdbg (dev,"PHY not initialized, bailing out\n" );return 0 ;
@@ -2232,16 +2228,12 @@ static int __maybe_unused qmp_combo_runtime_suspend(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 ]; +struct qmp_phy *qphy = qmp->usb_phy;const struct qmp_phy_cfg *cfg = qphy->cfg;int ret =0 ;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 (!qmp->init_count) {dev_vdbg (dev,"PHY not initialized, bailing out\n" );return 0 ;
Signature · 1 line
2.37.4
PATCH v2 6/6 phy: qcom-qmp-combo: clean up common initialisation
In reply to Johan HovoldCommit 52e013d0bffa ("phy: qcom-qmp: Add support for DP in USB3+DP combo phy") added support for the DisplayPort part of QMP PHYs but unfortunately did so by duplicating parts of the shared configuration, something which has lead to subtle bugs depending on probe order.
As the resources have always been requested based on the USB configuration, make sure to not rely on fields from the DP configuration when using them (e.g. in case they get out of sync) and remove the now unused fields from the DP configurations.
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 47 ++--------------------- 1 file changed, 4 insertions(+), 43 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +4 -43
@@ -1043,14 +1043,6 @@ static const struct qmp_phy_cfg sc7180_dpphy_cfg = { .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, - .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), - .regs = qmp_v3_usb3phy_regs_layout, - .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,
@@ -1108,14 +1100,6 @@ static const struct qmp_phy_cfg sdm845_dpphy_cfg = { .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 = 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, - .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,
@@ -1176,14 +1160,6 @@ static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { .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 = 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, - .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,
@@ -1240,14 +1216,6 @@ static const struct qmp_phy_cfg sc8280xp_usb43dp_dp_cfg = { .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,
@@ -1308,14 +1276,6 @@ static const struct qmp_phy_cfg sm8250_dpphy_cfg = { .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_sm8250_usbphy_clk_l, - .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_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_v4_phy_configure_dp_phy,
@@ -1911,8 +1871,8 @@ static int qcom_qmp_dp_phy_calibrate(struct phy *phy)static int qmp_combo_com_init (struct qmp_phy *qphy) {struct qcom_qmp *qmp = qphy->qmp; -const struct qmp_phy_cfg *cfg = qphy->cfg;struct qmp_phy *usb_phy = qmp->usb_phy; +const struct qmp_phy_cfg *cfg = usb_phy->cfg;void __iomem *dp_com = qmp->dp_com;int ret;
@@ -1964,7 +1924,7 @@ static int qmp_combo_com_init(struct qmp_phy *qphy)qphy_clrbits (dp_com,QPHY_V3_DP_COM_SWI_CTRL ,0x03 );qphy_clrbits (dp_com,QPHY_V3_DP_COM_SW_RESET ,SW_RESET ); -qphy_setbits (usb_phy->pcs, usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL ], +qphy_setbits (usb_phy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL ],SW_PWRDN );mutex_unlock (&qmp->phy_mutex);
@@ -1984,7 +1944,8 @@ static int qmp_combo_com_init(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; +struct qmp_phy *usb_phy = qmp->usb_phy; +const struct qmp_phy_cfg *cfg = usb_phy->cfg;mutex_lock (&qmp->phy_mutex);if (--qmp->init_count) {
Signature · 1 line
2.37.4
Quoted 8 lines · Johan Hovold
Here's a set of fixes for bugs founds while fixing the devicetree binding and adding (proper) support for SC8280XP to the combo driver.
The full series is over forty patches and I'll be posting these in three parts of which this is the first. In an effort to get all of these into 6.2, I'll also be submitting all three series before waiting for the previous ones to be applied.
Quoted 6 lines
The first fix below could possibly be considered 6.1-rc material, but I believe it's be fine to take all of these for 6.2.
Note that the next part of the series will do away with some of problems with this driver that led to the issues being fixed here (e.g. the split driver data and configuration).
Applied, thanks
Signature · 1 line
~Vinod