Commit f62c1930 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'tegra-for-5.7-usb-v2' of...

Merge tag 'tegra-for-5.7-usb-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into usb-next

Thierry writes:

usb: tegra: Changes for v5.7-rc1

These changes add USB OTG support for the XUSB host and XUSB device
controllers found on NVIDIA Tegra SoCs.

* tag 'tegra-for-5.7-usb-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  usb: gadget: tegra-xudc: Support multiple device modes
  usb: gadget: tegra-xudc: Use phy_set_mode() to set/unset device mode
  usb: gadget: tegra-xudc: Add usb-phy support
  usb: gadget: tegra-xudc: Remove usb-role-switch support
  usb: xhci-tegra: Add OTG support
  phy: tegra: Select USB_PHY
  phy: tegra: Don't use device-managed API to allocate ports
  phy: tegra: Fix regulator leak
  phy: tegra: Print -EPROBE_DEFER error message at debug level
  phy: tegra: xusb: Don't warn on probe defer
  phy: tegra: xusb: Add Tegra194 support
  phy: tegra: xusb: Protect Tegra186 soc with config
  phy: tegra: xusb: Add set_mode support for UTMI phy on Tegra186
  phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
  phy: tegra: xusb: Add support to get companion USB 3 port
  phy: tegra: xusb: Add usb-phy support
  phy: tegra: xusb: Add usb-role-switch support
parents 23a73711 b4e19931
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
config PHY_TEGRA_XUSB
	tristate "NVIDIA Tegra XUSB pad controller driver"
	depends on ARCH_TEGRA
	select USB_CONN_GPIO
	select USB_PHY
	help
	  Choose this option if you have an NVIDIA Tegra SoC.

+1 −0
Original line number Diff line number Diff line
@@ -6,4 +6,5 @@ phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_124_SOC) += xusb-tegra124.o
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_186_SOC) += xusb-tegra186.o
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_194_SOC) += xusb-tegra186.o
obj-$(CONFIG_PHY_TEGRA194_P2U) += phy-tegra194-p2u.o
+6 −0
Original line number Diff line number Diff line
@@ -1422,6 +1422,8 @@ tegra124_usb2_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra124_usb2_port_ops = {
	.release = tegra_xusb_usb2_port_release,
	.remove = tegra_xusb_usb2_port_remove,
	.enable = tegra124_usb2_port_enable,
	.disable = tegra124_usb2_port_disable,
	.map = tegra124_usb2_port_map,
@@ -1443,6 +1445,7 @@ tegra124_ulpi_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = {
	.release = tegra_xusb_ulpi_port_release,
	.enable = tegra124_ulpi_port_enable,
	.disable = tegra124_ulpi_port_disable,
	.map = tegra124_ulpi_port_map,
@@ -1464,6 +1467,7 @@ tegra124_hsic_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra124_hsic_port_ops = {
	.release = tegra_xusb_hsic_port_release,
	.enable = tegra124_hsic_port_enable,
	.disable = tegra124_hsic_port_disable,
	.map = tegra124_hsic_port_map,
@@ -1647,6 +1651,8 @@ tegra124_usb3_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = {
	.release = tegra_xusb_usb3_port_release,
	.remove = tegra_xusb_usb3_port_remove,
	.enable = tegra124_usb3_port_enable,
	.disable = tegra124_usb3_port_disable,
	.map = tegra124_usb3_port_map,
+208 −57
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@
#define  SSPX_ELPG_CLAMP_EN(x)			BIT(0 + (x) * 3)
#define  SSPX_ELPG_CLAMP_EN_EARLY(x)		BIT(1 + (x) * 3)
#define  SSPX_ELPG_VCORE_DOWN(x)		BIT(2 + (x) * 3)
#define XUSB_PADCTL_SS_PORT_CFG			0x2c
#define   PORTX_SPEED_SUPPORT_SHIFT(x)		((x) * 4)
#define   PORTX_SPEED_SUPPORT_MASK		(0x3)
#define     PORT_SPEED_SUPPORT_GEN1		(0x0)

#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x)	(0x88 + (x) * 0x40)
#define  HS_CURR_LEVEL(x)			((x) & 0x3f)
@@ -301,6 +305,97 @@ static void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
	tegra186_utmi_bias_pad_power_off(padctl);
}

static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
					       bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, USB2_VBUS_ID);

	if (status) {
		value |= VBUS_OVERRIDE;
		value &= ~ID_OVERRIDE(~0);
		value |= ID_OVERRIDE_FLOATING;
	} else {
		value &= ~VBUS_OVERRIDE;
	}

	padctl_writel(padctl, value, USB2_VBUS_ID);

	return 0;
}

static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
					    bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, USB2_VBUS_ID);

	if (status) {
		if (value & VBUS_OVERRIDE) {
			value &= ~VBUS_OVERRIDE;
			padctl_writel(padctl, value, USB2_VBUS_ID);
			usleep_range(1000, 2000);

			value = padctl_readl(padctl, USB2_VBUS_ID);
		}

		value &= ~ID_OVERRIDE(~0);
		value |= ID_OVERRIDE_GROUNDED;
	} else {
		value &= ~ID_OVERRIDE(~0);
		value |= ID_OVERRIDE_FLOATING;
	}

	padctl_writel(padctl, value, USB2_VBUS_ID);

	return 0;
}

