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 <nkristam@nvidia.com> Acked-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
5a40fc4b93
commit
de792a6da7
|
@ -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));
|
||||
|
||||
err = regulator_enable(port->supply);
|
||||
if (err)
|
||||
return err;
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -2023,30 +2124,6 @@ static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
|
|||
.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…
Reference in New Issue