diff options
Diffstat (limited to 'drivers/phy/tegra')
-rw-r--r-- | drivers/phy/tegra/xusb-tegra186.c | 20 | ||||
-rw-r--r-- | drivers/phy/tegra/xusb.c | 8 | ||||
-rw-r--r-- | drivers/phy/tegra/xusb.h | 1 |
3 files changed, 25 insertions, 4 deletions
diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c index 1aae8535f452..0f60d5d1c167 100644 --- a/drivers/phy/tegra/xusb-tegra186.c +++ b/drivers/phy/tegra/xusb-tegra186.c @@ -145,6 +145,8 @@ #define MODE_HS MODE(0) #define MODE_RST MODE(1) +#define XUSB_AO_UTMIP_SLEEPWALK_STATUS(x) (0xa0 + (x) * 4) + #define XUSB_AO_UTMIP_SLEEPWALK_CFG(x) (0xd0 + (x) * 4) #define XUSB_AO_UHSIC_SLEEPWALK_CFG(x) (0xf0 + (x) * 4) #define FAKE_USBOP_VAL BIT(0) @@ -172,24 +174,30 @@ #define AP_A BIT(4) #define AN_A BIT(5) #define HIGHZ_A BIT(6) +#define MASTER_ENABLE_A BIT(7) /* phase B */ #define USBOP_RPD_B BIT(8) #define USBON_RPD_B BIT(9) #define AP_B BIT(12) #define AN_B BIT(13) #define HIGHZ_B BIT(14) +#define MASTER_ENABLE_B BIT(15) /* phase C */ #define USBOP_RPD_C BIT(16) #define USBON_RPD_C BIT(17) #define AP_C BIT(20) #define AN_C BIT(21) #define HIGHZ_C BIT(22) +#define MASTER_ENABLE_C BIT(23) /* phase D */ #define USBOP_RPD_D BIT(24) #define USBON_RPD_D BIT(25) #define AP_D BIT(28) #define AN_D BIT(29) #define HIGHZ_D BIT(30) +#define MASTER_ENABLE_D BIT(31) +#define MASTER_ENABLE_B_C_D \ + (MASTER_ENABLE_B | MASTER_ENABLE_C | MASTER_ENABLE_D) #define XUSB_AO_UHSIC_SLEEPWALK(x) (0x120 + (x) * 4) /* phase A */ @@ -417,6 +425,8 @@ static int tegra186_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, value |= HIGHZ_A; value |= AP_A; value |= AN_B | AN_C | AN_D; + if (padctl->soc->supports_lp_cfg_en) + value |= MASTER_ENABLE_B_C_D; break; case USB_SPEED_LOW: @@ -424,6 +434,8 @@ static int tegra186_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, value |= HIGHZ_A; value |= AN_A; value |= AP_B | AP_C | AP_D; + if (padctl->soc->supports_lp_cfg_en) + value |= MASTER_ENABLE_B_C_D; break; default: @@ -488,6 +500,13 @@ static int tegra186_utmi_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) value |= WAKE_VAL_NONE; ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + if (padctl->soc->supports_lp_cfg_en) { + /* disable the four stages of sleepwalk */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK(index)); + value &= ~(MASTER_ENABLE_A | MASTER_ENABLE_B_C_D); + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK(index)); + } + /* power down the line state detectors of the port */ value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); value |= USBOP_VAL_PD | USBON_VAL_PD; @@ -1673,6 +1692,7 @@ const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc = { .supports_gen2 = true, .poll_trk_completed = true, .trk_hw_mode = true, + .supports_lp_cfg_en = true, }; EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc); #endif diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 78045bd6c214..b55d4e9f42b5 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -805,6 +805,7 @@ static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl, usb2->base.lane = usb2->base.ops->map(&usb2->base); if (IS_ERR(usb2->base.lane)) { err = PTR_ERR(usb2->base.lane); + tegra_xusb_port_unregister(&usb2->base); goto out; } @@ -871,6 +872,7 @@ static int tegra_xusb_add_ulpi_port(struct tegra_xusb_padctl *padctl, ulpi->base.lane = ulpi->base.ops->map(&ulpi->base); if (IS_ERR(ulpi->base.lane)) { err = PTR_ERR(ulpi->base.lane); + tegra_xusb_port_unregister(&ulpi->base); goto out; } @@ -1267,7 +1269,7 @@ remove: return err; } -static int tegra_xusb_padctl_remove(struct platform_device *pdev) +static void tegra_xusb_padctl_remove(struct platform_device *pdev) { struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); int err; @@ -1285,8 +1287,6 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) dev_err(&pdev->dev, "failed to assert reset: %d\n", err); padctl->soc->ops->remove(padctl); - - return 0; } static __maybe_unused int tegra_xusb_padctl_suspend_noirq(struct device *dev) @@ -1321,7 +1321,7 @@ static struct platform_driver tegra_xusb_padctl_driver = { .pm = &tegra_xusb_padctl_pm_ops, }, .probe = tegra_xusb_padctl_probe, - .remove = tegra_xusb_padctl_remove, + .remove_new = tegra_xusb_padctl_remove, }; module_platform_driver(tegra_xusb_padctl_driver); diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h index 8bd6cd281119..6e45d194c689 100644 --- a/drivers/phy/tegra/xusb.h +++ b/drivers/phy/tegra/xusb.h @@ -434,6 +434,7 @@ struct tegra_xusb_padctl_soc { bool need_fake_usb3_port; bool poll_trk_completed; bool trk_hw_mode; + bool supports_lp_cfg_en; }; struct tegra_xusb_padctl { |