| .. | .. |
|---|
| 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 | |
|---|