static int tegra186_utmi_phy_set_mode(struct phy *phy, enum phy_mode mode,
				      int submode)
{
	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
	struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl,
								lane->index);
	int err = 0;

	mutex_lock(&padctl->lock);

	dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode);

	if (mode == PHY_MODE_USB_OTG) {
		if (submode == USB_ROLE_HOST) {
			tegra186_xusb_padctl_id_override(padctl, true);

			err = regulator_enable(port->supply);
		} else if (submode == USB_ROLE_DEVICE) {
			tegra186_xusb_padctl_vbus_override(padctl, true);
		} else if (submode == USB_ROLE_NONE) {
			/*
			 * When port is peripheral only or role transitions to
			 * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
			 * enabled.
			 */
			if (regulator_is_enabled(port->supply))
				regulator_disable(port->supply);

			tegra186_xusb_padctl_id_override(padctl, false);
			tegra186_xusb_padctl_vbus_override(padctl, false);
		}
	}

	mutex_unlock(&padctl->lock);

	return err;
}

static int tegra186_utmi_phy_power_on(struct phy *phy)
{
	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -439,6 +534,7 @@ static const struct phy_ops utmi_phy_ops = {
	.exit = tegra186_utmi_phy_exit,
	.power_on = tegra186_utmi_phy_power_on,
	.power_off = tegra186_utmi_phy_power_off,
	.set_mode = tegra186_utmi_phy_set_mode,
	.owner = THIS_MODULE,
};

@@ -503,19 +599,6 @@ static const char * const tegra186_usb2_functions[] = {
	"xusb",
};

static const struct tegra_xusb_lane_soc tegra186_usb2_lanes[] = {
	TEGRA186_LANE("usb2-0", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-1", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-2", 0,  0, 0, usb2),
};

static const struct tegra_xusb_pad_soc tegra186_usb2_pad = {
	.name = "usb2",
	.num_lanes = ARRAY_SIZE(tegra186_usb2_lanes),
	.lanes = tegra186_usb2_lanes,
	.ops = &tegra186_usb2_pad_ops,
};

static int tegra186_usb2_port_enable(struct tegra_xusb_port *port)
{
	return 0;
@@ -532,6 +615,8 @@ tegra186_usb2_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra186_usb2_port_ops = {
	.release = tegra_xusb_usb2_port_release,
	.remove = tegra_xusb_usb2_port_remove,
	.enable = tegra186_usb2_port_enable,
	.disable = tegra186_usb2_port_disable,
	.map = tegra186_usb2_port_map,
@@ -591,6 +676,8 @@ tegra186_usb3_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra186_usb3_port_ops = {
	.release = tegra_xusb_usb3_port_release,
	.remove = tegra_xusb_usb3_port_remove,
	.enable = tegra186_usb3_port_enable,
	.disable = tegra186_usb3_port_disable,
	.map = tegra186_usb3_port_map,
@@ -635,6 +722,15 @@ static int tegra186_usb3_phy_power_on(struct phy *phy)

	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_CAP);

	if (padctl->soc->supports_gen2 && port->disable_gen2) {
		value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_CFG);
		value &= ~(PORTX_SPEED_SUPPORT_MASK <<
			PORTX_SPEED_SUPPORT_SHIFT(index));
		value |= (PORT_SPEED_SUPPORT_GEN1 <<
			PORTX_SPEED_SUPPORT_SHIFT(index));
		padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_CFG);
	}

	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_1);
	value &= ~SSPX_ELPG_VCORE_DOWN(index);
	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_1);
@@ -765,27 +861,6 @@ static const char * const tegra186_usb3_functions[] = {
	"xusb",
};

