[RFC/PATCH 6/8] usb: gadget: goku: use new interfaces

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

 



use new interfaces from udc-core on goku
controller driver.

Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/gadget/Kconfig    |    2 +-
 drivers/usb/gadget/goku_udc.c |  369 ++++++++++++++++++-----------------------
 drivers/usb/gadget/goku_udc.h |    4 +-
 3 files changed, 162 insertions(+), 213 deletions(-)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e6d4f2a..8628d4e 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -19,7 +19,7 @@ config USB_UDC_CORE
 menuconfig USB_GADGET
 	tristate "USB Gadget Support"
 	select USB_UDC_CORE if (USB_GADGET_MUSB_HDRC || USB_GADGET_AMD5536UDC)
-	select USB_UDC_CORE if (USB_GADGET_AT91)
+	select USB_UDC_CORE if (USB_GADGET_AT91 || USB_GADGET_GOKU)
 	help
 	   USB is a master/slave protocol, organized with one master
 	   host (such as a PC) controlling up to 127 peripheral devices.
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 1088d08..4e73d1f 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -108,7 +108,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	dev = ep->dev;
 	if (ep == &dev->ep[0])
 		return -EINVAL;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+	if (!dev->udc.driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 	if (ep->num != usb_endpoint_num(desc))
 		return -EINVAL;
@@ -727,7 +727,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	if (unlikely(!_ep || (!ep->desc && ep->num != 0)))
 		return -EINVAL;
 	dev = ep->dev;
-	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
+	if (unlikely(!dev->udc.driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
 
 	/* can't touch registers when suspended */
@@ -819,7 +819,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 	if (!_ep || !_req || (!ep->desc && ep->num != 0))
 		return -EINVAL;
 	dev = ep->dev;
-	if (!dev->driver)
+	if (!dev->udc.driver)
 		return -ESHUTDOWN;
 
 	/* we can't touch (dma) registers when suspended */
@@ -995,8 +995,146 @@ static int goku_get_frame(struct usb_gadget *_gadget)
 	return -EOPNOTSUPP;
 }
 
+static void udc_reset(struct goku_udc *dev)
+{
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+
+	writel(0, &regs->power_detect);
+	writel(0, &regs->int_enable);
+	readl(&regs->int_enable);
+	dev->int_enable = 0;
+
+	/* deassert reset, leave USB D+ at hi-Z (no pullup)
+	 * don't let INT_PWRDETECT sequence begin
+	 */
+	udelay(250);
+	writel(PW_RESETB, &regs->power_detect);
+	readl(&regs->int_enable);
+}
+
+static void udc_reinit (struct goku_udc *dev)
+{
+	static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
+
+	unsigned i;
+
+	INIT_LIST_HEAD (&dev->gadget.ep_list);
+	dev->gadget.ep0 = &dev->ep [0].ep;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	dev->ep0state = EP0_DISCONNECT;
+	dev->irqs = 0;
+
+	for (i = 0; i < 4; i++) {
+		struct goku_ep	*ep = &dev->ep[i];
+
+		ep->num = i;
+		ep->ep.name = names[i];
+		ep->reg_fifo = &dev->regs->ep_fifo [i];
+		ep->reg_status = &dev->regs->ep_status [i];
+		ep->reg_mode = &dev->regs->ep_mode[i];
+
+		ep->ep.ops = &goku_ep_ops;
+		list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+		ep->dev = dev;
+		INIT_LIST_HEAD (&ep->queue);
+
+		ep_reset(NULL, ep);
+	}
+
+	dev->ep[0].reg_mode = NULL;
+	dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
+	list_del_init (&dev->ep[0].ep.ep_list);
+}
+
+static void ep0_start(struct goku_udc *dev)
+{
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+	unsigned			i;
+
+	VDBG(dev, "%s\n", __func__);
+
+	udc_reset(dev);
+	udc_reinit (dev);
+	//writel(MST_EOPB_ENA | MST_TIMEOUT_ENA, &regs->dma_master);
+
+	/* hw handles set_address, set_feature, get_status; maybe more */
+	writel(   G_REQMODE_SET_INTF | G_REQMODE_GET_INTF
+		| G_REQMODE_SET_CONF | G_REQMODE_GET_CONF
+		| G_REQMODE_GET_DESC
+		| G_REQMODE_CLEAR_FEAT
+		, &regs->reqmode);
+
+	for (i = 0; i < 4; i++)
+		dev->ep[i].irqs = 0;
+
+	/* can't modify descriptors after writing UsbReady */
+	for (i = 0; i < DESC_LEN; i++)
+		writel(0, &regs->descriptors[i]);
+	writel(0, &regs->UsbReady);
+
+	/* expect ep0 requests when the host drops reset */
+	writel(PW_RESETB | PW_PULLUP, &regs->power_detect);
+	dev->int_enable = INT_DEVWIDE | INT_EP0;
+	writel(dev->int_enable, &dev->regs->int_enable);
+	readl(&regs->int_enable);
+	dev->gadget.speed = USB_SPEED_FULL;
+	dev->ep0state = EP0_IDLE;
+}
+
+static void udc_enable(struct goku_udc *dev)
+{
+	/* start enumeration now, or after power detect irq */
+	if (readl(&dev->regs->power_detect) & PW_DETECT)
+		ep0_start(dev);
+	else {
+		DBG(dev, "%s\n", __func__);
+		dev->int_enable = INT_PWRDETECT;
+		writel(dev->int_enable, &dev->regs->int_enable);
+	}
+}
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int goku_start(struct usb_gadget *gadget)
+{
+	struct goku_udc	*dev = container_of(gadget, struct goku_udc, gadget);
+
+	udc_enable(dev);
+
+	return 0;
+}
+
+static void
+stop_activity(struct goku_udc *dev)
+{
+	unsigned	i;
+
+	DBG (dev, "%s\n", __func__);
+
+	/* disconnect gadget driver after quiesceing hw and the driver */
+	udc_reset (dev);
+	for (i = 0; i < 4; i++)
+		nuke(&dev->ep [i], -ESHUTDOWN);
+}
+
+static void goku_stop(struct usb_gadget *gadget)
+{
+	struct goku_udc	*dev = container_of(gadget, struct goku_udc, gadget);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	stop_activity(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
 static const struct usb_gadget_ops goku_ops = {
 	.get_frame	= goku_get_frame,
+	.start		= goku_start,
+	.stop		= goku_stop,
 	// no remote wakeup
 	// not selfpowered
 };
@@ -1087,7 +1225,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
 		"\n",
 		pci_name(dev->pdev), driver_desc,
 		driver_name, DRIVER_VERSION, dmastr(),
-		dev->driver ? dev->driver->driver.name : "(none)",
+		dev->udc.driver ? dev->udc.driver->driver.name : "(none)",
 		is_usb_connected
 			? ((tmp & PW_PULLUP) ? "full speed" : "powered")
 			: "disconnected",
@@ -1109,7 +1247,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
 	dump_intmask("int_status", readl(&regs->int_status), &next, &size);
 	dump_intmask("int_enable", readl(&regs->int_enable), &next, &size);
 
-	if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
+	if (!is_usb_connected || !dev->udc.driver || (tmp & PW_PULLUP) == 0)
 		goto done;
 
 	/* registers for (active) device and ep0 */
@@ -1230,106 +1368,6 @@ done:
 
 /*-------------------------------------------------------------------------*/
 
-static void udc_reinit (struct goku_udc *dev)
-{
-	static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-
-	unsigned i;
-
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	dev->gadget.ep0 = &dev->ep [0].ep;
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	dev->ep0state = EP0_DISCONNECT;
-	dev->irqs = 0;
-
-	for (i = 0; i < 4; i++) {
-		struct goku_ep	*ep = &dev->ep[i];
-
-		ep->num = i;
-		ep->ep.name = names[i];
-		ep->reg_fifo = &dev->regs->ep_fifo [i];
-		ep->reg_status = &dev->regs->ep_status [i];
-		ep->reg_mode = &dev->regs->ep_mode[i];
-
-		ep->ep.ops = &goku_ep_ops;
-		list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-		ep->dev = dev;
-		INIT_LIST_HEAD (&ep->queue);
-
-		ep_reset(NULL, ep);
-	}
-
-	dev->ep[0].reg_mode = NULL;
-	dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
-	list_del_init (&dev->ep[0].ep.ep_list);
-}
-
-static void udc_reset(struct goku_udc *dev)
-{
-	struct goku_udc_regs __iomem	*regs = dev->regs;
-
-	writel(0, &regs->power_detect);
-	writel(0, &regs->int_enable);
-	readl(&regs->int_enable);
-	dev->int_enable = 0;
-
-	/* deassert reset, leave USB D+ at hi-Z (no pullup)
-	 * don't let INT_PWRDETECT sequence begin
-	 */
-	udelay(250);
-	writel(PW_RESETB, &regs->power_detect);
-	readl(&regs->int_enable);
-}
-
-static void ep0_start(struct goku_udc *dev)
-{
-	struct goku_udc_regs __iomem	*regs = dev->regs;
-	unsigned			i;
-
-	VDBG(dev, "%s\n", __func__);
-
-	udc_reset(dev);
-	udc_reinit (dev);
-	//writel(MST_EOPB_ENA | MST_TIMEOUT_ENA, &regs->dma_master);
-
-	/* hw handles set_address, set_feature, get_status; maybe more */
-	writel(   G_REQMODE_SET_INTF | G_REQMODE_GET_INTF
-		| G_REQMODE_SET_CONF | G_REQMODE_GET_CONF
-		| G_REQMODE_GET_DESC
-		| G_REQMODE_CLEAR_FEAT
-		, &regs->reqmode);
-
-	for (i = 0; i < 4; i++)
-		dev->ep[i].irqs = 0;
-
-	/* can't modify descriptors after writing UsbReady */
-	for (i = 0; i < DESC_LEN; i++)
-		writel(0, &regs->descriptors[i]);
-	writel(0, &regs->UsbReady);
-
-	/* expect ep0 requests when the host drops reset */
-	writel(PW_RESETB | PW_PULLUP, &regs->power_detect);
-	dev->int_enable = INT_DEVWIDE | INT_EP0;
-	writel(dev->int_enable, &dev->regs->int_enable);
-	readl(&regs->int_enable);
-	dev->gadget.speed = USB_SPEED_FULL;
-	dev->ep0state = EP0_IDLE;
-}
-
-static void udc_enable(struct goku_udc *dev)
-{
-	/* start enumeration now, or after power detect irq */
-	if (readl(&dev->regs->power_detect) & PW_DETECT)
-		ep0_start(dev);
-	else {
-		DBG(dev, "%s\n", __func__);
-		dev->int_enable = INT_PWRDETECT;
-		writel(dev->int_enable, &dev->regs->int_enable);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
 /* keeping it simple:
  * - one bus driver, initted first;
  * - one function driver, initted second
@@ -1337,99 +1375,6 @@ static void udc_enable(struct goku_udc *dev)
 
 static struct goku_udc	*the_controller;
 
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
-{
-	struct goku_udc	*dev = the_controller;
-	int			retval;
-
-	if (!driver
-			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	/* hook up the driver */
-	driver->driver.bus = NULL;
-	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
-	retval = driver->bind(&dev->gadget);
-	if (retval) {
-		DBG(dev, "bind to driver %s --> error %d\n",
-				driver->driver.name, retval);
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
-
-	/* then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	udc_enable(dev);
-
-	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_register_driver);
-
-static void
-stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
-{
-	unsigned	i;
-
-	DBG (dev, "%s\n", __func__);
-
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
-	/* disconnect gadget driver after quiesceing hw and the driver */
-	udc_reset (dev);
-	for (i = 0; i < 4; i++)
-		nuke(&dev->ep [i], -ESHUTDOWN);
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	if (dev->driver)
-		udc_enable(dev);
-}
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	struct goku_udc	*dev = the_controller;
-	unsigned long	flags;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	dev->driver = NULL;
-	stop_activity(dev, driver);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
-	dev->gadget.dev.driver = NULL;
-
-	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-
 /*-------------------------------------------------------------------------*/
 
 static void ep0_setup(struct goku_udc *dev)
@@ -1525,7 +1470,7 @@ succeed:
 	 * it may respond after this irq handler returns.
 	 */
 	spin_unlock (&dev->lock);
-	tmp = dev->driver->setup(&dev->gadget, &ctrl);
+	tmp = dev->udc.driver->setup(&dev->gadget, &ctrl);
 	spin_lock (&dev->lock);
 	if (unlikely(tmp < 0)) {
 stall:
@@ -1567,11 +1512,11 @@ rescan:
 	if (unlikely(stat & INT_DEVWIDE)) {
 		if (stat & INT_SYSERROR) {
 			ERROR(dev, "system error\n");
-			stop_activity(dev, dev->driver);
+			stop_activity(dev);
 			stat = 0;
 			handled = 1;
 			// FIXME have a neater way to prevent re-enumeration
-			dev->driver = NULL;
+			dev->udc.driver = NULL;
 			goto done;
 		}
 		if (stat & INT_PWRDETECT) {
@@ -1582,7 +1527,7 @@ rescan:
 			} else {
 				DBG(dev, "disconnect\n");
 				if (dev->gadget.speed == USB_SPEED_FULL)
-					stop_activity(dev, dev->driver);
+					stop_activity(dev);
 				dev->ep0state = EP0_DISCONNECT;
 				dev->int_enable = INT_DEVWIDE;
 				writel(dev->int_enable, &dev->regs->int_enable);
@@ -1604,10 +1549,10 @@ rescan:
 				DBG(dev, "USB suspend\n");
 				dev->ep0state = EP0_SUSPEND;
 				if (dev->gadget.speed != USB_SPEED_UNKNOWN
-						&& dev->driver
-						&& dev->driver->suspend) {
+						&& dev->udc.driver
+						&& dev->udc.driver->suspend) {
 					spin_unlock(&dev->lock);
-					dev->driver->suspend(&dev->gadget);
+					dev->udc.driver->suspend(&dev->gadget);
 					spin_lock(&dev->lock);
 				}
 			} else {
@@ -1619,10 +1564,10 @@ rescan:
 				DBG(dev, "USB resume\n");
 				dev->ep0state = EP0_IDLE;
 				if (dev->gadget.speed != USB_SPEED_UNKNOWN
-						&& dev->driver
-						&& dev->driver->resume) {
+						&& dev->udc.driver
+						&& dev->udc.driver->resume) {
 					spin_unlock(&dev->lock);
-					dev->driver->resume(&dev->gadget);
+					dev->udc.driver->resume(&dev->gadget);
 					spin_lock(&dev->lock);
 				}
 			}
@@ -1631,7 +1576,7 @@ pm_next:
 		if (stat & INT_USBRESET) {		/* hub reset done */
 			ACK(INT_USBRESET);
 			INFO(dev, "USB reset done, gadget %s\n",
-				dev->driver->driver.name);
+				dev->udc.driver->driver.name);
 		}
 		// and INT_ERR on some endpoint's crc/bitstuff/... problem
 	}
@@ -1728,7 +1673,7 @@ static void goku_remove(struct pci_dev *pdev)
 
 	DBG(dev, "%s\n", __func__);
 
-	BUG_ON(dev->driver);
+	BUG_ON(dev->udc.driver);
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	remove_proc_entry(proc_node_name, NULL);
@@ -1846,7 +1791,9 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	/* done */
 	the_controller = dev;
-	retval = device_register(&dev->gadget.dev);
+	dev->udc.gadget = &dev->gadget;
+
+	retval = usb_add_udc(&pdev->dev, &dev->udc);
 	if (retval == 0)
 		return 0;
 
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index 566cb23..8e0153a 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/usb/udc.h>
+
 /*
  * PCI BAR 0 points to these registers.
  */
@@ -241,10 +243,10 @@ enum ep0state {
 
 struct goku_udc {
 	/* each pci device provides one gadget, several endpoints */
+	struct usb_udc			udc;
 	struct usb_gadget		gadget;
 	spinlock_t			lock;
 	struct goku_ep			ep[4];
-	struct usb_gadget_driver	*driver;
 
 	enum ep0state			ep0state;
 	unsigned			got_irq:1,
-- 
1.7.3.rc0.35.g8ac8c

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