[RFC/RFT/NOT-FOR-MERGING 3/3] usb: gadget: udc: use new interfaces

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

 



fix all UDC drivers to use the new interfaces
while also enabling compilation of udc.c on
Kconfig.

Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/gadget/Makefile        |    1 +
 drivers/usb/gadget/amd5536udc.c    |  451 ++++++++++++++++--------------------
 drivers/usb/gadget/amd5536udc.h    |    4 +-
 drivers/usb/gadget/at91_udc.c      |  131 ++++-------
 drivers/usb/gadget/at91_udc.h      |    4 +-
 drivers/usb/gadget/dummy_hcd.c     |   99 +++------
 drivers/usb/musb/musb_core.c       |    4 +-
 drivers/usb/musb/musb_core.h       |    4 +-
 drivers/usb/musb/musb_gadget.c     |  214 +++++------------
 drivers/usb/musb/musb_gadget_ep0.c |    4 +-
 drivers/usb/musb/tusb6010.c        |    2 +-
 11 files changed, 357 insertions(+), 561 deletions(-)

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 27283df..302ac96 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -5,6 +5,7 @@ ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
 	EXTRA_CFLAGS		+= -DDEBUG
 endif
 
+obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 731150d4..261349c 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -339,7 +339,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
 
 	DBG(dev, "udc_ep_enable() ep %d\n", ep->num);
 
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+	if (!dev->udc.driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
 	spin_lock_irqsave(&dev->lock, iflags);
@@ -1099,7 +1099,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 	VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
 	dev = ep->dev;
 
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+	if (!dev->udc.driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
 	/* map dma (usually done before) */
@@ -1355,7 +1355,7 @@ udc_set_halt(struct usb_ep *usbep, int halt)
 	ep = container_of(usbep, struct udc_ep, ep);
 	if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
 		return -EINVAL;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+	if (!ep->dev->udc.driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
 	spin_lock_irqsave(&udc_stall_spinlock, iflags);
@@ -1418,6 +1418,134 @@ static const struct usb_ep_ops udc_ep_ops = {
 
 /*-------------------------------------------------------------------------*/
 
+/* Inits endpoint 0 so that SETUP packets are processed */
+static void activate_control_endpoints(struct udc *dev)
+{
+	u32 tmp;
+
+	DBG(dev, "activate_control_endpoints\n");
+
+	/* flush fifo */
+	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+	tmp |= AMD_BIT(UDC_EPCTL_F);
+	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+
+	/* set ep0 directions */
+	dev->ep[UDC_EP0IN_IX].in = 1;
+	dev->ep[UDC_EP0OUT_IX].in = 0;
+
+	/* set buffer size (tx fifo entries) of EP0_IN */
+	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+	if (dev->gadget.speed == USB_SPEED_FULL)
+		tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,
+					UDC_EPIN_BUFF_SIZE);
+	else if (dev->gadget.speed == USB_SPEED_HIGH)
+		tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,
+					UDC_EPIN_BUFF_SIZE);
+	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+
+	/* set max packet size of EP0_IN */
+	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+	if (dev->gadget.speed == USB_SPEED_FULL)
+		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,
+					UDC_EP_MAX_PKT_SIZE);
+	else if (dev->gadget.speed == USB_SPEED_HIGH)
+		tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,
+				UDC_EP_MAX_PKT_SIZE);
+	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+
+	/* set max packet size of EP0_OUT */
+	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+	if (dev->gadget.speed == USB_SPEED_FULL)
+		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+					UDC_EP_MAX_PKT_SIZE);
+	else if (dev->gadget.speed == USB_SPEED_HIGH)
+		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+					UDC_EP_MAX_PKT_SIZE);
+	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+
+	/* set max packet size of EP0 in UDC CSR */
+	tmp = readl(&dev->csr->ne[0]);
+	if (dev->gadget.speed == USB_SPEED_FULL)
+		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+					UDC_CSR_NE_MAX_PKT);
+	else if (dev->gadget.speed == USB_SPEED_HIGH)
+		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+					UDC_CSR_NE_MAX_PKT);
+	writel(tmp, &dev->csr->ne[0]);
+
+	if (use_dma) {
+		dev->ep[UDC_EP0OUT_IX].td->status |=
+			AMD_BIT(UDC_DMA_OUT_STS_L);
+		/* write dma desc address */
+		writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,
+			&dev->ep[UDC_EP0OUT_IX].regs->subptr);
+		writel(dev->ep[UDC_EP0OUT_IX].td_phys,
+			&dev->ep[UDC_EP0OUT_IX].regs->desptr);
+		/* stop RDE timer */
+		if (timer_pending(&udc_timer)) {
+			set_rde = 0;
+			mod_timer(&udc_timer, jiffies - 1);
+		}
+		/* stop pollstall timer */
+		if (timer_pending(&udc_pollstall_timer)) {
+			mod_timer(&udc_pollstall_timer, jiffies - 1);
+		}
+		/* enable DMA */
+		tmp = readl(&dev->regs->ctl);
+		tmp |= AMD_BIT(UDC_DEVCTL_MODE)
+				| AMD_BIT(UDC_DEVCTL_RDE)
+				| AMD_BIT(UDC_DEVCTL_TDE);
+		if (use_dma_bufferfill_mode) {
+			tmp |= AMD_BIT(UDC_DEVCTL_BF);
+		} else if (use_dma_ppb_du) {
+			tmp |= AMD_BIT(UDC_DEVCTL_DU);
+		}
+		writel(tmp, &dev->regs->ctl);
+	}
+
+	/* clear NAK by writing CNAK for EP0IN */
+	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+	tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+	dev->ep[UDC_EP0IN_IX].naking = 0;
+	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
+
+	/* clear NAK by writing CNAK for EP0OUT */
+	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+	tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+	dev->ep[UDC_EP0OUT_IX].naking = 0;
+	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
+}
+
+/* Make endpoint 0 ready for control traffic */
+static int setup_ep0(struct udc *dev)
+{
+	activate_control_endpoints(dev);
+	/* enable ep0 interrupts */
+	udc_enable_ep0_interrupts(dev);
+	/* enable device setup interrupts */
+	udc_enable_dev_setup_interrupts(dev);
+
+	return 0;
+}
+
+/* Bringup after Connect event, initial bringup to be ready for ep0 events */
+static void usb_connect(struct udc *dev)
+{
+
+	dev_info(&dev->pdev->dev, "USB Connect\n");
+
+	dev->connected = 1;
+
+	/* put into initial config */
+	udc_basic_init(dev);
+
+	/* enable device setup interrupts */
+	udc_enable_dev_setup_interrupts(dev);
+}
+
 /* Get frame counter (not implemented) */
 static int udc_get_frame(struct usb_gadget *gadget)
 {
@@ -1437,10 +1565,66 @@ static int udc_wakeup(struct usb_gadget *gadget)
 	return 0;
 }
 