static const struct tegra_xusb_lane_soc tegra186_usb3_lanes[] = {
	TEGRA186_LANE("usb3-0", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-1", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-2", 0,  0, 0, usb3),
};

static const struct tegra_xusb_pad_soc tegra186_usb3_pad = {
	.name = "usb3",
	.num_lanes = ARRAY_SIZE(tegra186_usb3_lanes),
	.lanes = tegra186_usb3_lanes,
	.ops = &tegra186_usb3_pad_ops,
};

static const struct tegra_xusb_pad_soc * const tegra186_pads[] = {
	&tegra186_usb2_pad,
	&tegra186_usb3_pad,
#if 0 /* TODO implement */
	&tegra186_hsic_pad,
#endif
};

static int
tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)
{
@@ -802,7 +877,9 @@ tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)

	err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
	if (err) {
		dev_err(dev, "failed to read calibration fuse: %d\n", err);
		if (err != -EPROBE_DEFER)
			dev_err(dev, "failed to read calibration fuse: %d\n",
				err);
		return err;
	}

@@ -857,34 +934,13 @@ static void tegra186_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
{
}

static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
					       bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, USB2_VBUS_ID);

	if (status) {
		value |= VBUS_OVERRIDE;
		value &= ~ID_OVERRIDE(~0);
		value |= ID_OVERRIDE_FLOATING;
	} else {
		value &= ~VBUS_OVERRIDE;
	}

	padctl_writel(padctl, value, USB2_VBUS_ID);

	return 0;
}

static const struct tegra_xusb_padctl_ops tegra186_xusb_padctl_ops = {
	.probe = tegra186_xusb_padctl_probe,
	.remove = tegra186_xusb_padctl_remove,
	.vbus_override = tegra186_xusb_padctl_vbus_override,
};

#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
static const char * const tegra186_xusb_padctl_supply_names[] = {
	"avdd-pll-erefeut",
	"avdd-usb",
@@ -892,6 +948,40 @@ static const char * const tegra186_xusb_padctl_supply_names[] = {
	"vddio-hsic",
};

static const struct tegra_xusb_lane_soc tegra186_usb2_lanes[] = {
	TEGRA186_LANE("usb2-0", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-1", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-2", 0,  0, 0, usb2),
};

static const struct tegra_xusb_pad_soc tegra186_usb2_pad = {
	.name = "usb2",
	.num_lanes = ARRAY_SIZE(tegra186_usb2_lanes),
	.lanes = tegra186_usb2_lanes,
	.ops = &tegra186_usb2_pad_ops,
};

static const struct tegra_xusb_lane_soc tegra186_usb3_lanes[] = {
	TEGRA186_LANE("usb3-0", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-1", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-2", 0,  0, 0, usb3),
};

static const struct tegra_xusb_pad_soc tegra186_usb3_pad = {
	.name = "usb3",
	.num_lanes = ARRAY_SIZE(tegra186_usb3_lanes),
	.lanes = tegra186_usb3_lanes,
	.ops = &tegra186_usb3_pad_ops,
};

static const struct tegra_xusb_pad_soc * const tegra186_pads[] = {
	&tegra186_usb2_pad,
	&tegra186_usb3_pad,
#if 0 /* TODO implement */
	&tegra186_hsic_pad,
#endif
};

const struct tegra_xusb_padctl_soc tegra186_xusb_padctl_soc = {
	.num_pads = ARRAY_SIZE(tegra186_pads),
	.pads = tegra186_pads,
@@ -916,6 +1006,67 @@ const struct tegra_xusb_padctl_soc tegra186_xusb_padctl_soc = {
	.num_supplies = ARRAY_SIZE(tegra186_xusb_padctl_supply_names),
};
EXPORT_SYMBOL_GPL(tegra186_xusb_padctl_soc);
#endif

#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
static const char * const tegra194_xusb_padctl_supply_names[] = {
	"avdd-usb",
	"vclamp-usb",
};

static const struct tegra_xusb_lane_soc tegra194_usb2_lanes[] = {
	TEGRA186_LANE("usb2-0", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-1", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-2", 0,  0, 0, usb2),
	TEGRA186_LANE("usb2-3", 0,  0, 0, usb2),
};

static const struct tegra_xusb_pad_soc tegra194_usb2_pad = {
	.name = "usb2",
	.num_lanes = ARRAY_SIZE(tegra194_usb2_lanes),
	.lanes = tegra194_usb2_lanes,
	.ops = &tegra186_usb2_pad_ops,
};

static const struct tegra_xusb_lane_soc tegra194_usb3_lanes[] = {
	TEGRA186_LANE("usb3-0", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-1", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-2", 0,  0, 0, usb3),
	TEGRA186_LANE("usb3-3", 0,  0, 0, usb3),
};

static const struct tegra_xusb_pad_soc tegra194_usb3_pad = {
	.name = "usb3",
	.num_lanes = ARRAY_SIZE(tegra194_usb3_lanes),
	.lanes = tegra194_usb3_lanes,
	.ops = &tegra186_usb3_pad_ops,
};

static const struct tegra_xusb_pad_soc * const tegra194_pads[] = {
	&tegra194_usb2_pad,
	&tegra194_usb3_pad,
};

const struct tegra_xusb_padctl_soc tegra194_xusb_padctl_soc = {
	.num_pads = ARRAY_SIZE(tegra194_pads),
	.pads = tegra194_pads,
	.ports = {
		.usb2 = {
			.ops = &tegra186_usb2_port_ops,
			.count = 4,
		},
		.usb3 = {
			.ops = &tegra186_usb3_port_ops,
			.count = 4,
		},
	},
	.ops = &tegra186_xusb_padctl_ops,
	.supply_names = tegra194_xusb_padctl_supply_names,
	.num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names),
	.supports_gen2 = true,
};
EXPORT_SYMBOL_GPL(tegra194_xusb_padctl_soc);
#endif

MODULE_AUTHOR("JC Kuo <jckuo@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra186 XUSB Pad Controller driver");
+109 −27
Original line number Diff line number Diff line
@@ -236,6 +236,7 @@
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8
#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0

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

static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
					      bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);

	if (status) {
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
	} else {
		value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
	}

	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);

	return 0;
}

