Skip to content

Commit de792a6

Browse files
Nagarjuna Kristamthierryreding
authored andcommitted
phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
Add support for set_mode on USB 2 phy. This allow XUSB host/device mode drivers to configure the hardware to corresponding modes. Signed-off-by: Nagarjuna Kristam <[email protected]> Acked-by: Kishon Vijay Abraham I <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 5a40fc4 commit de792a6

File tree

1 file changed

+104
-27
lines changed

1 file changed

+104
-27
lines changed

drivers/phy/tegra/xusb-tegra210.c

Lines changed: 104 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18
237237
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf
238238
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8
239+
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0
239240

240241
struct tegra210_xusb_fuse_calibration {
241242
u32 hs_curr_level[4];
@@ -935,6 +936,103 @@ static int tegra210_usb2_phy_exit(struct phy *phy)
935936
return tegra210_xusb_padctl_disable(lane->pad->padctl);
936937
}
937938

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+
9381036
static int tegra210_usb2_phy_power_on(struct phy *phy)
9391037
{
9401038
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -1048,9 +1146,11 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
10481146
padctl_writel(padctl, value,
10491147
XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
10501148

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+
}
10541154

10551155
mutex_lock(&padctl->lock);
10561156

@@ -1164,6 +1264,7 @@ static const struct phy_ops tegra210_usb2_phy_ops = {
11641264
.exit = tegra210_usb2_phy_exit,
11651265
.power_on = tegra210_usb2_phy_power_on,
11661266
.power_off = tegra210_usb2_phy_power_off,
1267+
.set_mode = tegra210_usb2_phy_set_mode,
11671268
.owner = THIS_MODULE,
11681269
};
11691270

@@ -2023,30 +2124,6 @@ static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
20232124
.map = tegra210_usb3_port_map,
20242125
};
20252126

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-
20502127
static int tegra210_utmi_port_reset(struct phy *phy)
20512128
{
20522129
struct tegra_xusb_padctl *padctl;

0 commit comments

Comments
 (0)