summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorDinh Nguyen <r00091@freescale.com>2009-09-16 11:31:02 -0500
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-02-12 17:19:13 +0100
commitbe490e5431216bef29eefedde905a45e22d05477 (patch)
treea6a2da8cc60df6b2616b887ee3b7136ad14a3f56 /drivers/usb
parentaca8630a75798e500a0bc64c05346a4089b2fda7 (diff)
usb: add ehci otg support
Add OTG support to ehci host controllers Signed-off-by: Dinh Nguyen <r00091@freescale.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hub.c8
-rw-r--r--drivers/usb/host/ehci-hub.c31
-rw-r--r--drivers/usb/host/ehci.h5
3 files changed, 44 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 71f86c60d83c..5acf9757b09a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1160,6 +1160,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -E2BIG;
}
+ /* With OTG enabled, suspending root hub results in gadget not
+ * working because gadget uses the same root hub. We disable
+ * this feature when OTG is selected.
+ */
+#if defined(CONFIG_PM) && defined(CONFIG_USB_EHCI_ARC_OTG)
+ hdev->autosuspend_disabled = 1;
+#endif
+
#ifdef CONFIG_USB_OTG_BLACKLIST_HUB
if (hdev->parent) {
dev_warn(&intf->dev, "ignoring external hub\n");
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index f46ad27c9a90..615d263c57c1 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -549,6 +549,37 @@ ehci_hub_descriptor (
desc->wHubCharacteristics = cpu_to_le16(temp);
}
+#ifdef CONFIG_USB_OTG
+static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ u32 status;
+
+ if (!port)
+ return -EINVAL;
+ port--;
+
+ /* start port reset before HNP protocol time out */
+ status = readl(&ehci->regs->port_status[port]);
+ if (!(status & PORT_CONNECT))
+ return -ENODEV;
+
+ /* khubd will finish the reset later */
+ if (ehci_is_TDI(ehci))
+ writel(PORT_RESET | (status & ~(PORT_CSC | PORT_PEC
+ | PORT_OCC)), &ehci->regs->port_status[port]);
+ else
+ writel(PORT_RESET, &ehci->regs->port_status[port]);
+
+ return 0;
+}
+#else
+static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
+{
+ return 0;
+}
+#endif /* CONFIG_USB_OTG */
+
/*-------------------------------------------------------------------------*/
static int ehci_hub_control (
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2bfff30f4704..5947f6c19567 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -138,6 +138,11 @@ struct ehci_hcd { /* one per controller */
u8 sbrn; /* packed release number */
+ /*
+ * OTG controllers and transceivers need software interaction;
+ * other external transceivers should be software-transparent
+ */
+ struct otg_transceiver *transceiver;
/* irq statistics */
#ifdef EHCI_STATS
struct ehci_stats stats;