.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. |
---|
3 | 4 | * Copyright (C) 2015 Google, Inc. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | 5 | */ |
---|
14 | 6 | |
---|
15 | 7 | #include <linux/clk.h> |
---|
.. | .. |
---|
47 | 39 | #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 0x1 |
---|
48 | 40 | |
---|
49 | 41 | #define XUSB_PADCTL_USB2_PORT_CAP 0x008 |
---|
| 42 | +#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(x) (0x0 << ((x) * 4)) |
---|
50 | 43 | #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4)) |
---|
| 44 | +#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(x) (0x2 << ((x) * 4)) |
---|
| 45 | +#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(x) (0x3 << ((x) * 4)) |
---|
51 | 46 | #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4)) |
---|
52 | 47 | |
---|
53 | 48 | #define XUSB_PADCTL_SS_PORT_MAP 0x014 |
---|
.. | .. |
---|
55 | 50 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5) |
---|
56 | 51 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5)) |
---|
57 | 52 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) |
---|
| 53 | +#define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7 |
---|
58 | 54 | |
---|
59 | 55 | #define XUSB_PADCTL_ELPG_PROGRAM1 0x024 |
---|
60 | 56 | #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) |
---|
.. | .. |
---|
69 | 65 | #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) |
---|
70 | 66 | #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x))) |
---|
71 | 67 | |
---|
| 68 | +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(x) (0x080 + (x) * 0x40) |
---|
| 69 | +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP (1 << 18) |
---|
| 70 | +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN (1 << 22) |
---|
| 71 | + |
---|
72 | 72 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40) |
---|
73 | 73 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7 |
---|
74 | 74 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3 |
---|
| 75 | +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL 0x1 |
---|
75 | 76 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6) |
---|
76 | 77 | |
---|
77 | 78 | #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40) |
---|
.. | .. |
---|
229 | 230 | |
---|
230 | 231 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40) |
---|
231 | 232 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368 |
---|
| 233 | + |
---|
| 234 | +#define XUSB_PADCTL_USB2_VBUS_ID 0xc60 |
---|
| 235 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON (1 << 14) |
---|
| 236 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18 |
---|
| 237 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf |
---|
| 238 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8 |
---|
| 239 | +#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0 |
---|
232 | 240 | |
---|
233 | 241 | struct tegra210_xusb_fuse_calibration { |
---|
234 | 242 | u32 hs_curr_level[4]; |
---|
.. | .. |
---|
928 | 936 | return tegra210_xusb_padctl_disable(lane->pad->padctl); |
---|
929 | 937 | } |
---|
930 | 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 | + |
---|
931 | 1036 | static int tegra210_usb2_phy_power_on(struct phy *phy) |
---|
932 | 1037 | { |
---|
933 | 1038 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
---|
.. | .. |
---|
948 | 1053 | |
---|
949 | 1054 | priv = to_tegra210_xusb_padctl(padctl); |
---|
950 | 1055 | |
---|
| 1056 | + if (port->usb3_port_fake != -1) { |
---|
| 1057 | + value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); |
---|
| 1058 | + value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( |
---|
| 1059 | + port->usb3_port_fake); |
---|
| 1060 | + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP( |
---|
| 1061 | + port->usb3_port_fake, index); |
---|
| 1062 | + padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); |
---|
| 1063 | + |
---|
| 1064 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1065 | + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( |
---|
| 1066 | + port->usb3_port_fake); |
---|
| 1067 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1068 | + |
---|
| 1069 | + usleep_range(100, 200); |
---|
| 1070 | + |
---|
| 1071 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1072 | + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( |
---|
| 1073 | + port->usb3_port_fake); |
---|
| 1074 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1075 | + |
---|
| 1076 | + usleep_range(100, 200); |
---|
| 1077 | + |
---|
| 1078 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1079 | + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( |
---|
| 1080 | + port->usb3_port_fake); |
---|
| 1081 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1082 | + } |
---|
| 1083 | + |
---|
951 | 1084 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); |
---|
952 | 1085 | value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << |
---|
953 | 1086 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | |
---|
.. | .. |
---|
965 | 1098 | |
---|
966 | 1099 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); |
---|
967 | 1100 | value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index); |
---|
968 | | - value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index); |
---|
| 1101 | + if (port->mode == USB_DR_MODE_UNKNOWN) |
---|
| 1102 | + value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(index); |
---|
| 1103 | + else if (port->mode == USB_DR_MODE_PERIPHERAL) |
---|
| 1104 | + value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(index); |
---|
| 1105 | + else if (port->mode == USB_DR_MODE_HOST) |
---|
| 1106 | + value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index); |
---|
| 1107 | + else if (port->mode == USB_DR_MODE_OTG) |
---|
| 1108 | + value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(index); |
---|
969 | 1109 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); |
---|
970 | 1110 | |
---|
971 | 1111 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); |
---|
.. | .. |
---|
997 | 1137 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); |
---|
998 | 1138 | value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK << |
---|
999 | 1139 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT); |
---|
1000 | | - value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18; |
---|
| 1140 | + if (port->mode == USB_DR_MODE_HOST) |
---|
| 1141 | + value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18; |
---|
| 1142 | + else |
---|
| 1143 | + value |= |
---|
| 1144 | + XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL << |
---|
| 1145 | + XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT; |
---|
1001 | 1146 | padctl_writel(padctl, value, |
---|
1002 | 1147 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); |
---|
1003 | 1148 | |
---|
1004 | | - err = regulator_enable(port->supply); |
---|
1005 | | - if (err) |
---|
1006 | | - 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 | + } |
---|
1007 | 1154 | |
---|
1008 | 1155 | mutex_lock(&padctl->lock); |
---|
1009 | 1156 | |
---|
.. | .. |
---|
1070 | 1217 | |
---|
1071 | 1218 | mutex_lock(&padctl->lock); |
---|
1072 | 1219 | |
---|
| 1220 | + if (port->usb3_port_fake != -1) { |
---|
| 1221 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1222 | + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( |
---|
| 1223 | + port->usb3_port_fake); |
---|
| 1224 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1225 | + |
---|
| 1226 | + usleep_range(100, 200); |
---|
| 1227 | + |
---|
| 1228 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1229 | + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( |
---|
| 1230 | + port->usb3_port_fake); |
---|
| 1231 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1232 | + |
---|
| 1233 | + usleep_range(250, 350); |
---|
| 1234 | + |
---|
| 1235 | + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1236 | + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( |
---|
| 1237 | + port->usb3_port_fake); |
---|
| 1238 | + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); |
---|
| 1239 | + |
---|
| 1240 | + value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); |
---|
| 1241 | + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->usb3_port_fake, |
---|
| 1242 | + XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED); |
---|
| 1243 | + padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); |
---|
| 1244 | + } |
---|
| 1245 | + |
---|
1073 | 1246 | if (WARN_ON(pad->enable == 0)) |
---|
1074 | 1247 | goto out; |
---|
1075 | 1248 | |
---|
.. | .. |
---|
1091 | 1264 | .exit = tegra210_usb2_phy_exit, |
---|
1092 | 1265 | .power_on = tegra210_usb2_phy_power_on, |
---|
1093 | 1266 | .power_off = tegra210_usb2_phy_power_off, |
---|
| 1267 | + .set_mode = tegra210_usb2_phy_set_mode, |
---|
1094 | 1268 | .owner = THIS_MODULE, |
---|
1095 | 1269 | }; |
---|
1096 | 1270 | |
---|
.. | .. |
---|
1233 | 1407 | struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); |
---|
1234 | 1408 | struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); |
---|
1235 | 1409 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
---|
1236 | | - struct tegra210_xusb_padctl *priv; |
---|
1237 | 1410 | unsigned int index = lane->index; |
---|
1238 | 1411 | u32 value; |
---|
1239 | 1412 | int err; |
---|
1240 | | - |
---|
1241 | | - priv = to_tegra210_xusb_padctl(padctl); |
---|
1242 | 1413 | |
---|
1243 | 1414 | err = regulator_enable(pad->supply); |
---|
1244 | 1415 | if (err) |
---|
.. | .. |
---|
1782 | 1953 | } |
---|
1783 | 1954 | |
---|
1784 | 1955 | static const struct tegra_xusb_port_ops tegra210_usb2_port_ops = { |
---|
| 1956 | + .release = tegra_xusb_usb2_port_release, |
---|
| 1957 | + .remove = tegra_xusb_usb2_port_remove, |
---|
1785 | 1958 | .enable = tegra210_usb2_port_enable, |
---|
1786 | 1959 | .disable = tegra210_usb2_port_disable, |
---|
1787 | 1960 | .map = tegra210_usb2_port_map, |
---|
.. | .. |
---|
1803 | 1976 | } |
---|
1804 | 1977 | |
---|
1805 | 1978 | static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = { |
---|
| 1979 | + .release = tegra_xusb_hsic_port_release, |
---|
1806 | 1980 | .enable = tegra210_hsic_port_enable, |
---|
1807 | 1981 | .disable = tegra210_hsic_port_disable, |
---|
1808 | 1982 | .map = tegra210_hsic_port_map, |
---|
.. | .. |
---|
1948 | 2122 | } |
---|
1949 | 2123 | |
---|
1950 | 2124 | static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = { |
---|
| 2125 | + .release = tegra_xusb_usb3_port_release, |
---|
| 2126 | + .remove = tegra_xusb_usb3_port_remove, |
---|
1951 | 2127 | .enable = tegra210_usb3_port_enable, |
---|
1952 | 2128 | .disable = tegra210_usb3_port_disable, |
---|
1953 | 2129 | .map = tegra210_usb3_port_map, |
---|
1954 | 2130 | }; |
---|
| 2131 | + |
---|
| 2132 | +static int tegra210_utmi_port_reset(struct phy *phy) |
---|
| 2133 | +{ |
---|
| 2134 | + struct tegra_xusb_padctl *padctl; |
---|
| 2135 | + struct tegra_xusb_lane *lane; |
---|
| 2136 | + u32 value; |
---|
| 2137 | + |
---|
| 2138 | + lane = phy_get_drvdata(phy); |
---|
| 2139 | + padctl = lane->pad->padctl; |
---|
| 2140 | + |
---|
| 2141 | + value = padctl_readl(padctl, |
---|
| 2142 | + XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(lane->index)); |
---|
| 2143 | + |
---|
| 2144 | + if ((value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP) || |
---|
| 2145 | + (value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN)) { |
---|
| 2146 | + tegra210_xusb_padctl_vbus_override(padctl, false); |
---|
| 2147 | + tegra210_xusb_padctl_vbus_override(padctl, true); |
---|
| 2148 | + return 1; |
---|
| 2149 | + } |
---|
| 2150 | + |
---|
| 2151 | + return 0; |
---|
| 2152 | +} |
---|
1955 | 2153 | |
---|
1956 | 2154 | static int |
---|
1957 | 2155 | tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse) |
---|
.. | .. |
---|
2015 | 2213 | .remove = tegra210_xusb_padctl_remove, |
---|
2016 | 2214 | .usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect, |
---|
2017 | 2215 | .hsic_set_idle = tegra210_hsic_set_idle, |
---|
| 2216 | + .vbus_override = tegra210_xusb_padctl_vbus_override, |
---|
| 2217 | + .utmi_port_reset = tegra210_utmi_port_reset, |
---|
| 2218 | +}; |
---|
| 2219 | + |
---|
| 2220 | +static const char * const tegra210_xusb_padctl_supply_names[] = { |
---|
| 2221 | + "avdd-pll-utmip", |
---|
| 2222 | + "avdd-pll-uerefe", |
---|
| 2223 | + "dvdd-pex-pll", |
---|
| 2224 | + "hvdd-pex-pll-e", |
---|
2018 | 2225 | }; |
---|
2019 | 2226 | |
---|
2020 | 2227 | const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { |
---|
.. | .. |
---|
2035 | 2242 | }, |
---|
2036 | 2243 | }, |
---|
2037 | 2244 | .ops = &tegra210_xusb_padctl_ops, |
---|
| 2245 | + .supply_names = tegra210_xusb_padctl_supply_names, |
---|
| 2246 | + .num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names), |
---|
| 2247 | + .need_fake_usb3_port = true, |
---|
2038 | 2248 | }; |
---|
2039 | 2249 | EXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc); |
---|
2040 | 2250 | |
---|