[PATCH 24/25] langwell: USB Client supports 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 provided the support to common OTG data structure.

Main changes:
- Notify otg related events using notifier and remove direct
  access to otg data structure(state machine).
- Provide start_peripheral/stop_peripheral function to transceiver.
- Provide client register/unregister function.

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

 drivers/usb/gadget/langwell_udc.c |  179 +++++++++++++++++++++++++++----------
 drivers/usb/gadget/langwell_udc.h |    5 +
 2 files changed, 132 insertions(+), 52 deletions(-)


diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index 6251c3c..5db2289 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -1899,6 +1899,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 	dev->ep0_state = WAIT_FOR_SETUP;
 	dev->ep0_dir = USB_DIR_OUT;
 
+	/* bind OTG transceiver */
+	if (dev->transceiver)
+		(void)otg_set_peripheral(dev->transceiver, &dev->gadget);
+
 	/* enable interrupt and set controller to run state */
 	if (dev->got_irq)
 		langwell_udc_start(dev);
@@ -2368,26 +2372,22 @@ static void handle_setup_packet(struct langwell_udc *dev,
 					dev->dev_status &= ~(1 << wValue);
 				}
 				break;
-			default:
-				rc = -EOPNOTSUPP;
-				break;
-			}
-
-			if (!gadget_is_otg(&dev->gadget))
-				break;
-			else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
+			case USB_DEVICE_B_HNP_ENABLE:
 				dev->gadget.b_hnp_enable = 1;
-#ifdef	OTG_TRANSCEIVER
-				if (!dev->lotg->otg.default_a)
-					dev->lotg->hsm.b_hnp_enable = 1;
-#endif
-			} else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+				dev->dev_status |= (1 << wValue);
+				break;
+			case USB_DEVICE_A_HNP_SUPPORT:
 				dev->gadget.a_hnp_support = 1;
-			else if (setup->bRequest ==
-					USB_DEVICE_A_ALT_HNP_SUPPORT)
+				dev->dev_status |= (1 << wValue);
+				break;
+			case USB_DEVICE_A_ALT_HNP_SUPPORT:
 				dev->gadget.a_alt_hnp_support = 1;
-			else
+				dev->dev_status |= (1 << wValue);
 				break;
+			default:
+				rc = -EOPNOTSUPP;
+				break;
+			}
 		} else
 			break;
 
@@ -2829,12 +2829,6 @@ static void handle_usb_reset(struct langwell_udc *dev)
 		dev->usb_state = USB_STATE_ATTACHED;
 	}
 
-#ifdef	OTG_TRANSCEIVER
-	/* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
-	if (!dev->lotg->otg.default_a)
-		dev->lotg->hsm.b_hnp_enable = 0;
-#endif
-
 	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
@@ -2848,26 +2842,8 @@ static void handle_bus_suspend(struct langwell_udc *dev)
 	dev->usb_state = USB_STATE_SUSPENDED;
 
 #ifdef	OTG_TRANSCEIVER
-	if (dev->lotg->otg.default_a) {
-		if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
-			dev->lotg->hsm.b_bus_suspend = 1;
-			/* notify transceiver the state changes */
-			if (spin_trylock(&dev->lotg->wq_lock)) {
-				langwell_update_transceiver();
-				spin_unlock(&dev->lotg->wq_lock);
-			}
-		}
-		dev->lotg->hsm.b_bus_suspend_vld++;
-	} else {
-		if (!dev->lotg->hsm.a_bus_suspend) {
-			dev->lotg->hsm.a_bus_suspend = 1;
-			/* notify transceiver the state changes */
-			if (spin_trylock(&dev->lotg->wq_lock)) {
-				langwell_update_transceiver();
-				spin_unlock(&dev->lotg->wq_lock);
-			}
-		}
-	}
+	atomic_notifier_call_chain(&dev->iotg->iotg_notifier,
+				MID_OTG_NOTIFY_CSUSPEND, dev->iotg);
 #endif
 
 	/* report suspend to the driver */
@@ -2901,8 +2877,8 @@ static void handle_bus_resume(struct langwell_udc *dev)
 		langwell_phy_low_power(dev, 0);
 
 #ifdef	OTG_TRANSCEIVER
-	if (dev->lotg->otg.default_a == 0)
-		dev->lotg->hsm.a_bus_suspend = 0;
+	atomic_notifier_call_chain(&dev->iotg->iotg_notifier,
+				MID_OTG_NOTIFY_CRESUME, dev->iotg);
 #endif
 
 	/* report resume to the driver */
@@ -3136,7 +3112,7 @@ static void langwell_udc_remove(struct pci_dev *pdev)
 	if (dev->transceiver) {
 		otg_put_transceiver(dev->transceiver);
 		dev->transceiver = NULL;
-		dev->lotg = NULL;
+		dev->iotg = NULL;
 	}
 #endif
 
@@ -3200,8 +3176,10 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 	/* mem region and register base */
 	dev->region = 1;
 	dev->transceiver = otg_get_transceiver();
-	dev->lotg = otg_to_langwell(dev->transceiver);
-	base = dev->lotg->regs;
+
+	dev->iotg = otg_to_mid_xceiv(dev->transceiver);
+
+	base = dev->iotg->base;
 #else
 	pci_set_drvdata(pdev, dev);
 