static int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
					    bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);

	if (status) {
		if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) {
			value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
			padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
			usleep_range(1000, 2000);

			value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
		}

		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED <<
			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
	} else {
		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
	}

	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);

	return 0;
}

static int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode,
				      int submode)
{
	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
	struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl,
								lane->index);
	int err = 0;

	mutex_lock(&padctl->lock);

	dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode);

	if (mode == PHY_MODE_USB_OTG) {
		if (submode == USB_ROLE_HOST) {
			tegra210_xusb_padctl_id_override(padctl, true);

			err = regulator_enable(port->supply);
		} else if (submode == USB_ROLE_DEVICE) {
			tegra210_xusb_padctl_vbus_override(padctl, true);
		} else if (submode == USB_ROLE_NONE) {
			/*
			 * When port is peripheral only or role transitions to
			 * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
			 * be enabled.
			 */
			if (regulator_is_enabled(port->supply))
				regulator_disable(port->supply);

			tegra210_xusb_padctl_id_override(padctl, false);
			tegra210_xusb_padctl_vbus_override(padctl, false);
		}
	}

	mutex_unlock(&padctl->lock);

	return err;
}

static int tegra210_usb2_phy_power_on(struct phy *phy)
{
	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -1048,9 +1146,11 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
	padctl_writel(padctl, value,
		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));

	if (port->supply && port->mode == USB_DR_MODE_HOST) {
		err = regulator_enable(port->supply);
		if (err)
			return err;
	}

	mutex_lock(&padctl->lock);

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

@@ -1852,6 +1953,8 @@ tegra210_usb2_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra210_usb2_port_ops = {
	.release = tegra_xusb_usb2_port_release,
	.remove = tegra_xusb_usb2_port_remove,
	.enable = tegra210_usb2_port_enable,
	.disable = tegra210_usb2_port_disable,
	.map = tegra210_usb2_port_map,
@@ -1873,6 +1976,7 @@ tegra210_hsic_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = {
	.release = tegra_xusb_hsic_port_release,
	.enable = tegra210_hsic_port_enable,
	.disable = tegra210_hsic_port_disable,
	.map = tegra210_hsic_port_map,
@@ -2018,35 +2122,13 @@ tegra210_usb3_port_map(struct tegra_xusb_port *port)
}

static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
	.release = tegra_xusb_usb3_port_release,
	.remove = tegra_xusb_usb3_port_remove,
	.enable = tegra210_usb3_port_enable,
	.disable = tegra210_usb3_port_disable,
	.map = tegra210_usb3_port_map,
};

static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
					      bool status)
{
	u32 value;

	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);

	if (status) {
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
	} else {
		value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
	}

	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);

	return 0;
}

static int tegra210_utmi_port_reset(struct phy *phy)
{
	struct tegra_xusb_padctl *padctl;
Loading