phy: qcom-qmp-combo: fix broken power on

[ Upstream commit 7a7d86d14d ]

The 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.

Fixes: 52e013d0bf ("phy: qcom-qmp: Add support for DP in USB3+DP combo phy")
Cc: stable@vger.kernel.org	# 5.10
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Link: https://lore.kernel.org/r/20221114081346.5116-5-johan+linaro@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Johan Hovold 2022-11-14 09:13:44 +01:00 committed by Greg Kroah-Hartman
parent 749fa62e49
commit 906f421ac5
1 changed files with 13 additions and 7 deletions

View File

@ -767,6 +767,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;
@ -1607,7 +1608,7 @@ static int qcom_qmp_phy_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;
@ -1663,13 +1664,13 @@ static int qcom_qmp_phy_combo_com_init(struct qmp_phy *qphy)
qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET);
}
if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL])
qphy_setbits(pcs,
cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
cfg->pwrdn_ctrl);
if (usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL])
qphy_setbits(usb_phy->pcs,
usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
usb_phy->cfg->pwrdn_ctrl);
else
qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL,
cfg->pwrdn_ctrl);
qphy_setbits(usb_phy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL,
usb_phy->cfg->pwrdn_ctrl);
mutex_unlock(&qmp->phy_mutex);
@ -2576,6 +2577,8 @@ static int qcom_qmp_phy_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.
@ -2591,6 +2594,9 @@ static int qcom_qmp_phy_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);
if (!IS_ERR(phy_provider))
dev_info(dev, "Registered Qcom-QMP phy\n");