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