Skip to content

Commit ec7f98f

Browse files
Wayne Changgregkh
authored andcommitted
phy: tegra: xusb: Fix unbalanced regulator disable in UTMI PHY mode
commit cefc1ca upstream. When transitioning from USB_ROLE_DEVICE to USB_ROLE_NONE, the code assumed that the regulator should be disabled. However, if the regulator is marked as always-on, regulator_is_enabled() continues to return true, leading to an incorrect attempt to disable a regulator which is not enabled. This can result in warnings such as: [ 250.155624] WARNING: CPU: 1 PID: 7326 at drivers/regulator/core.c:3004 _regulator_disable+0xe4/0x1a0 [ 250.155652] unbalanced disables for VIN_SYS_5V0 To fix this, we move the regulator control logic into tegra186_xusb_padctl_id_override() function since it's directly related to the ID override state. The regulator is now only disabled when the role transitions from USB_ROLE_HOST to USB_ROLE_NONE, by checking the VBUS_ID register. This ensures that regulator enable/disable operations are properly balanced and only occur when actually transitioning to/from host mode. Fixes: 49d46e3 ("phy: tegra: xusb: Add set_mode support for UTMI phy on Tegra186") Cc: stable@vger.kernel.org Signed-off-by: Wayne Chang <waynec@nvidia.com> Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Link: https://lore.kernel.org/r/20250502092606.2275682-1-waynec@nvidia.com Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent cdf264c commit ec7f98f

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

drivers/phy/tegra/xusb-tegra186.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -782,13 +782,15 @@ static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
782782
}
783783

784784
static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
785-
bool status)
785+
struct tegra_xusb_usb2_port *port, bool status)
786786
{
787-
u32 value;
787+
u32 value, id_override;
788+
int err = 0;
788789

789790
dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");
790791

791792
value = padctl_readl(padctl, USB2_VBUS_ID);
793+
id_override = value & ID_OVERRIDE(~0);
792794

793795
if (status) {
794796
if (value & VBUS_OVERRIDE) {
@@ -799,15 +801,35 @@ static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
799801
value = padctl_readl(padctl, USB2_VBUS_ID);
800802
}
801803

802-
value &= ~ID_OVERRIDE(~0);
803-
value |= ID_OVERRIDE_GROUNDED;
804+
if (id_override != ID_OVERRIDE_GROUNDED) {
805+
value &= ~ID_OVERRIDE(~0);
806+
value |= ID_OVERRIDE_GROUNDED;
807+
padctl_writel(padctl, value, USB2_VBUS_ID);
808+
809+
err = regulator_enable(port->supply);
810+
if (err) {
811+
dev_err(padctl->dev, "Failed to enable regulator: %d\n", err);
812+
return err;
813+
}
814+
}
804815
} else {
805-
value &= ~ID_OVERRIDE(~0);
806-
value |= ID_OVERRIDE_FLOATING;
816+
if (id_override == ID_OVERRIDE_GROUNDED) {
817+
/*
818+
* The regulator is disabled only when the role transitions
819+
* from USB_ROLE_HOST to USB_ROLE_NONE.
820+
*/
821+
err = regulator_disable(port->supply);
822+
if (err) {
823+
dev_err(padctl->dev, "Failed to disable regulator: %d\n", err);
824+
return err;
825+
}
826+
827+
value &= ~ID_OVERRIDE(~0);
828+
value |= ID_OVERRIDE_FLOATING;
829+
padctl_writel(padctl, value, USB2_VBUS_ID);
830+
}
807831
}
808832

809-
padctl_writel(padctl, value, USB2_VBUS_ID);
810-
811833
return 0;
812834
}
813835

@@ -826,27 +848,20 @@ static int tegra186_utmi_phy_set_mode(struct phy *phy, enum phy_mode mode,
826848

827849
if (mode == PHY_MODE_USB_OTG) {
828850
if (submode == USB_ROLE_HOST) {
829-
tegra186_xusb_padctl_id_override(padctl, true);
830-
831-
err = regulator_enable(port->supply);
851+
err = tegra186_xusb_padctl_id_override(padctl, port, true);
852+
if (err)
853+
goto out;
832854
} else if (submode == USB_ROLE_DEVICE) {
833855
tegra186_xusb_padctl_vbus_override(padctl, true);
834856
} else if (submode == USB_ROLE_NONE) {
835-
/*
836-
* When port is peripheral only or role transitions to
837-
* USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
838-
* enabled.
839-
*/
840-
if (regulator_is_enabled(port->supply))
841-
regulator_disable(port->supply);
842-
843-
tegra186_xusb_padctl_id_override(padctl, false);
857+
err = tegra186_xusb_padctl_id_override(padctl, port, false);
858+
if (err)
859+
goto out;
844860
tegra186_xusb_padctl_vbus_override(padctl, false);
845861
}
846862
}
847-
863+
out:
848864
mutex_unlock(&padctl->lock);
849-
850865
return err;
851866
}
852867

0 commit comments

Comments
 (0)