+static int udc_start(struct usb_gadget *gadget)
+{
+	struct udc	*dev = container_of(gadget, struct udc, gadget);
+	u32 tmp;
+
+	/* Some gadget drivers use both ep0 directions.
+	 * NOTE: to gadget driver, ep0 is just one endpoint...
+	 */
+	dev->ep[UDC_EP0OUT_IX].ep.driver_data =
+		dev->ep[UDC_EP0IN_IX].ep.driver_data;
+
+	/* get ready for ep0 traffic */
+	setup_ep0(dev);
+
+	/* clear SD */
+	tmp = readl(&dev->regs->ctl);
+	tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);
+	writel(tmp, &dev->regs->ctl);
+
+	usb_connect(dev);
+
+	return 0;
+}
+
+/* shutdown requests and disconnect from gadget */
+static void shutdown(struct udc *dev)
+{
+	int tmp;
+
+	/* empty queues and init hardware */
+	udc_basic_init(dev);
+	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+		empty_req_queue(&dev->ep[tmp]);
+
+	udc_setup_endpoints(dev);
+}
+
+static void udc_stop(struct usb_gadget *gadget)
+{
+	struct udc	*dev = container_of(gadget, struct udc, gadget);
+	unsigned long	flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	udc_mask_unused_interrupts(dev);
+	shutdown(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* set SD */
+	tmp = readl(&dev->regs->ctl);
+	tmp |= AMD_BIT(UDC_DEVCTL_SD);
+	writel(tmp, &dev->regs->ctl);
+}
+
 /* gadget operations */
 static const struct usb_gadget_ops udc_ops = {
 	.wakeup		= udc_wakeup,
 	.get_frame	= udc_get_frame,
+	.start		= udc_start,
+	.stop		= udc_stop,
 };
 
 /* Setups endpoint parameters, adds endpoints to linked list */
@@ -1621,21 +1805,6 @@ static void udc_setup_endpoints(struct udc *dev)
 	dev->cur_alt = 0;
 }
 
-/* Bringup after Connect event, initial bringup to be ready for ep0 events */
-static void usb_connect(struct udc *dev)
-{
-
-	dev_info(&dev->pdev->dev, "USB Connect\n");
-
-	dev->connected = 1;
-
-	/* put into initial config */
-	udc_basic_init(dev);
-
-	/* enable device setup interrupts */
-	udc_enable_dev_setup_interrupts(dev);
-}
-
 /*
  * Calls gadget with disconnect event and resets the UDC and makes
  * initial bringup to be ready for ep0 events
@@ -1667,9 +1836,9 @@ static void udc_tasklet_disconnect(unsigned long par)
 	DBG(dev, "Tasklet disconnect\n");
 	spin_lock_irq(&dev->lock);
 
-	if (dev->driver) {
+	if (dev->udc.driver) {
 		spin_unlock(&dev->lock);
-		dev->driver->disconnect(&dev->gadget);
+		dev->udc.driver->disconnect(&dev->gadget);
 		spin_lock(&dev->lock);
 
 		/* empty queues */
@@ -1840,224 +2009,6 @@ static void udc_pollstall_timer_function(unsigned long v)
 		complete(&on_pollstall_exit);
 }
 
