diff options
author | Venkata (Muni) Anda <muni@nvidia.com> | 2011-03-28 23:15:40 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-03-29 17:50:19 -0700 |
commit | db8872556e282e57992b28c3a0aade43ca5744f7 (patch) | |
tree | 8d7459c76bb8c245a13cce52b853d1e9f42f146d /drivers/usb | |
parent | d3c9f78e7ec505076ddad2aefaeef5e8c20a4823 (diff) |
usb: host: ehci-tegra: Wait for SOF before resume
Wait for Start Of Frame interrupt, then wait 20 us, before starting
port resume. Workaround for hardware issue that can cause the SOF to
be sent out at the same time as the phy speed change.
Change-Id: I91ccbd2902448e87aa3cdf1970305de22efa1c10
Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index a516af28c29b..8acf0c4366f7 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -25,6 +25,8 @@ #define TEGRA_USB_DMA_ALIGN 32 +#define STS_SRI (1<<7) /* SOF Recieved */ + struct tegra_ehci_hcd { struct ehci_hcd *ehci; struct tegra_usb_phy *phy; @@ -71,6 +73,7 @@ static int tegra_ehci_hub_control( struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); u32 __iomem *status_reg; u32 temp; + u32 usbsts_reg; unsigned long flags; int retval = 0; @@ -144,6 +147,26 @@ static int tegra_ehci_hub_control( ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); + ehci_dbg(ehci, "%s:USBSTS = 0x%x", __func__, + ehci_readl(ehci, &ehci->regs->status)); + usbsts_reg = ehci_readl(ehci, &ehci->regs->status); + ehci_writel(ehci, usbsts_reg, &ehci->regs->status); + usbsts_reg = ehci_readl(ehci, &ehci->regs->status); + udelay(20); + + if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000)) + pr_err("%s: timeout set for STS_SRI\n", __func__); + + usbsts_reg = ehci_readl(ehci, &ehci->regs->status); + ehci_writel(ehci, usbsts_reg, &ehci->regs->status); + + if (handshake(ehci, &ehci->regs->status, STS_SRI, 0, 2000)) + pr_err("%s: timeout clear STS_SRI\n", __func__); + + if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000)) + pr_err("%s: timeout set STS_SRI\n", __func__); + + udelay(20); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); /* start resume signalling */ ehci_writel(ehci, temp | PORT_RESUME, status_reg); |