[PATCH 1/3] ehci: Support for Intel Moorestown MPH and OTG host

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Alek Du <alek.du@xxxxxxxxx>

The Intel Moorestown platform has EHCI MPH and EHCI OTG host. This patch adds
PCI probe part for them. The HNP part and SRAM part will be added later.

Signed-off-by: Jacob Pan <jacob.jun.pan@xxxxxxxxx>
Signed-off-by: Alek Du <alek.du@xxxxxxxxx>
Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx>
Signed-off-by: Dirk Brandewie <dirk.brandewie@xxxxxxxxx>
---

 drivers/usb/core/hub.c      |   10 ++++++++++
 drivers/usb/core/usb.h      |    1 -
 drivers/usb/host/ehci-hcd.c |   19 +++++++++++++++++++
 drivers/usb/host/ehci-hub.c |   13 +++++++++++--
 drivers/usb/host/ehci-pci.c |   15 +++++++++++++++
 drivers/usb/host/ehci.h     |    6 ++++++
 include/linux/usb/hcd.h     |    6 ++++++
 7 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5ca3714..df2215f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1614,6 +1614,14 @@ static void hub_free_dev(struct usb_device *udev)
 		hcd->driver->free_dev(hcd, udev);
 }
 
+static void otg_notify(struct usb_device *udev, unsigned action)
+{
+	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+	if (hcd->otg_notify)
+		hcd->otg_notify(udev, action);
+}
+
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
  * @pdev: pointer to device being disconnected
@@ -1670,6 +1678,7 @@ void usb_disconnect(struct usb_device **pdev)
 	 * notifier chain (used by usbfs and possibly others).
 	 */
 	device_del(&udev->dev);
+	otg_notify(udev, USB_DEVICE_REMOVE);
 
 	/* Free the device number and delete the parent's children[]
 	 * (or root_hub) pointer.
@@ -1900,6 +1909,7 @@ int usb_new_device(struct usb_device *udev)
 		dev_err(&udev->dev, "can't device_add, error %d\n", err);
 		goto fail;
 	}
+	otg_notify(udev, USB_DEVICE_ADD);
 
 	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
 	usb_mark_last_busy(udev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index d44d4b7..e369957 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -161,4 +161,3 @@ extern void usb_notify_add_device(struct usb_device *udev);
 extern void usb_notify_remove_device(struct usb_device *udev);
 extern void usb_notify_add_bus(struct usb_bus *ubus);
 extern void usb_notify_remove_bus(struct usb_bus *ubus);
-
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8696489..ee2a382 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -47,6 +47,8 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/langwell_otg.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -1179,6 +1181,10 @@ MODULE_LICENSE ("GPL");
 #ifdef CONFIG_PCI
 #include "ehci-pci.c"
 #define	PCI_DRIVER		ehci_pci_driver
+#ifdef CONFIG_USB_LANGWELL_OTG
+#include "ehci-langwell-pci.c"
+#define LNW_OTG_HOST_DRIVER    ehci_otg_driver
+#endif
 #endif
 
 #ifdef CONFIG_USB_EHCI_FSL
@@ -1363,8 +1369,18 @@ static int __init ehci_hcd_init(void)
 	if (retval < 0)
 		goto clean4;
 #endif
+
+#ifdef LNW_OTG_HOST_DRIVER
+	retval = langwell_register_host(&LNW_OTG_HOST_DRIVER);
+	if (retval < 0)
+		goto clean5;
+#endif
 	return retval;
 
+#ifdef LNW_OTG_HOST_DRIVER
+clean5:
+	langwell_unregister_host(&LNW_OTG_HOST_DRIVER);
+#endif
 #ifdef XILINX_OF_PLATFORM_DRIVER
 	/* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */
 clean4:
@@ -1397,6 +1413,9 @@ module_init(ehci_hcd_init);
 
 static void __exit ehci_hcd_cleanup(void)
 {
+#ifdef LNW_OTG_HOST_DRIVER
+	langwell_unregister_host(&LNW_OTG_HOST_DRIVER);
+#endif
 #ifdef XILINX_OF_PLATFORM_DRIVER
 	platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
 #endif
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 77bbb23..c052d1c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -207,6 +207,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 	int			port;
 	int			mask;
 	int			changed;
+	int			rc = 0;
 
 	ehci_dbg(ehci, "suspend root hub\n");
 
@@ -324,13 +325,17 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 	ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
+
+	if (ehci->has_otg && ehci->otg_suspend)
+		rc = ehci->otg_suspend(hcd);
+
 	spin_unlock_irq (&ehci->lock);
 
 	/* ehci_work() may have re-enabled the watchdog timer, which we do not
 	 * want, and so we must delete any pending watchdog timer events.
 	 */
 	del_timer_sync(&ehci->watchdog);
-	return 0;
+	return rc;
 }
 
 
@@ -342,6 +347,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	u32			power_okay;
 	int			i;
 	unsigned long		resume_needed = 0;
+	int			rc = 0;
 
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
@@ -454,9 +460,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	/* Now we can safely re-enable irqs */
 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
 
+	if (ehci->has_otg && ehci->otg_resume)
+		rc = ehci->otg_resume(hcd);
+
 	spin_unlock_irq (&ehci->lock);
 	ehci_handover_companion_ports(ehci);
-	return 0;
+	return rc;
 }
 
 #else
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 8311de7..f4e718c 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -53,6 +53,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	u8			rev;
 	u32			temp;
 	int			retval;
+	int			force_otg_hc_mode = 0;
 
 	switch (pdev->vendor) {
 	case PCI_VENDOR_ID_TOSHIBA_2:
@@ -66,6 +67,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 #endif
 		}
 		break;
+	case PCI_VENDOR_ID_INTEL:
+		if (pdev->device == 0x0811) {
+			ehci_info(ehci, "Detected Langwell OTG HC\n");
+			hcd->has_tt = 1;
+			ehci->has_hostpc = 1;
+			ehci->has_otg = 1;
+			force_otg_hc_mode = 1;
+		} else if (pdev->device == 0x0806) {
+			ehci_info(ehci, "Detected Langwell MPH\n");
+			hcd->has_tt = 1;
+			ehci->has_hostpc = 1;
+		}
 	}
 
 	ehci->caps = hcd->regs;
@@ -101,6 +114,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	if (force_otg_hc_mode)
+		ehci_reset(ehci);
 
 	retval = ehci_halt(ehci);
 	if (retval)
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index c161d97..264051a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -158,6 +158,8 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		has_hostpc:1;
 	unsigned		has_lpm:1;  /* support link power management */
 	unsigned		has_ppcd:1; /* support per-port change bits */
+
+	unsigned		has_otg:1;	/* if it is otg host*/
 	u8			sbrn;		/* packed release number */
 
 	/* irq statistics */
@@ -168,6 +170,10 @@ struct ehci_hcd {			/* one per controller */
 #	define COUNT(x) do {} while (0)
 #endif
 
+	/* otg host has additional bus_suspend and bus_resume */
+	int (*otg_suspend)(struct usb_hcd *hcd);
+	int (*otg_resume)(struct usb_hcd *hcd);
+
 	/* debug files */
 #ifdef DEBUG
 	struct dentry		*debug_dir;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 0097136..a91e7e5 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -174,6 +174,12 @@ struct usb_hcd {
 	 * (ohci 32, uhci 1024, ehci 256/512/1024).
 	 */
 
+	/* some otg HCDs need this to get USB_DEVICE_ADD and USB_DEVICE_REMOVE
+	 * from root hub, we do not want to use USB notification chain, since
+	 * it would be a over kill to use high level notification.
+	 */
+	void (*otg_notify) (struct usb_device *udev, unsigned action);
+
 	/* The HC driver's private data is stored at the end of
 	 * this structure.
 	 */

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux