forked from luck/tmp_suning_uos_patched
phy: tegra: xusb: Add set_mode support for UTMI phy on Tegra186
Add support for set_mode on UTMI 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
de792a6da7
commit
49d46e3c7e
|
@ -301,6 +301,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 +530,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,
|
||||
};
|
||||
|
||||
|
@ -857,28 +949,6 @@ 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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user