[PATCH v2 2/2] phy: qcom: qmp-combo: check qmp_combo_com_init() in the typec callbacks

From: Oleg Keri

Date: Wed Sep 16 2026 - 09:04:30 EST


qmp_combo_typec_switch_set() and qmp_combo_reconfigure_phy(), which the
typec mux callback and the USB4 init path use, tear the common block down
and bring it straight back up on an orientation or altmode change, but
they discard the result of the bringup:

qmp_combo_com_exit(qmp, true);

qmp->qmpphy_mode = new_mode;

/* Now everything's powered down, power up the right PHYs */
qmp_combo_com_init(qmp, true);

if ((qmp->usb_init_count || qmp->usb4_init_count) &&
new_mode != QMPPHY_MODE_DP_ONLY)
qmp_combo_usb_power_on(qmp->usb_phy);

If qmp_combo_com_init() fails - a regulator, a reset or
clk_bulk_prepare_enable() - it unwinds what it had brought up and returns
an error, leaving the clocks disabled. Both paths then carry on and
qmp_combo_usb_power_on(), and dp_aux_init() after it, write PHY registers
with no clock running. qmp_combo_usb4_init() already checks the return
value of qmp_combo_reconfigure_phy(), but never sees a failure from it.

Propagate the failure instead. The PHY is then left logically
initialised with its clocks off, which is the state any forced bringup
failure already produces and which these callbacks have no way to report
to the PHY consumers; what changes is that the register writes that
would fault no longer happen.

Fixes: 2851117f8f42 ("phy: qcom-qmp-combo: Introduce orientation switching")
Signed-off-by: Oleg Keri <okerixx@xxxxxxxxx>
---
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index f6d3320a59d9..ae70ebba36c4 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -4601,6 +4601,8 @@ static int qmp_combo_usb_set_mode(struct phy *phy, enum phy_mode mode, int submo

static int qmp_combo_reconfigure_phy(struct qmp_combo *qmp, enum qmpphy_mode new_mode)
{
+ int ret;
+
dev_dbg(qmp->dev, "qmp_combo_reconfigure_phy: switching from qmpphy mode %d to %d\n",
qmp->qmpphy_mode, new_mode);

@@ -4615,7 +4617,9 @@ static int qmp_combo_reconfigure_phy(struct qmp_combo *qmp, enum qmpphy_mode new
qmp->qmpphy_mode = new_mode;

/* Now everything's powered down, power up the right PHYs */
- qmp_combo_com_init(qmp, true);
+ ret = qmp_combo_com_init(qmp, true);
+ if (ret)
+ return ret;

if ((qmp->usb_init_count || qmp->usb4_init_count) &&
new_mode != QMPPHY_MODE_DP_ONLY)
@@ -5166,6 +5170,7 @@ static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
{
struct qmp_combo *qmp = typec_switch_get_drvdata(sw);
const struct qmp_phy_cfg *cfg = qmp->cfg;
+ int ret;

if (qmp->qmpphy_mode == QMPPHY_MODE_USB4) {
/* QMPPHY has no orientation handling in USB4 mode, don't cache the setting */
@@ -5186,7 +5191,10 @@ static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
qmp_combo_usb_power_off(qmp->usb_phy);
qmp_combo_com_exit(qmp, true);

- qmp_combo_com_init(qmp, true);
+ ret = qmp_combo_com_init(qmp, true);
+ if (ret)
+ return ret;
+
if (qmp->usb_init_count || qmp->usb4_init_count)
qmp_combo_usb_power_on(qmp->usb_phy);
if (qmp->dp_init_count)
--
2.55.0