[PATCH 09/13] EHCI: support common OTG data structure for Intel MID platform.

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

 



From: Hao Wu <hao.wu@xxxxxxxxx>

This patch is Host side related modification to support common OTG data
structure for Intel MID platform.

Main changes:
- Update OTG related data structure.
- Provide start_host/stop_host function to transceiver.
- Provide register/unregister function.

Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx>
Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
---

 drivers/usb/host/ehci-hcd.c          |   17 ++--
 drivers/usb/host/ehci-langwell-pci.c |  152 +++++++++++++++++++++++++---------
 2 files changed, 121 insertions(+), 48 deletions(-)


diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5d5d5f4..9097ccd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -43,8 +43,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/langwell_otg.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -1145,7 +1143,7 @@ MODULE_LICENSE ("GPL");
 #define	PCI_DRIVER		ehci_pci_driver
 #ifdef CONFIG_USB_LANGWELL_OTG
 #include "ehci-langwell-pci.c"
-#define LNW_OTG_HOST_DRIVER	ehci_otg_driver
+#define INTEL_MID_OTG_HOST_DRIVER	ehci_otg_driver
 #endif
 #endif
 
@@ -1267,20 +1265,21 @@ static int __init ehci_hcd_init(void)
 		goto clean4;
 #endif
 
-#ifdef LNW_OTG_HOST_DRIVER
-	retval = langwell_register_host(&LNW_OTG_HOST_DRIVER);
+#ifdef INTEL_MID_OTG_HOST_DRIVER
+	retval = intel_mid_ehci_driver_register(&INTEL_MID_OTG_HOST_DRIVER);
 	if (retval < 0)
 		goto clean4;
 #endif
+
 	return retval;
 
 #ifdef XILINX_OF_PLATFORM_DRIVER
 	/* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
 clean4:
 #endif
-#ifdef LNW_OTG_HOST_DRIVER
+#ifdef INTEL_MID_OTG_HOST_DRIVER
 clean4:
-	langwell_unregister_host(&LNW_OTG_HOST_DRIVER);
+	intel_mid_ehci_driver_unregister(&INTEL_MID_OTG_HOST_DRIVER);
 #endif
 #ifdef OF_PLATFORM_DRIVER
 	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
@@ -1325,8 +1324,8 @@ static void __exit ehci_hcd_cleanup(void)
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
-#ifdef LNW_OTG_HOST_DRIVER
-	langwell_unregister_host(&LNW_OTG_HOST_DRIVER);
+#ifdef INTEL_MID_OTG_HOST_DRIVER
+	intel_mid_ehci_driver_unregister(&INTEL_MID_OTG_HOST_DRIVER);
 #endif
 #ifdef DEBUG
 	debugfs_remove(ehci_debug_root);
diff --git a/drivers/usb/host/ehci-langwell-pci.c b/drivers/usb/host/ehci-langwell-pci.c
index a89e93e..ee2a56f 100644
--- a/drivers/usb/host/ehci-langwell-pci.c
+++ b/drivers/usb/host/ehci-langwell-pci.c
@@ -1,7 +1,7 @@
 /*
- * Intel Moorestown Platform Langwell OTG EHCI Controller PCI Bus Glue.
+ * Intel MID Platform Langwell/Penwell OTG EHCI Controller PCI Bus Glue.
  *
- * Copyright (c) 2008 - 2009, Intel Corporation.
+ * Copyright (c) 2008 - 2010, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License 2 as published by the
@@ -17,23 +17,24 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/usb/otg.h>
+#include <linux/usb/intel_mid_otg.h>
+
 static int usb_otg_suspend(struct usb_hcd *hcd)
 {
 	struct otg_transceiver *otg;
-	struct langwell_otg *iotg;
+	struct intel_mid_otg_xceiv *iotg;
 
 	otg = otg_get_transceiver();
 	if (otg == NULL) {
 		printk(KERN_ERR	"%s Failed to get otg transceiver\n", __func__);
 		return -EINVAL;
 	}
-	iotg = container_of(otg, struct langwell_otg, otg);
+	iotg = otg_to_mid_xceiv(otg);
 	printk(KERN_INFO "%s OTG HNP update suspend\n", __func__);
-	if (iotg->otg.default_a)
-		iotg->hsm.a_suspend_req = 1;
-	else
-		iotg->hsm.b_bus_req = 0;
-	langwell_update_transceiver();
+
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_HSUSPEND, iotg);
 	otg_put_transceiver(otg);
 	return 0;
 }
@@ -41,19 +42,18 @@ static int usb_otg_suspend(struct usb_hcd *hcd)
 static int usb_otg_resume(struct usb_hcd *hcd)
 {
 	struct otg_transceiver *otg;
-	struct langwell_otg *iotg;
+	struct intel_mid_otg_xceiv *iotg;
 
 	otg = otg_get_transceiver();
 	if (otg == NULL) {
 		printk(KERN_ERR "%s Failed to get otg transceiver\n", __func__);
 		return -EINVAL;
 	}
-	iotg = container_of(otg, struct langwell_otg, otg);
+	iotg = otg_to_mid_xceiv(otg);
 	printk(KERN_INFO "%s OTG HNP update resume\n", __func__);
-	if (iotg->otg.default_a) {
-		iotg->hsm.b_bus_resume = 1;
-		langwell_update_transceiver();
-	}
+
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_HRESUME, iotg);
 	otg_put_transceiver(otg);
 	return 0;
 }
@@ -62,54 +62,52 @@ static int usb_otg_resume(struct usb_hcd *hcd)
 static void otg_notify(struct usb_device *udev, unsigned action)
 {
 	struct otg_transceiver *otg;
-	struct langwell_otg *iotg;
+	struct intel_mid_otg_xceiv *iotg;
+
+	/* Ignore root hub add/remove event */
+	if (!udev->parent) {
+		printk(KERN_INFO "%s Ignore root hub otg_notify\n", __func__);
+		return;
+	}
 
 	otg = otg_get_transceiver();
 	if (otg == NULL) {
 		printk(KERN_ERR "%s Failed to get otg transceiver\n", __func__);
 		return;
 	}