@@ -3300,6 +3278,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 		goto error;
 	}
 
+#ifndef	OTG_TRANSCEIVER
 	/* allocate device dQH memory */
 	size = dev->ep_max * sizeof(struct langwell_dqh);
 	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
@@ -3318,6 +3297,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 	}
 	dev->ep_dqh_size = size;
 	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+#endif
 
 	/* initialize ep0 status request structure */
 	dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
@@ -3369,7 +3349,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 #ifndef	OTG_TRANSCEIVER
 	/* reset ep0 dQH and endptctrl */
 	ep0_reset(dev);
-#endif
 
 	/* create dTD dma_pool resource */
 	dev->dtd_pool = dma_pool_create("langwell_dtd",
@@ -3382,6 +3361,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 		retval = -ENOMEM;
 		goto error;
 	}
+#endif
 
 	/* done */
 	dev_info(&dev->pdev->dev, "%s\n", driver_desc);
@@ -3598,11 +3578,110 @@ static struct pci_driver langwell_pci_driver = {
 	.shutdown =	langwell_udc_shutdown,
 };
 
+#ifdef	OTG_TRANSCEIVER
+static int intel_mid_start_peripheral(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 = langwell_udc_resume(pdev);
+	if (retval)
+		dev_dbg(&pdev->dev, "Failed to start peripheral driver\n");
+
+	return retval;
+}
+
+static int intel_mid_stop_peripheral(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 = langwell_udc_suspend(pdev, PMSG_FREEZE);
+	if (retval)
+		dev_dbg(&pdev->dev, "Failed to stop peripheral driver\n");
+
+	return retval;
+}
+
+static int intel_mid_register_peripheral(struct pci_driver *peripheral_driver)
+{
+	struct otg_transceiver		*otg;
+	struct intel_mid_otg_xceiv	*iotg;
+	struct pci_dev			*pdev;
+	int				retval;
+
+	otg = otg_get_transceiver();
+	if (otg == NULL)
+		return -ENODEV;
+
+	if (peripheral_driver == NULL || peripheral_driver->probe == NULL)
+		return -EINVAL;
+
+	pdev = to_pci_dev(otg->dev);
+	retval = peripheral_driver->probe(pdev, peripheral_driver->id_table);
+	if (retval) {
+		dev_dbg(&pdev->dev, "client probe function failed\n");
+		return retval;
+	}
+
+	iotg = otg_to_mid_xceiv(otg);
+
+	iotg->start_peripheral = intel_mid_start_peripheral;
+	iotg->stop_peripheral = intel_mid_stop_peripheral;
+
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_CLIENTADD, iotg);
+
+	otg_put_transceiver(otg);
+
+	return 0;
+}
+
+
+static void intel_mid_unregister_peripheral(struct pci_driver
+		*peripheral_driver)
+{
+	struct otg_transceiver		*otg;
+	struct intel_mid_otg_xceiv	*iotg;
+	struct pci_dev			*pdev;
+
+	otg = otg_get_transceiver();
+	if (otg == NULL)
+		return ;
+
+	if (peripheral_driver ==  NULL || peripheral_driver->remove == NULL)
+		return ;
+
+	pdev = to_pci_dev(otg->dev);
+	peripheral_driver->remove(pdev);
+
+	iotg = otg_to_mid_xceiv(otg);
+
+	iotg->start_peripheral = NULL;
+	iotg->stop_peripheral = NULL;
+
+	atomic_notifier_call_chain(&iotg->iotg_notifier,
+				MID_OTG_NOTIFY_CLIENTREMOVE, iotg);
+
+	otg_put_transceiver(otg);
+}
+#endif
+
 
 static int __init init(void)
 {
 #ifdef	OTG_TRANSCEIVER
-	return langwell_register_peripheral(&langwell_pci_driver);
+	return intel_mid_register_peripheral(&langwell_pci_driver);
 #else
 	return pci_register_driver(&langwell_pci_driver);
 #endif
@@ -3613,7 +3692,7 @@ module_init(init);
 static void __exit cleanup(void)
 {
 #ifdef	OTG_TRANSCEIVER
-	return langwell_unregister_peripheral(&langwell_pci_driver);
+	intel_mid_unregister_peripheral(&langwell_pci_driver);
 #else
 	pci_unregister_driver(&langwell_pci_driver);
 #endif
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index fa5563d..23ecd1c 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -18,6 +18,7 @@
  */
 
 #include <linux/usb/langwell_udc.h>
+#include <linux/usb/intel_mid_otg.h>
 
 #if defined(CONFIG_USB_LANGWELL_OTG)
 #include <linux/usb/langwell_otg.h>
@@ -206,8 +207,8 @@ struct langwell_udc {
 	/* pci state used to access those endpoints */
 	struct pci_dev		*pdev;
 
-	/* Langwell otg transceiver */
-	struct langwell_otg	*lotg;
+	/* Intel mid otg transceiver */
+	struct intel_mid_otg_xceiv	*iotg;
 
 	/* control registers */
 	struct langwell_cap_regs	__iomem	*cap_regs;

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