-/* Inits endpoint 0 so that SETUP packets are processed */
-static void activate_control_endpoints(struct udc *dev)
-{
-	u32 tmp;
-
-	DBG(dev, "activate_control_endpoints\n");
-
-	/* flush fifo */
-	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-	tmp |= AMD_BIT(UDC_EPCTL_F);
-	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-
-	/* set ep0 directions */
-	dev->ep[UDC_EP0IN_IX].in = 1;
-	dev->ep[UDC_EP0OUT_IX].in = 0;
-
-	/* set buffer size (tx fifo entries) of EP0_IN */
-	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
-	if (dev->gadget.speed == USB_SPEED_FULL)
-		tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,
-					UDC_EPIN_BUFF_SIZE);
-	else if (dev->gadget.speed == USB_SPEED_HIGH)
-		tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,
-					UDC_EPIN_BUFF_SIZE);
-	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
-
-	/* set max packet size of EP0_IN */
-	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
-	if (dev->gadget.speed == USB_SPEED_FULL)
-		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,
-					UDC_EP_MAX_PKT_SIZE);
-	else if (dev->gadget.speed == USB_SPEED_HIGH)
-		tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,
-				UDC_EP_MAX_PKT_SIZE);
-	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
-
-	/* set max packet size of EP0_OUT */
-	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
-	if (dev->gadget.speed == USB_SPEED_FULL)
-		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
-					UDC_EP_MAX_PKT_SIZE);
-	else if (dev->gadget.speed == USB_SPEED_HIGH)
-		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
-					UDC_EP_MAX_PKT_SIZE);
-	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
-
-	/* set max packet size of EP0 in UDC CSR */
-	tmp = readl(&dev->csr->ne[0]);
-	if (dev->gadget.speed == USB_SPEED_FULL)
-		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
-					UDC_CSR_NE_MAX_PKT);
-	else if (dev->gadget.speed == USB_SPEED_HIGH)
-		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
-					UDC_CSR_NE_MAX_PKT);
-	writel(tmp, &dev->csr->ne[0]);
-
-	if (use_dma) {
-		dev->ep[UDC_EP0OUT_IX].td->status |=
-			AMD_BIT(UDC_DMA_OUT_STS_L);
-		/* write dma desc address */
-		writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,
-			&dev->ep[UDC_EP0OUT_IX].regs->subptr);
-		writel(dev->ep[UDC_EP0OUT_IX].td_phys,
-			&dev->ep[UDC_EP0OUT_IX].regs->desptr);
-		/* stop RDE timer */
-		if (timer_pending(&udc_timer)) {
-			set_rde = 0;
-			mod_timer(&udc_timer, jiffies - 1);
-		}
-		/* stop pollstall timer */
-		if (timer_pending(&udc_pollstall_timer)) {
-			mod_timer(&udc_pollstall_timer, jiffies - 1);
-		}
-		/* enable DMA */
-		tmp = readl(&dev->regs->ctl);
-		tmp |= AMD_BIT(UDC_DEVCTL_MODE)
-				| AMD_BIT(UDC_DEVCTL_RDE)
-				| AMD_BIT(UDC_DEVCTL_TDE);
-		if (use_dma_bufferfill_mode) {
-			tmp |= AMD_BIT(UDC_DEVCTL_BF);
-		} else if (use_dma_ppb_du) {
-			tmp |= AMD_BIT(UDC_DEVCTL_DU);
-		}
-		writel(tmp, &dev->regs->ctl);
-	}
-
-	/* clear NAK by writing CNAK for EP0IN */
-	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-	tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-	dev->ep[UDC_EP0IN_IX].naking = 0;
-	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
-
-	/* clear NAK by writing CNAK for EP0OUT */
-	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
-	tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
-	dev->ep[UDC_EP0OUT_IX].naking = 0;
-	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
-}
-
-/* Make endpoint 0 ready for control traffic */
-static int setup_ep0(struct udc *dev)
-{
-	activate_control_endpoints(dev);
-	/* enable ep0 interrupts */
-	udc_enable_ep0_interrupts(dev);
-	/* enable device setup interrupts */
-	udc_enable_dev_setup_interrupts(dev);
-
-	return 0;
-}
-
-/* Called by gadget driver to register itself */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
-{
-	struct udc		*dev = udc;
-	int			retval;
-	u32 tmp;
-
-	if (!driver || !driver->bind || !driver->setup
-			|| driver->speed != USB_SPEED_HIGH)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	driver->driver.bus = NULL;
-	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
-
-	retval = driver->bind(&dev->gadget);
-
-	/* Some gadget drivers use both ep0 directions.
-	 * NOTE: to gadget driver, ep0 is just one endpoint...
-	 */
-	dev->ep[UDC_EP0OUT_IX].ep.driver_data =
-		dev->ep[UDC_EP0IN_IX].ep.driver_data;
-
-	if (retval) {
-		DBG(dev, "binding to %s returning %d\n",
-				driver->driver.name, retval);
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
-
-	/* get ready for ep0 traffic */
-	setup_ep0(dev);
-
-	/* clear SD */
-	tmp = readl(&dev->regs->ctl);
-	tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);
-	writel(tmp, &dev->regs->ctl);
-
-	usb_connect(dev);
-
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_register_driver);
-
-/* shutdown requests and disconnect from gadget */
-static void
-shutdown(struct udc *dev, struct usb_gadget_driver *driver)
-__releases(dev->lock)
-__acquires(dev->lock)
-{
-	int tmp;
-
-	if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	/* empty queues and init hardware */
-	udc_basic_init(dev);
-	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
-		empty_req_queue(&dev->ep[tmp]);
-
-	udc_setup_endpoints(dev);
-}
-
-/* Called by gadget driver to unregister itself */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	struct udc	*dev = udc;
-	unsigned long	flags;
-	u32 tmp;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	udc_mask_unused_interrupts(dev);
-	shutdown(dev, driver);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
-	dev->gadget.dev.driver = NULL;
-	dev->driver = NULL;
-
-	/* set SD */
-	tmp = readl(&dev->regs->ctl);
-	tmp |= AMD_BIT(UDC_DEVCTL_SD);
-	writel(tmp, &dev->regs->ctl);
-
-
-	DBG(dev, "%s: unregistered\n", driver->driver.name);
-
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-
 /* Clear pending NAK bits */
 static void udc_process_cnak_queue(struct udc *dev)
 {
@@ -2613,7 +2564,7 @@ __acquires(dev->lock)
 
 		/* call gadget with setup data received */
 		spin_unlock(&dev->lock);
-		setup_supported = dev->driver->setup(&dev->gadget,
+		setup_supported = dev->udc.driver->setup(&dev->gadget,
 						&setup_data.request);
 		spin_lock(&dev->lock);
 
@@ -2869,7 +2820,7 @@ __acquires(dev->lock)
 		}
 		/* call gadget zero with setup data received */
 		spin_unlock(&dev->lock);
-		tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+		tmp = dev->udc.driver->setup(&dev->gadget, &setup_data.request);
 		spin_lock(&dev->lock);
 
 	} /* SET_INTERFACE ? */
@@ -2929,7 +2880,7 @@ __acquires(dev->lock)
 
 		/* call gadget zero with setup data received */
 		spin_unlock(&dev->lock);
-		tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+		tmp = dev->udc.driver->setup(&dev->gadget, &setup_data.request);
 		spin_lock(&dev->lock);
 
 	} /* USB reset */
@@ -2948,11 +2899,11 @@ __acquires(dev->lock)
 
 		/* call gadget to resume and reset configs etc. */
 		spin_unlock(&dev->lock);
