summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRakesh Bodla <rbodla@nvidia.com>2012-05-31 21:32:23 +0530
committerSimone Willett <swillett@nvidia.com>2012-06-01 13:07:10 -0700
commit2c596cbe2ed008c047a695e77aa687564c8cf74d (patch)
tree9218f18ad5fe2ef107b484b3c531452f72a0559a
parente1d8ccd5570853c102c17089d6f1aff37bae42bd (diff)
arm: tegra: usb: fix UTMIP auto suspend issues
Fixing the UTMIP auto suspend issues. Bug 992463 Bug 989400 Change-Id: Ia0d536cd66081b263f7f2bde5debcc600dcef22a Signed-off-by: Rakesh Bodla <rbodla@nvidia.com> Reviewed-on: http://git-master/r/105692 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/tegra3_usb_phy.c28
-rw-r--r--drivers/usb/host/ehci-tegra.c13
2 files changed, 34 insertions, 7 deletions
diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c
index 432dd5509664..b151eb61d5e9 100644
--- a/arch/arm/mach-tegra/tegra3_usb_phy.c
+++ b/arch/arm/mach-tegra/tegra3_usb_phy.c
@@ -1341,16 +1341,20 @@ static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
unsigned int inst = phy->inst;
DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-
- val = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
HOSTPC1_DEVLC_PSPD_MASK;
- if (val == USB_PHY_PORT_SPEED_HIGH) {
+
+ if (phy->port_speed == USB_PHY_PORT_SPEED_HIGH) {
/* Disable interrupts */
writel(0, base + USB_USBINTR);
/* Clear the run bit to stop SOFs - 2LS WAR */
val = readl(base + USB_USBCMD);
val &= ~USB_USBCMD_RS;
writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
}
val = readl(pmc_base + PMC_SLEEP_CFG);
@@ -1388,6 +1392,21 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
val |= UTMIP_PD_CHRG;
writel(val, base + UTMIP_BAT_CHRG_CFG0);
} else {
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ /* Disable interrupts */
+ writel(0, base + USB_USBINTR);
+
+ /* Clear the run bit to stop SOFs - 2LS WAR */
+ val = readl(base + USB_USBCMD);
+ val &= ~USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
utmip_setup_pmc_wake_detect(phy);
}
@@ -1409,9 +1428,6 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
utmi_phy_pad_power_off(phy);
- phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
- HOSTPC1_DEVLC_PSPD_MASK;
-
if (phy->pdata->u_data.host.hot_plug) {
bool enable_hotplug = true;
/* if it is OTG port then make sure to enable hot-plug feature
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c5fa8160bffe..98f3d5106a38 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -224,7 +224,7 @@ static int tegra_ehci_hub_control(
status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
/* Ensure the port PORT_SUSPEND and PORT_RESUME has cleared */
if (handshake(ehci, status_reg, (PORT_SUSPEND | PORT_RESUME), 0, 25000)) {
- pr_err("%s: timeout waiting for SUSPEND to clear\n", __func__);
+ EHCI_DBG("%s: timeout waiting for SUSPEND to clear\n", __func__);
}
tegra_usb_phy_post_resume(tegra->phy);
tegra->port_resuming = 0;
@@ -241,6 +241,11 @@ static int tegra_ehci_hub_control(
if (wValue == USB_PORT_FEAT_SUSPEND) {
tegra_usb_phy_pre_resume(tegra->phy, false);
tegra->port_resuming = 1;
+ } else if (wValue == USB_PORT_FEAT_ENABLE) {
+ u32 temp;
+ temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS;
+ ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]);
+ return retval;
}
break;
}
@@ -264,6 +269,12 @@ static int tegra_ehci_hub_control(
tegra_usb_phy_port_power(tegra->phy);
}
break;
+ case ClearPortFeature:
+ if (wValue == USB_PORT_FEAT_SUSPEND) {
+ /* tegra USB controller needs 25 ms to resume the port */
+ ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
+ }
+ break;
}
}