summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorVenkata (Muni) Anda <muni@nvidia.com>2011-03-28 23:15:40 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:37:02 -0800
commite60f96e364a97ff2d1ab9bd0a5b58a4e3b3760f3 (patch)
treec727ebae79c4d0561725d550b7598be861a090c1 /drivers/usb
parent1acb3ddfeaf05647bae0d9a62ca14c7d2f2d5b9c (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 94764ad5c43f..748e31cf1815 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;
@@ -136,6 +138,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;
@@ -216,6 +219,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);