summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorVenkata (Muni) Anda <muni@nvidia.com>2011-03-28 23:15:40 -0700
committerColin Cross <ccross@android.com>2011-03-29 17:50:19 -0700
commitdb8872556e282e57992b28c3a0aade43ca5744f7 (patch)
tree8d7459c76bb8c245a13cce52b853d1e9f42f146d /drivers/usb
parentd3c9f78e7ec505076ddad2aefaeef5e8c20a4823 (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.c23
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);