Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: tegra: xusb: Fix unbalanced regulator disable in UTMI PHY mode

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: 49d46e3c7e59 ("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>

authored by

Wayne Chang and committed by
Vinod Koul
cefc1cae 7be54870

+38 -23
+38 -23
drivers/phy/tegra/xusb-tegra186.c
··· 783 783 } 784 784 785 785 static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl, 786 - bool status) 786 + struct tegra_xusb_usb2_port *port, bool status) 787 787 { 788 - u32 value; 788 + u32 value, id_override; 789 + int err = 0; 789 790 790 791 dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear"); 791 792 792 793 value = padctl_readl(padctl, USB2_VBUS_ID); 794 + id_override = value & ID_OVERRIDE(~0); 793 795 794 796 if (status) { 795 797 if (value & VBUS_OVERRIDE) { ··· 802 800 value = padctl_readl(padctl, USB2_VBUS_ID); 803 801 } 804 802 805 - value &= ~ID_OVERRIDE(~0); 806 - value |= ID_OVERRIDE_GROUNDED; 807 - } else { 808 - value &= ~ID_OVERRIDE(~0); 809 - value |= ID_OVERRIDE_FLOATING; 810 - } 803 + if (id_override != ID_OVERRIDE_GROUNDED) { 804 + value &= ~ID_OVERRIDE(~0); 805 + value |= ID_OVERRIDE_GROUNDED; 806 + padctl_writel(padctl, value, USB2_VBUS_ID); 811 807 812 - padctl_writel(padctl, value, USB2_VBUS_ID); 808 + err = regulator_enable(port->supply); 809 + if (err) { 810 + dev_err(padctl->dev, "Failed to enable regulator: %d\n", err); 811 + return err; 812 + } 813 + } 814 + } else { 815 + if (id_override == ID_OVERRIDE_GROUNDED) { 816 + /* 817 + * The regulator is disabled only when the role transitions 818 + * from USB_ROLE_HOST to USB_ROLE_NONE. 819 + */ 820 + err = regulator_disable(port->supply); 821 + if (err) { 822 + dev_err(padctl->dev, "Failed to disable regulator: %d\n", err); 823 + return err; 824 + } 825 + 826 + value &= ~ID_OVERRIDE(~0); 827 + value |= ID_OVERRIDE_FLOATING; 828 + padctl_writel(padctl, value, USB2_VBUS_ID); 829 + } 830 + } 813 831 814 832 return 0; 815 833 } ··· 849 827 850 828 if (mode == PHY_MODE_USB_OTG) { 851 829 if (submode == USB_ROLE_HOST) { 852 - tegra186_xusb_padctl_id_override(padctl, true); 853 - 854 - err = regulator_enable(port->supply); 830 + err = tegra186_xusb_padctl_id_override(padctl, port, true); 831 + if (err) 832 + goto out; 855 833 } else if (submode == USB_ROLE_DEVICE) { 856 834 tegra186_xusb_padctl_vbus_override(padctl, true); 857 835 } else if (submode == USB_ROLE_NONE) { 858 - /* 859 - * When port is peripheral only or role transitions to 860 - * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not 861 - * enabled. 862 - */ 863 - if (regulator_is_enabled(port->supply)) 864 - regulator_disable(port->supply); 865 - 866 - tegra186_xusb_padctl_id_override(padctl, false); 836 + err = tegra186_xusb_padctl_id_override(padctl, port, false); 837 + if (err) 838 + goto out; 867 839 tegra186_xusb_padctl_vbus_override(padctl, false); 868 840 } 869 841 } 870 - 842 + out: 871 843 mutex_unlock(&padctl->lock); 872 - 873 844 return err; 874 845 } 875 846