summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-03-09 12:03:18 -0700
committerOlof Johansson <olof@lixom.net>2014-03-09 12:03:18 -0700
commit1760e4f855a2ead08a40deac9abd4fb8cdf3af32 (patch)
tree8ee1c79f4c46fd225d90e832def3d7f7e3742086 /drivers/usb/host/ehci-hub.c
parent1e871089f66416ce540d8e362225a0878a5d2c06 (diff)
parentc8ae7e9bfc8caf679e891c4f0a04f2435b45e2da (diff)
Merge tag 'imx-soc-3.15' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc
i.MX SoC changes for 3.15 from Shawn Guo: - Support suspend from ocram (DDR IO floating) for imx6 platforms - Add cpuidle support for imx6sl - Sparse warning fixes for imx6sl and vf610 clock code - Remove PWM platform code - Support ptp and rmii clock from pad - Support WEIM CS GPR configuration - Random cleanups and defconfig updates * tag 'imx-soc-3.15' of git://git.linaro.org/people/shawnguo/linux-2.6: (373 commits) ARM: imx6: drop .text.head section annotation from headsmp.S ARM: imx6: build suspend-imx6.o with CONFIG_SOC_IMX6 ARM: imx6: rename pm-imx6q.c to pm-imx6.c ARM: imx6: introduce CONFIG_SOC_IMX6 for i.MX6 common stuff ARM: imx6: do not call imx6q_suspend_init() with !CONFIG_SUSPEND ARM: imx6: call suspend_set_ops() from suspend routine ARM: imx6: build headsmp.o only on CONFIG_SMP ARM: imx6: move v7_cpu_resume() into suspend-imx6.S ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority ARM: imx6q: Add GPR6 and GPR7 register definitions for iomuxc gpr bus: imx-weim: support CS GPR configuration ARM: mach-imx: Kconfig: Remove IMX_HAVE_PLATFORM_IMX2_WDT from SOC_IMX53 ARM: imx_v6_v7_defconfig: Select CONFIG_DEBUG_FS ARM: mach-imx: Select CONFIG_SRAM at ARCH_MXC level ARM: imx: add speed grading check for i.mx6 soc ARM: imx: avoid calling clk APIs in idle thread which may cause schedule ARM: imx6q: support ptp and rmii clock from pad ARM: imx6q: remove unneeded clk lookups ARM: imx_v6_v7_defconfig: Select CONFIG_MMC_UNSAFE_RESUME ARM: imx_v4_v5_defconfig: Select CONFIG_MMC_UNSAFE_RESUME ...
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 47b858fc50b2..7ae0c4d51741 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
int port;
int mask;
int changed;
+ bool fs_idle_delay;
ehci_dbg(ehci, "suspend root hub\n");
@@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->bus_suspended = 0;
ehci->owned_ports = 0;
changed = 0;
+ fs_idle_delay = false;
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
@@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
}
if (t1 != t2) {
+ /*
+ * On some controllers, Wake-On-Disconnect will
+ * generate false wakeup signals until the bus
+ * switches over to full-speed idle. For their
+ * sake, add a delay if we need one.
+ */
+ if ((t2 & PORT_WKDISC_E) &&
+ ehci_port_speed(ehci, t2) ==
+ USB_PORT_STAT_HIGH_SPEED)
+ fs_idle_delay = true;
ehci_writel(ehci, t2, reg);
changed = 1;
}
}
+ spin_unlock_irq(&ehci->lock);
+
+ if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
+ /*
+ * Wait for HCD to enter low-power mode or for the bus
+ * to switch to full-speed idle.
+ */
+ usleep_range(5000, 5500);
+ }
if (changed && ehci->has_tdi_phy_lpm) {
- spin_unlock_irq(&ehci->lock);
- msleep(5); /* 5 ms for HCD to enter low-power mode */
spin_lock_irq(&ehci->lock);
-
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port];
@@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
port, (t3 & HOSTPC_PHCD) ?
"succeeded" : "failed");
}
+ spin_unlock_irq(&ehci->lock);
}
- spin_unlock_irq(&ehci->lock);
/* Apparently some devices need a >= 1-uframe delay here */
if (ehci->bus_suspended)