|
236 | 236 | #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18 |
237 | 237 | #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf |
238 | 238 | #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8 |
| 239 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0 |
239 | 240 |
|
240 | 241 | struct tegra210_xusb_fuse_calibration { |
241 | 242 | u32 hs_curr_level[4]; |
@@ -935,6 +936,103 @@ static int tegra210_usb2_phy_exit(struct phy *phy) |
935 | 936 | return tegra210_xusb_padctl_disable(lane->pad->padctl); |
936 | 937 | } |
937 | 938 |
|
| 939 | +static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, |
| 940 | + bool status) |
| 941 | +{ |
| 942 | + u32 value; |
| 943 | + |
| 944 | + dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear"); |
| 945 | + |
| 946 | + value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); |
| 947 | + |
| 948 | + if (status) { |
| 949 | + value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; |
| 950 | + value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << |
| 951 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); |
| 952 | + value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << |
| 953 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; |
| 954 | + } else { |
| 955 | + value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; |
| 956 | + } |
| 957 | + |
| 958 | + padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); |
| 959 | + |
| 960 | + return 0; |
| 961 | +} |
| 962 | + |
| 963 | +static int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl, |
| 964 | + bool status) |
| 965 | +{ |
| 966 | + u32 value; |
| 967 | + |
| 968 | + dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear"); |
| 969 | + |
| 970 | + value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); |
| 971 | + |
| 972 | + if (status) { |
| 973 | + if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) { |
| 974 | + value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; |
| 975 | + padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); |
| 976 | + usleep_range(1000, 2000); |
| 977 | + |
| 978 | + value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); |
| 979 | + } |
| 980 | + |
| 981 | + value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << |
| 982 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); |
| 983 | + value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED << |
| 984 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; |
| 985 | + } else { |
| 986 | + value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << |
| 987 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); |
| 988 | + value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << |
| 989 | + XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; |
| 990 | + } |
| 991 | + |
| 992 | + padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); |
| 993 | + |
| 994 | + return 0; |
| 995 | +} |
| 996 | + |
| 997 | +static int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode, |
| 998 | + int submode) |
| 999 | +{ |
| 1000 | + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
| 1001 | + struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
| 1002 | + struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl, |
| 1003 | + lane->index); |
| 1004 | + int err = 0; |
| 1005 | + |
| 1006 | + mutex_lock(&padctl->lock); |
| 1007 | + |
| 1008 | + dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode); |
| 1009 | + |
| 1010 | + if (mode == PHY_MODE_USB_OTG) { |
| 1011 | + if (submode == USB_ROLE_HOST) { |
| 1012 | + tegra210_xusb_padctl_id_override(padctl, true); |
| 1013 | + |
| 1014 | + err = regulator_enable(port->supply); |
| 1015 | + } else if (submode == USB_ROLE_DEVICE) { |
| 1016 | + tegra210_xusb_padctl_vbus_override(padctl, true); |
| 1017 | + } else if (submode == USB_ROLE_NONE) { |
| 1018 | + /* |
| 1019 | + * When port is peripheral only or role transitions to |
| 1020 | + * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not |
| 1021 | + * be enabled. |
| 1022 | + */ |
| 1023 | + if (regulator_is_enabled(port->supply)) |
| 1024 | + regulator_disable(port->supply); |
| 1025 | + |
| 1026 | + tegra210_xusb_padctl_id_override(padctl, false); |
| 1027 | + tegra210_xusb_padctl_vbus_override(padctl, false); |
| 1028 | + } |
| 1029 | + } |
| 1030 | + |
| 1031 | + mutex_unlock(&padctl->lock); |
| 1032 | + |
| 1033 | + return err; |
| 1034 | +} |
| 1035 | + |
938 | 1036 | static int tegra210_usb2_phy_power_on(struct phy *phy) |
939 | 1037 | { |
940 | 1038 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
@@ -1048,9 +1146,11 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) |
1048 | 1146 | padctl_writel(padctl, value, |
1049 | 1147 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); |
1050 | 1148 |
|
1051 | | - err = regulator_enable(port->supply); |
1052 | | - if (err) |
1053 | | - return err; |
| 1149 | + if (port->supply && port->mode == USB_DR_MODE_HOST) { |
| 1150 | + err = regulator_enable(port->supply); |
| 1151 | + if (err) |
| 1152 | + return err; |
| 1153 | + } |
1054 | 1154 |
|
1055 | 1155 | mutex_lock(&padctl->lock); |
1056 | 1156 |
|
@@ -1164,6 +1264,7 @@ static const struct phy_ops tegra210_usb2_phy_ops = { |
1164 | 1264 | .exit = tegra210_usb2_phy_exit, |
1165 | 1265 | .power_on = tegra210_usb2_phy_power_on, |
1166 | 1266 | .power_off = tegra210_usb2_phy_power_off, |
| 1267 | + .set_mode = tegra210_usb2_phy_set_mode, |
1167 | 1268 | .owner = THIS_MODULE, |
1168 | 1269 | }; |
1169 | 1270 |
|
@@ -2023,30 +2124,6 @@ static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = { |
2023 | 2124 | .map = tegra210_usb3_port_map, |
2024 | 2125 | }; |
2025 | 2126 |
|
2026 | | -static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, |
2027 | | - bool status) |
2028 | | -{ |
2029 | | - u32 value; |
2030 | | - |
2031 | | - dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear"); |
2032 | | - |
2033 | | - value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); |
2034 | | - |
2035 | | - if (status) { |
2036 | | - value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; |
2037 | | - value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << |
2038 | | - XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); |
2039 | | - value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << |
2040 | | - XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; |
2041 | | - } else { |
2042 | | - value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; |
2043 | | - } |
2044 | | - |
2045 | | - padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); |
2046 | | - |
2047 | | - return 0; |
2048 | | -} |
2049 | | - |
2050 | 2127 | static int tegra210_utmi_port_reset(struct phy *phy) |
2051 | 2128 | { |
2052 | 2129 | struct tegra_xusb_padctl *padctl; |
|
0 commit comments