-		if (dev->sys_suspended && dev->driver->resume) {
-			dev->driver->resume(&dev->gadget);
+		if (dev->sys_suspended && dev->udc.driver->resume) {
+			dev->udc.driver->resume(&dev->gadget);
 			dev->sys_suspended = 0;
 		}
-		dev->driver->disconnect(&dev->gadget);
+		dev->udc.driver->disconnect(&dev->gadget);
 		spin_lock(&dev->lock);
 
 		/* disable ep0 to empty req queue */
@@ -2992,10 +2943,10 @@ __acquires(dev->lock)
 	if (dev_irq & AMD_BIT(UDC_DEVINT_US)) {
 		DBG(dev, "USB Suspend interrupt\n");
 		ret_val = IRQ_HANDLED;
-		if (dev->driver->suspend) {
+		if (dev->udc.driver->suspend) {
 			spin_unlock(&dev->lock);
 			dev->sys_suspended = 1;
-			dev->driver->suspend(&dev->gadget);
+			dev->udc.driver->suspend(&dev->gadget);
 			spin_lock(&dev->lock);
 		}
 	} /* new speed ? */
@@ -3133,7 +3084,7 @@ static void udc_pci_remove(struct pci_dev *pdev)
 	dev = pci_get_drvdata(pdev);
 
 	/* gadget driver must not be registered */
-	BUG_ON(dev->driver != NULL);
+	BUG_ON(dev->udc.driver != NULL);
 
 	/* dma pool cleanup */
 	if (dev->data_requests)
@@ -3328,8 +3279,6 @@ static int udc_pci_probe(
 	dev->phys_addr = resource;
 	dev->irq = pdev->irq;
 	dev->pdev = pdev;
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
 	/* general probing */
 	if (udc_probe(dev) == 0)
@@ -3381,7 +3330,9 @@ static int udc_probe(struct udc *dev)
 		"driver version: %s(for Geode5536 B1)\n", tmp);
 	udc = dev;
 
-	retval = device_register(&dev->gadget.dev);
+	udc->udc.gadget = &udc->gadget;
+
+	retval = usb_add_udc(&dev->pdev->dev, &dev->udc);
 	if (retval)
 		goto finished;
 
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
index 4bbabbb..3995fda 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/amd5536udc.h
@@ -22,6 +22,8 @@
 #ifndef AMD5536UDC_H
 #define AMD5536UDC_H
 
+#include <linux/usb/udc.h>
+
 /* various constants */
 #define UDC_RDE_TIMER_SECONDS		1
 #define UDC_RDE_TIMER_DIV		10
@@ -531,11 +533,11 @@ struct udc_ep {
 
 /* device struct */
 struct udc {
+	struct usb_udc			udc;
 	struct usb_gadget		gadget;
 	spinlock_t			lock;	/* protects all state */
 	/* all endpoints */
 	struct udc_ep			ep[UDC_EP_NUM];
-	struct usb_gadget_driver	*driver;
 	/* operational flags */
 	unsigned			active : 1,
 					stall_ep0in : 1,
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 93ead19..cbeff67 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/clk.h>
+#include <linux/usb/udc.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
@@ -186,7 +187,7 @@ static int proc_udc_show(struct seq_file *s, void *unused)
 			: "disabled",
 		udc->selfpowered ? "self" : "VBUS",
 		udc->suspended ? ", suspended" : "",
-		udc->driver ? udc->driver->driver.name : "(none)");
+		udc->udc.driver ? udc->udc.driver->driver.name : "(none)");
 
 	/* don't access registers when interface isn't clocked */
 	if (!udc->clocked) {
@@ -491,7 +492,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
 		return -EINVAL;
 	}
 
-	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+	if (!udc->udc.driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
 		DBG("bogus device state\n");
 		return -ESHUTDOWN;
 	}
@@ -631,7 +632,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
 
 	udc = ep->udc;
 
-	if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+	if (!udc || !udc->udc.driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
 		DBG("invalid device\n");
 		return -EINVAL;
 	}
@@ -851,7 +852,7 @@ static void udc_reinit(struct at91_udc *udc)
 
 static void stop_activity(struct at91_udc *udc)
 {
-	struct usb_gadget_driver *driver = udc->driver;
+	struct usb_gadget_driver *driver = udc->udc.driver;
 	int i;
 
 	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
@@ -953,7 +954,7 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
 	// VDBG("vbus %s\n", is_active ? "on" : "off");
 	spin_lock_irqsave(&udc->lock, flags);
 	udc->vbus = (is_active != 0);
-	if (udc->driver)
+	if (udc->udc.driver)
 		pullup(udc, is_active);
 	else
 		pullup(udc, 0);
@@ -984,12 +985,40 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int at91_start(struct usb_gadget *gadget)
+{
+	struct at91_udc	*udc = to_udc(gadget);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->enabled = 1;
+	udc->selfpowered = 1;
+	pullup(udc, 1);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+static void at91_stop(struct usb_gadget *gadget)
+{
+	struct at91_udc *udc = to_udc(gadget);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->enabled = 0;
+	at91_udp_write(udc, AT91_UDP_IDR, ~0);
+	pullup(udc, 0);
+	spin_unlock_irqrestore(&udc->lock, flags);
+}
+
 static const struct usb_gadget_ops at91_udc_ops = {
 	.get_frame		= at91_get_frame,
 	.wakeup			= at91_wakeup,
 	.set_selfpowered	= at91_set_selfpowered,
 	.vbus_session		= at91_vbus_session,
 	.pullup			= at91_pullup,
+	.start			= at91_start,
+	.stop			= at91_stop,
 
 	/*
 	 * VBUS-powered devices may also also want to support bigger
@@ -1242,9 +1271,9 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 #undef w_length
 
 	/* pass request up to the gadget driver */
-	if (udc->driver) {
+	if (udc->udc.driver) {
 		spin_unlock(&udc->lock);
-		status = udc->driver->setup(&udc->gadget, &pkt.r);
+		status = udc->udc.driver->setup(&udc->gadget, &pkt.r);
 		spin_lock(&udc->lock);
 	}
 	else
@@ -1455,9 +1484,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
 			 * and then into standby to avoid drawing more than
 			 * 500uA power (2500uA for some high-power configs).
 			 */
-			if (udc->driver && udc->driver->suspend) {
+			if (udc->udc.driver && udc->udc.driver->suspend) {
 				spin_unlock(&udc->lock);
-				udc->driver->suspend(&udc->gadget);
+				udc->udc.driver->suspend(&udc->gadget);
 				spin_lock(&udc->lock);
 			}
 
@@ -1476,9 +1505,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
 			 * would normally want to switch out of slow clock
 			 * mode into normal mode.
 			 */
-			if (udc->driver && udc->driver->resume) {
+			if (udc->udc.driver && udc->udc.driver->resume) {
 				spin_unlock(&udc->lock);
-				udc->driver->resume(&udc->gadget);
+				udc->udc.driver->resume(&udc->gadget);
 				spin_lock(&udc->lock);
 			}
 
@@ -1515,6 +1544,9 @@ static void nop_release(struct device *dev)
 }
 
 static struct at91_udc controller = {
+	.udc	= {
+		.name	= (char *) driver_name,
+	},
 	.gadget = {
 		.ops	= &at91_udc_ops,
 		.ep0	= &controller.ep[0].ep,
@@ -1628,75 +1660,6 @@ static void at91_vbus_timer(unsigned long data)
 		schedule_work(&udc->vbus_timer_work);
 }
 
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
-{
-	struct at91_udc	*udc = &controller;
-	int		retval;
-	unsigned long	flags;
-
-	if (!driver
-			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->setup) {
-		DBG("bad parameter.\n");
-		return -EINVAL;
-	}
-
-	if (udc->driver) {
-		DBG("UDC already has a gadget driver\n");
-		return -EBUSY;
-	}
-
-	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
-	dev_set_drvdata(&udc->gadget.dev, &driver->driver);
-	udc->enabled = 1;
-	udc->selfpowered = 1;
-
-	retval = driver->bind(&udc->gadget);
-	if (retval) {
-		DBG("driver->bind() returned %d\n", retval);
-		udc->driver = NULL;
-		udc->gadget.dev.driver = NULL;
-		dev_set_drvdata(&udc->gadget.dev, NULL);
-		udc->enabled = 0;
-		udc->selfpowered = 0;
-		return retval;
-	}
-
-	spin_lock_irqsave(&udc->lock, flags);
-	pullup(udc, 1);
-	spin_unlock_irqrestore(&udc->lock, flags);
-
-	DBG("bound to %s\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL (usb_gadget_register_driver);
-
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
-{
-	struct at91_udc *udc = &controller;
-	unsigned long	flags;
-
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
-	spin_lock_irqsave(&udc->lock, flags);
-	udc->enabled = 0;
-	at91_udp_write(udc, AT91_UDP_IDR, ~0);
-	pullup(udc, 0);
-	spin_unlock_irqrestore(&udc->lock, flags);
-
-	driver->unbind(&udc->gadget);
-	udc->gadget.dev.driver = NULL;
-	dev_set_drvdata(&udc->gadget.dev, NULL);
-	udc->driver = NULL;
-
-	DBG("unbound from %s\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
-
 /*-------------------------------------------------------------------------*/
 
 static void at91udc_shutdown(struct platform_device *dev)
@@ -1744,7 +1707,6 @@ static int __init at91udc_probe(struct platform_device *pdev)
 
 	/* init software state */
 	udc = &controller;
-	udc->gadget.dev.parent = dev;
 	udc->board = *(struct at91_udc_data *) dev->platform_data;
 	udc->pdev = pdev;
 	udc->enabled = 0;
@@ -1797,7 +1759,8 @@ static int __init at91udc_probe(struct platform_device *pdev)
 		goto fail0b;
 	}
 
-	retval = device_register(&udc->gadget.dev);
+	udc->udc.gadget = &udc->gadget;
+	retval = usb_add_udc(&pdev->dev, &udc->udc);
 	if (retval < 0)
 		goto fail0b;
 
@@ -1884,7 +1847,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 
 	DBG("remove\n");
 
-	if (udc->driver)
+	if (udc->udc.driver)
 		return -EBUSY;
 
 	spin_lock_irqsave(&udc->lock, flags);
@@ -1918,7 +1881,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
 	struct at91_udc *udc = platform_get_drvdata(pdev);
-	int		wake = udc->driver && device_may_wakeup(&pdev->dev);
+	int		wake = udc->udc.driver && device_may_wakeup(&pdev->dev);
 	unsigned long	flags;
 
 	/* Unless we can act normally to the host (letting it wake us up
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 108ca54..e1aee2b 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -22,6 +22,8 @@
 #ifndef AT91_UDC_H
 #define AT91_UDC_H
 
+#include <linux/usb/udc.h>
+
 /*
  * USB Device Port (UDP) registers.
  * Based on AT91RM9200 datasheet revision E.
@@ -125,9 +127,9 @@ struct at91_ep {
  * access protection for chip registers or driver state
  */
 struct at91_udc {
+	struct usb_udc			udc;
 	struct usb_gadget		gadget;
 	struct at91_ep			ep[NUM_ENDPOINTS];
-	struct usb_gadget_driver	*driver;
 	unsigned			vbus:1;
 	unsigned			enabled:1;
 	unsigned			clocked:1;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index dc65462..6b28d3f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -46,6 +46,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/usb.h>
+#include <linux/usb/udc.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/hcd.h>
 
@@ -160,8 +161,8 @@ struct dummy {
 	 */
 	struct dummy_ep			ep [DUMMY_ENDPOINTS];
 	int				address;
+	struct usb_udc			udc;
 	struct usb_gadget		gadget;
-	struct usb_gadget_driver	*driver;
 	struct dummy_request		fifo_req;
 	u8				fifo_buf [FIFO_SIZE];
 	u16				devstatus;
@@ -294,20 +295,20 @@ set_link_state (struct dummy *dum)
 			(dum->port_status & USB_PORT_STAT_RESET) != 0) {
 		if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
 				(dum->old_status & USB_PORT_STAT_RESET) == 0 &&
-				dum->driver) {
+				dum->udc.driver) {
 			stop_activity (dum);
 			spin_unlock (&dum->lock);
-			dum->driver->disconnect (&dum->gadget);
+			dum->udc.driver->disconnect (&dum->gadget);
 			spin_lock (&dum->lock);
 		}
 	} else if (dum->active != dum->old_active) {
-		if (dum->old_active && dum->driver->suspend) {
+		if (dum->old_active && dum->udc.driver->suspend) {
 			spin_unlock (&dum->lock);
-			dum->driver->suspend (&dum->gadget);
+			dum->udc.driver->suspend (&dum->gadget);
 			spin_lock (&dum->lock);
-		} else if (!dum->old_active && dum->driver->resume) {
+		} else if (!dum->old_active && dum->udc.driver->resume) {
 			spin_unlock (&dum->lock);
-			dum->driver->resume (&dum->gadget);
+			dum->udc.driver->resume (&dum->gadget);
 			spin_lock (&dum->lock);
 		}
 	}
@@ -341,7 +342,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
 	dum = ep_to_dummy (ep);
-	if (!dum->driver || !is_enabled (dum))
+	if (!dum->udc.driver || !is_enabled (dum))
 		return -ESHUTDOWN;
 	max = le16_to_cpu(desc->wMaxPacketSize) & 0x3ff;
 
@@ -518,7 +519,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 		return -EINVAL;
 
 	dum = ep_to_dummy (ep);
-	if (!dum->driver || !is_enabled (dum))
+	if (!dum->udc.driver || !is_enabled (dum))
 		return -ESHUTDOWN;
 
 #if 0
@@ -571,7 +572,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
 	ep = usb_ep_to_dummy_ep (_ep);
 	dum = ep_to_dummy (ep);
 
-	if (!dum->driver)
+	if (!dum->udc.driver)
 		return -ESHUTDOWN;
 
 	local_irq_save (flags);
@@ -606,7 +607,7 @@ dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
 		return -EINVAL;
 	ep = usb_ep_to_dummy_ep (_ep);
 	dum = ep_to_dummy (ep);
-	if (!dum->driver)
+	if (!dum->udc.driver)
 		return -ESHUTDOWN;
 	if (!value)
 		ep->halted = ep->wedged = 0;
@@ -710,11 +711,16 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
 	return 0;
 }
 
+static int dummy_gadget_start(struct usb_gadget *driver);
+static void dummy_gadget_stop(struct usb_gadget *driver);
+
 static const struct usb_gadget_ops dummy_ops = {
 	.get_frame	= dummy_g_get_frame,
 	.wakeup		= dummy_wakeup,
 	.set_selfpowered = dummy_set_selfpowered,
 	.pullup		= dummy_pullup,
+	.start		= dummy_gadget_start,
+	.stop		= dummy_gadget_stop,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -725,9 +731,9 @@ show_function (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
-	if (!dum->driver || !dum->driver->function)
+	if (!dum->udc.driver || !dum->udc.driver->function)
 		return 0;
-	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->udc.driver->function);
 }
 static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
@@ -747,19 +753,14 @@ static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
  * for each driver that registers:  just add to a big root hub.
  */
 
-int
-usb_gadget_register_driver (struct usb_gadget_driver *driver)
+static int
+dummy_gadget_start(struct usb_gadget *gadget)
 {
 	struct dummy	*dum = the_controller;
-	int		retval, i;
+	int		i;
 
 	if (!dum)
 		return -EINVAL;
-	if (dum->driver)
-		return -EBUSY;
-	if (!driver->bind || !driver->setup
-			|| driver->speed == USB_SPEED_UNKNOWN)
-		return -EINVAL;
 
 	/*
 	 * SLAVE side init ... the layer above hardware, which
@@ -786,23 +787,11 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
 		INIT_LIST_HEAD (&ep->queue);
 	}
 
-	dum->gadget.ep0 = &dum->ep [0].ep;
+	gadget->ep0 = &dum->ep [0].ep;
 	dum->ep [0].ep.maxpacket = 64;
 	list_del_init (&dum->ep [0].ep.ep_list);
 	INIT_LIST_HEAD(&dum->fifo_req.queue);
 
-	driver->driver.bus = NULL;
-	dum->driver = driver;
-	dum->gadget.dev.driver = &driver->driver;
-	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
-			driver->driver.name);
-	retval = driver->bind(&dum->gadget);
-	if (retval) {
-		dum->driver = NULL;
-		dum->gadget.dev.driver = NULL;
-		return retval;
-	}
-
 	/* khubd will enumerate this in a while */
 	spin_lock_irq (&dum->lock);
 	dum->pullup = 1;
@@ -812,40 +801,28 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
 
-int
-usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static void
+dummy_gadget_stop(struct usb_gadget *gadget)
 {
 	struct dummy	*dum = the_controller;
 	unsigned long	flags;
 
 	if (!dum)
-		return -ENODEV;
-	if (!driver || driver != dum->driver || !driver->unbind)
-		return -EINVAL;
-
-	dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
-			driver->driver.name);
+		return;
 
 	spin_lock_irqsave (&dum->lock, flags);
 	dum->pullup = 0;
 	set_link_state (dum);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
-	driver->unbind (&dum->gadget);
-	dum->gadget.dev.driver = NULL;
-	dum->driver = NULL;
-
 	spin_lock_irqsave (&dum->lock, flags);
 	dum->pullup = 0;
 	set_link_state (dum);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
-	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
 
 #undef is_enabled
 
@@ -859,32 +836,22 @@ int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
 EXPORT_SYMBOL (net2280_set_fifo_mode);
 
 
-/* The gadget structure is stored inside the hcd structure and will be
- * released along with it. */
-static void
-dummy_gadget_release (struct device *dev)
-{
-	struct dummy	*dum = gadget_dev_to_dummy (dev);
-
-	usb_put_hcd (dummy_to_hcd (dum));
-}
-
 static int dummy_udc_probe (struct platform_device *pdev)
 {
 	struct dummy	*dum = the_controller;
 	int		rc;
 
+	dum->udc.name = gadget_name;
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.is_dualspeed = 1;
+	dum->udc.gadget = &dum->gadget;
 
 	/* maybe claim OTG support, though we won't complete HNP */
 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
 
 	dev_set_name(&dum->gadget.dev, "gadget");
-	dum->gadget.dev.parent = &pdev->dev;
-	dum->gadget.dev.release = dummy_gadget_release;
-	rc = device_register (&dum->gadget.dev);
+	rc = usb_add_udc(&pdev->dev, &dum->udc);
 	if (rc < 0)
 		return rc;
 
@@ -903,7 +870,7 @@ static int dummy_udc_remove (struct platform_device *pdev)
 
 	platform_set_drvdata (pdev, NULL);
 	device_remove_file (&dum->gadget.dev, &dev_attr_function);
-	device_unregister (&dum->gadget.dev);
+	usb_del_udc(&dum->udc);
 	return 0;
 }
 
@@ -1443,7 +1410,7 @@ restart:
 			 */
 			if (value > 0) {
 				spin_unlock (&dum->lock);
-				value = dum->driver->setup (&dum->gadget,
+				value = dum->udc.driver->setup (&dum->gadget,
 						&setup);
 				spin_lock (&dum->lock);
 
@@ -1640,7 +1607,7 @@ static int dummy_hub_control (
 			if (dum->pullup) {
 				dum->port_status |= USB_PORT_STAT_ENABLE;
 				/* give it the best speed we agree on */
-				dum->gadget.speed = dum->driver->speed;
+				dum->gadget.speed = dum->udc.driver->speed;
 				dum->gadget.ep0->maxpacket = 64;
 				switch (dum->gadget.speed) {
 				case USB_SPEED_HIGH:
@@ -1841,7 +1808,7 @@ static void dummy_stop (struct usb_hcd *hcd)
 	dum = hcd_to_dummy (hcd);
 
 	device_remove_file (dummy_dev(dum), &dev_attr_urbs);
-	usb_gadget_unregister_driver (dum->driver);
+	usb_gadget_unregister_driver (dum->udc.driver);
 	dev_info (dummy_dev(dum), "stopped\n");
 }
 
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 540c766..9f26fc0 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -115,7 +115,7 @@
 #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
 
 
-unsigned musb_debug;
+unsigned musb_debug = 5;
 module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
@@ -1584,7 +1584,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
-		if (!musb->gadget_driver) {
+		if (!musb->udc.driver) {
 			DBG(5, "No gadget driver loaded\n");
 			return IRQ_HANDLED;
 		}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 91d6779..f35e457 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -42,6 +42,7 @@
 #include <linux/timer.h>
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/usb/udc.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb.h>
@@ -446,8 +447,9 @@ struct musb {
 	u8			test_mode_nr;
 	u16			ackpend;		/* ep0 */
 	enum musb_g_ep0_state	ep0_state;
+
+	struct usb_udc		udc;
 	struct usb_gadget	g;			/* the gadget */
-	struct usb_gadget_driver *gadget_driver;	/* its driver */
 #endif
 
 	struct musb_hdrc_config	*config;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 6fca870..6ad3f2b 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -47,6 +47,8 @@
 
 #include "musb_core.h"
 
+static int musb_gadget_start(struct usb_gadget *gadget);
+static void musb_gadget_stop(struct usb_gadget *gadget);
 
 /* MUSB PERIPHERAL status 3-mar-2006:
  *
@@ -1499,7 +1501,7 @@ static void musb_pullup(struct musb *musb, int is_on)
 	/* FIXME if on, HdrcStart; if off, HdrcStop */
 
 	DBG(3, "gadget %s D+ pullup %s\n",
-		musb->gadget_driver->function, is_on ? "on" : "off");
+		musb->udc.driver->function, is_on ? "on" : "off");
 	musb_writeb(musb->mregs, MUSB_POWER, power);
 }
 
@@ -1552,6 +1554,8 @@ static const struct usb_gadget_ops musb_gadget_operations = {
 	/* .vbus_session		= musb_gadget_vbus_session, */
 	.vbus_draw		= musb_gadget_vbus_draw,
 	.pullup			= musb_gadget_pullup,
+	.start			= musb_gadget_start,
+	.stop			= musb_gadget_stop,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -1564,13 +1568,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
  */
 static struct musb *the_gadget;
 
-static void musb_gadget_release(struct device *dev)
-{
-	/* kref_put(WHAT) */
-	dev_dbg(dev, "%s\n", __func__);
-}
-
-
 static void __init
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
@@ -1656,13 +1653,9 @@ int __init musb_gadget_setup(struct musb *musb)
 	musb->g.ops = &musb_gadget_operations;
 	musb->g.is_dualspeed = 1;
 	musb->g.speed = USB_SPEED_UNKNOWN;
-
-	/* this "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&musb->g.dev, "gadget");
-	musb->g.dev.parent = musb->controller;
-	musb->g.dev.dma_mask = musb->controller->dma_mask;
-	musb->g.dev.release = musb_gadget_release;
 	musb->g.name = musb_driver_name;
+	musb->udc.name = musb_driver_name;
+	musb->udc.gadget = &musb->g;
 
 	if (is_otg_enabled(musb))
 		musb->g.is_otg = 1;
@@ -1672,9 +1665,10 @@ int __init musb_gadget_setup(struct musb *musb)
 	musb->is_active = 0;
 	musb_platform_try_idle(musb, 0);
 
-	status = device_register(&musb->g.dev);
+	status = usb_add_udc(musb->controller, &musb->udc);
 	if (status != 0)
 		the_gadget = NULL;
+
 	return status;
 }
 
@@ -1683,7 +1677,7 @@ void musb_gadget_cleanup(struct musb *musb)
 	if (musb != the_gadget)
 		return;
 
-	device_unregister(&musb->g.dev);
+	usb_del_udc(&musb->udc);
 	the_gadget = NULL;
 }
 
@@ -1698,132 +1692,68 @@ void musb_gadget_cleanup(struct musb *musb)
  * @param driver the gadget driver
  * @return <0 if error, 0 if everything is fine
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+static int musb_gadget_start(struct usb_gadget *gadget)
 {
-	int retval;
+	struct musb *musb = gadget_to_musb(gadget);
 	unsigned long flags;
-	struct musb *musb = the_gadget;
-
-	if (!driver
-			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->setup)
-		return -EINVAL;
-
-	/* driver must be initialized to support peripheral mode */
-	if (!musb) {
-		DBG(1, "%s, no dev??\n", __func__);
-		return -ENODEV;
-	}
+	int retval = 0;
 
-	DBG(3, "registering driver %s\n", driver->function);
 	spin_lock_irqsave(&musb->lock, flags);
 
-	if (musb->gadget_driver) {
-		DBG(1, "%s is already bound to %s\n",
-				musb_driver_name,
-				musb->gadget_driver->driver.name);
-		retval = -EBUSY;
-	} else {
-		musb->gadget_driver = driver;
-		musb->g.dev.driver = &driver->driver;
-		driver->driver.bus = NULL;
-		musb->softconnect = 1;
-		retval = 0;
-	}
-
-	spin_unlock_irqrestore(&musb->lock, flags);
+	otg_set_peripheral(musb->xceiv, gadget);
+	musb->xceiv->state = OTG_STATE_B_IDLE;
+	musb->is_active = 1;
 
-	if (retval == 0) {
-		retval = driver->bind(&musb->g);
-		if (retval != 0) {
-			DBG(3, "bind to driver %s failed --> %d\n",
-					driver->driver.name, retval);
-			musb->gadget_driver = NULL;
-			musb->g.dev.driver = NULL;
-		}
+	/* FIXME this ignores the softconnect flag.  Drivers are
+	 * allowed hold the peripheral inactive until for example
+	 * userspace hooks up printer hardware or DSP codecs, so
+	 * hosts only see fully functional devices.
+	 */
 
-		spin_lock_irqsave(&musb->lock, flags);
+	if (!is_otg_enabled(musb))
+		musb_start(musb);
 
-		otg_set_peripheral(musb->xceiv, &musb->g);
-		musb->xceiv->state = OTG_STATE_B_IDLE;
-		musb->is_active = 1;
+	if (is_otg_enabled(musb)) {
+		DBG(3, "OTG startup...\n");
 
-		/* FIXME this ignores the softconnect flag.  Drivers are
-		 * allowed hold the peripheral inactive until for example
-		 * userspace hooks up printer hardware or DSP codecs, so
-		 * hosts only see fully functional devices.
+		/* REVISIT:  funcall to other code, which also
+		 * handles power budgeting ... this way also
+		 * ensures HdrcStart is indirectly called.
 		 */
-
-		if (!is_otg_enabled(musb))
-			musb_start(musb);
-
-		otg_set_peripheral(musb->xceiv, &musb->g);
-
-		spin_unlock_irqrestore(&musb->lock, flags);
-
-		if (is_otg_enabled(musb)) {
-			DBG(3, "OTG startup...\n");
-
-			/* REVISIT:  funcall to other code, which also
-			 * handles power budgeting ... this way also
-			 * ensures HdrcStart is indirectly called.
-			 */
-			retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
-			if (retval < 0) {
-				DBG(1, "add_hcd failed, %d\n", retval);
-				spin_lock_irqsave(&musb->lock, flags);
-				otg_set_peripheral(musb->xceiv, NULL);
-				musb->gadget_driver = NULL;
-				musb->g.dev.driver = NULL;
-				spin_unlock_irqrestore(&musb->lock, flags);
-			}
+		retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+		if (retval < 0) {
+			DBG(1, "add_hcd failed, %d\n", retval);
+			otg_set_peripheral(musb->xceiv, NULL);
 		}
 	}
 
+	spin_unlock_irqrestore(&musb->lock, flags);
+
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
 
-static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
+static void stop_activity(struct musb *musb)
 {
 	int			i;
 	struct musb_hw_ep	*hw_ep;
 
-	/* don't disconnect if it's not connected */
-	if (musb->g.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-	else
-		musb->g.speed = USB_SPEED_UNKNOWN;
-
-	/* deactivate the hardware */
-	if (musb->softconnect) {
-		musb->softconnect = 0;
-		musb_pullup(musb, 0);
-	}
 	musb_stop(musb);
 
 	/* killing any outstanding requests will quiesce the driver;
 	 * then report disconnect
 	 */
-	if (driver) {
-		for (i = 0, hw_ep = musb->endpoints;
-				i < musb->nr_endpoints;
-				i++, hw_ep++) {
-			musb_ep_select(musb->mregs, i);
-			if (hw_ep->is_shared_fifo /* || !epnum */) {
+	for (i = 0, hw_ep = musb->endpoints;
+			i < musb->nr_endpoints;
+			i++, hw_ep++) {
+		musb_ep_select(musb->mregs, i);
+		if (hw_ep->is_shared_fifo /* || !epnum */) {
+			nuke(&hw_ep->ep_in, -ESHUTDOWN);
+		} else {
+			if (hw_ep->max_packet_sz_tx)
 				nuke(&hw_ep->ep_in, -ESHUTDOWN);
-			} else {
-				if (hw_ep->max_packet_sz_tx)
-					nuke(&hw_ep->ep_in, -ESHUTDOWN);
-				if (hw_ep->max_packet_sz_rx)
-					nuke(&hw_ep->ep_out, -ESHUTDOWN);
-			}
+			if (hw_ep->max_packet_sz_rx)
+				nuke(&hw_ep->ep_out, -ESHUTDOWN);
 		}
-
-		spin_unlock(&musb->lock);
-		driver->disconnect(&musb->g);
-		spin_lock(&musb->lock);
 	}
 }
 
@@ -1833,14 +1763,10 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
  *
  * @param driver the gadget driver to unregister
  */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static void musb_gadget_stop(struct usb_gadget *gadget)
 {
+	struct musb	*musb = gadget_to_musb(gadget);
 	unsigned long	flags;
-	int		retval = 0;
-	struct musb	*musb = the_gadget;
-
-	if (!driver || !driver->unbind || !musb)
-		return -EINVAL;
 
 	/* REVISIT always use otg_set_peripheral() here too;
 	 * this needs to shut down the OTG engine.
@@ -1852,40 +1778,22 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	musb_hnp_stop(musb);
 #endif
 
-	if (musb->gadget_driver == driver) {
-
-		(void) musb_gadget_vbus_draw(&musb->g, 0);
-
-		musb->xceiv->state = OTG_STATE_UNDEFINED;
-		stop_activity(musb, driver);
-		otg_set_peripheral(musb->xceiv, NULL);
-
-		DBG(3, "unregistering driver %s\n", driver->function);
-		spin_unlock_irqrestore(&musb->lock, flags);
-		driver->unbind(&musb->g);
-		spin_lock_irqsave(&musb->lock, flags);
-
-		musb->gadget_driver = NULL;
-		musb->g.dev.driver = NULL;
+	musb->xceiv->state = OTG_STATE_UNDEFINED;
+	stop_activity(musb);
+	otg_set_peripheral(musb->xceiv, NULL);
 
-		musb->is_active = 0;
-		musb_platform_try_idle(musb, 0);
-	} else
-		retval = -EINVAL;
+	musb->is_active = 0;
+	musb_platform_try_idle(musb, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
-	if (is_otg_enabled(musb) && retval == 0) {
+	if (is_otg_enabled(musb)) {
 		usb_remove_hcd(musb_to_hcd(musb));
 		/* FIXME we need to be able to register another
 		 * gadget driver here and have everything work;
 		 * that currently misbehaves.
 		 */
 	}
-
-	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /* ----------------------------------------------------------------------- */
 
@@ -1900,9 +1808,9 @@ void musb_g_resume(struct musb *musb)
 	case OTG_STATE_B_WAIT_ACON:
 	case OTG_STATE_B_PERIPHERAL:
 		musb->is_active = 1;
-		if (musb->gadget_driver && musb->gadget_driver->resume) {
+		if (musb->udc.driver && musb->udc.driver->resume) {
 			spin_unlock(&musb->lock);
-			musb->gadget_driver->resume(&musb->g);
+			musb->udc.driver->resume(&musb->g);
 			spin_lock(&musb->lock);
 		}
 		break;
@@ -1927,9 +1835,9 @@ void musb_g_suspend(struct musb *musb)
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		musb->is_suspended = 1;
-		if (musb->gadget_driver && musb->gadget_driver->suspend) {
+		if (musb->udc.driver && musb->udc.driver->suspend) {
 			spin_unlock(&musb->lock);
-			musb->gadget_driver->suspend(&musb->g);
+			musb->udc.driver->suspend(&musb->g);
 			spin_lock(&musb->lock);
 		}
 		break;
@@ -1963,9 +1871,9 @@ void musb_g_disconnect(struct musb *musb)
 	(void) musb_gadget_vbus_draw(&musb->g, 0);
 
 	musb->g.speed = USB_SPEED_UNKNOWN;
-	if (musb->gadget_driver && musb->gadget_driver->disconnect) {
+	if (musb->udc.driver && musb->udc.driver->disconnect) {
 		spin_unlock(&musb->lock);
-		musb->gadget_driver->disconnect(&musb->g);
+		musb->udc.driver->disconnect(&musb->g);
 		spin_lock(&musb->lock);
 	}
 
@@ -2007,8 +1915,8 @@ __acquires(musb->lock)
 			(devctl & MUSB_DEVCTL_BDEVICE)
 				? "B-Device" : "A-Device",
 			musb_readb(mbase, MUSB_FADDR),
-			musb->gadget_driver
-				? musb->gadget_driver->driver.name
+			musb->udc.driver
+				? musb->udc.driver->driver.name
 				: NULL
 			);
 
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 59bef8f..d7d07f0 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -640,10 +640,10 @@ __releases(musb->lock)
 __acquires(musb->lock)
 {
 	int retval;
-	if (!musb->gadget_driver)
+	if (!musb->udc.driver)
 		return -EOPNOTSUPP;
 	spin_unlock(&musb->lock);
-	retval = musb->gadget_driver->setup(&musb->g, ctrlrequest);
+	retval = musb->udc.driver->setup(&musb->g, ctrlrequest);
 	spin_lock(&musb->lock);
 	return retval;
 }
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 3c48e77..010fab5 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -444,7 +444,7 @@ static void musb_do_idle(unsigned long _musb)
 			goto done;
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
-		if (is_peripheral_enabled(musb) && !musb->gadget_driver)
+		if (is_peripheral_enabled(musb) && !musb->udc.driver)
 			wakeups = 0;
 		else {
 			wakeups = TUSB_PRCM_WHOSTDISCON
-- 
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