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