-	iotg = container_of(otg, struct langwell_otg, otg);
+	iotg = otg_to_mid_xceiv(otg);
 
 	switch (action) {
 	case USB_DEVICE_ADD:
 		pr_debug("Notify OTG HNP add device\n");
-		if (iotg->otg.default_a == 1)
-			iotg->hsm.b_conn = 1;
-		else
-			iotg->hsm.a_conn = 1;
+		atomic_notifier_call_chain(&iotg->iotg_notifier,
+					MID_OTG_NOTIFY_CONNECT, iotg);
 		break;
 	case USB_DEVICE_REMOVE:
 		pr_debug("Notify OTG HNP delete device\n");
-		if (iotg->otg.default_a == 1)
-			iotg->hsm.b_conn = 0;
-		else
-			iotg->hsm.a_conn = 0;
+		atomic_notifier_call_chain(&iotg->iotg_notifier,
+					MID_OTG_NOTIFY_DISCONN, iotg);
 		break;
 	default:
 		otg_put_transceiver(otg);
 		return ;
 	}
-	if (spin_trylock(&iotg->wq_lock)) {
-		langwell_update_transceiver();
-		spin_unlock(&iotg->wq_lock);
-	}
 	otg_put_transceiver(otg);
 	return;
 }
 
-static int ehci_langwell_probe(struct pci_dev *pdev,
+static int ehci_mid_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
 	struct hc_driver *driver;
-	struct langwell_otg *iotg;
 	struct otg_transceiver *otg;
+	struct intel_mid_otg_xceiv *iotg;
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
 	int irq;
 	int retval;
 
-	pr_debug("initializing Langwell USB OTG Host Controller\n");
+	pr_debug("initializing Intel MID USB OTG Host Controller\n");
 
 	/* we need not call pci_enable_dev since otg transceiver already take
 	 * the control of this device and this probe actaully gets called by
@@ -142,8 +140,10 @@ static int ehci_langwell_probe(struct pci_dev *pdev,
 		retval = -EINVAL;
 		goto err1;
 	}
-	iotg = container_of(otg, struct langwell_otg, otg);
-	hcd->regs = iotg->regs;
+
+	iotg = otg_to_mid_xceiv(otg);
+	hcd->regs = iotg->base;
+
 	hcd->rsrc_start = pci_resource_start(pdev, 0);
 	hcd->rsrc_len = pci_resource_len(pdev, 0);
 
@@ -168,7 +168,7 @@ err1:
 	return retval;
 }
 
-void ehci_langwell_remove(struct pci_dev *dev)
+void ehci_mid_remove(struct pci_dev *dev)
 {
 	struct usb_hcd *hcd = pci_get_drvdata(dev);
 
@@ -178,13 +178,13 @@ void ehci_langwell_remove(struct pci_dev *dev)
 	usb_put_hcd(hcd);
 }
 
-/* Langwell OTG EHCI driver */
+/* Intel MID OTG EHCI driver */
 static struct pci_driver ehci_otg_driver = {
-	.name =		"ehci-langwell",
+	.name =		"ehci-intel-mid",
 	.id_table =	pci_ids,
 
-	.probe =	ehci_langwell_probe,
-	.remove =	ehci_langwell_remove,
+	.probe =	ehci_mid_probe,
+	.remove =	ehci_mid_remove,
 
 #ifdef CONFIG_PM_SLEEP
 	.driver =	{
@@ -193,3 +193,77 @@ static struct pci_driver ehci_otg_driver = {
 #endif
 	.shutdown = 	usb_hcd_pci_shutdown,
 };
+
+static int ehci_mid_start_host(struct intel_mid_otg_xceiv *iotg)
+{
+	struct pci_dev	*pdev;
+	int		retval;
+
+	if (iotg == NULL)
+		return -EINVAL;
+
+	pdev = to_pci_dev(iotg->otg.dev);
+
+	retval = ehci_mid_probe(pdev, ehci_otg_driver.id_table);
+	if (retval)
+		dev_dbg(iotg->otg.dev, "Failed to start host\n");
+
+	return retval;
+}
+
+static int ehci_mid_stop_host(struct intel_mid_otg_xceiv *iotg)
+{
+	struct pci_dev	*pdev;
+
+	if (iotg == NULL)
+		return -EINVAL;
+
+	pdev = to_pci_dev(iotg->otg.dev);
+
+	ehci_mid_remove(pdev);
+
+	return 0;
+}
+
+static int intel_mid_ehci_driver_register(struct pci_driver *host_driver)
+{
+	struct otg_transceiver		*otg;
+	struct intel_mid_otg_xceiv	*iotg;
+
+	otg = otg_get_transceiver();
+	if (otg == NULL)
+		return -EINVAL;
+
+	iotg = otg_to_mid_xceiv(otg);
+	iotg->start_host = ehci_mid_start_host;
+	iotg->stop_host = ehci_mid_stop_host;
+
+	/* notify host driver is registered */
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_HOSTADD, iotg);
+
+	otg_put_transceiver(otg);
+
+	return 0;
+}
+
+static void intel_mid_ehci_driver_unregister(struct pci_driver *host_driver)
+{
+	struct otg_transceiver		*otg;
+	struct intel_mid_otg_xceiv	*iotg;
+
+	otg = otg_get_transceiver();
+	if (otg == NULL)
+		return ;
+
+	iotg = otg_to_mid_xceiv(otg);
+	iotg->start_host = NULL;
+	iotg->stop_host = NULL;
+
+	/* notify host driver is unregistered */
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_HOSTREMOVE, iotg);
+
+	otg_put_transceiver(otg);
+}
+

--
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