summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-omap.c')
-rw-r--r--drivers/usb/host/ehci-omap.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index a67a0030dd5..5450e628157 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -116,6 +116,8 @@
#define OMAP_UHH_DEBUG_CSR (0x44)
/* EHCI Register Set */
+#define EHCI_INSNREG04 (0xA0)
+#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
#define EHCI_INSNREG05_ULPI (0xA4)
#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31
#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24
@@ -181,7 +183,7 @@ struct ehci_hcd_omap {
void __iomem *ehci_base;
/* Regulators for USB PHYs.
- * Each PHY can have a seperate regulator.
+ * Each PHY can have a separate regulator.
*/
struct regulator *regulator[OMAP3_HS_USB_PORTS];
};
@@ -352,8 +354,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
/* Bypass the TLL module for PHY mode operation */
- if (omap_rev() <= OMAP3430_REV_ES2_1) {
- dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n");
+ if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
+ dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
@@ -382,6 +384,18 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
+ /*
+ * An undocumented "feature" in the OMAP3 EHCI controller,
+ * causes suspended ports to be taken out of suspend when
+ * the USBCMD.Run/Stop bit is cleared (for example when
+ * we do ehci_bus_suspend).
+ * This breaks suspend-resume if the root-hub is allowed
+ * to suspend. Writing 1 to this undocumented register bit
+ * disables this feature and restores normal behavior.
+ */
+ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
+ EHCI_INSNREG04_DISABLE_UNSUSPEND);
+
if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
@@ -629,11 +643,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}
snprintf(supply, sizeof(supply), "hsusb%d", i);
omap->regulator[i] = regulator_get(omap->dev, supply);
- if (IS_ERR(omap->regulator[i]))
+ if (IS_ERR(omap->regulator[i])) {
+ omap->regulator[i] = NULL;
dev_dbg(&pdev->dev,
"failed to get ehci port%d regulator\n", i);
- else
+ } else {
regulator_enable(omap->regulator[i]);
+ }
}
ret = omap_start_ehc(omap, hcd);
@@ -657,6 +673,9 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_add_hcd;
}
+ /* root ports should always stay powered */
+ ehci_port_power(omap->ehci, 1);
+
return 0;
err_add_hcd: