ChangeSet 1.1500.8.24, 2004/02/05 16:33:43-08:00, [EMAIL PROTECTED]

[PATCH] USB Gadget: pxa2xx_udc updates

[USB] pxa2xx_udc updates, mostly for non-Lubbock hardware

  - IXP 42x UDC support (Greg Weeks)

  - remove Lubbock-specific build assumption (Guennadi Liakhovetski)

  - handle D+ pullup right on iPaqs, e7xx, etc (HH.org)

  - don't unbind() with irqs blocked; matches other controller drivers,
    and network layer expectations

  - handle some deferred ep0 responses better

  - support iso transfers (needs fifo size tracking)


 drivers/usb/gadget/pxa2xx_udc.c |  142 +++++++++++++++++++++++++++-------------
 drivers/usb/gadget/pxa2xx_udc.h |   18 +++--
 2 files changed, 109 insertions(+), 51 deletions(-)


diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c   Mon Feb  9 14:38:13 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.c   Mon Feb  9 14:38:13 2004
@@ -1,6 +1,6 @@
 /*
  * linux/drivers/usb/gadget/pxa2xx_udc.c
- * Intel PXA2xx on-chip full speed USB device controllers
+ * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers
  *
  * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
  * Copyright (C) 2003 Robert Schwebel, Pengutronix
@@ -59,27 +59,26 @@
 
 #include <asm/arch/udc.h>
 
-#include "pxa2xx_udc.h"
-
 
 /*
  * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx
  * series processors.  The UDC for the IXP 4xx series is very similar.
+ * There are fifteen endpoints, in addition to ep0.
  *
  * Such controller drivers work with a gadget driver.  The gadget driver
  * returns descriptors, implements configuration and data protocols used
  * by the host to interact with this device, and allocates endpoints to
  * the different protocol interfaces.  The controller driver virtualizes
  * usb hardware so that the gadget drivers will be more portable.
- *
+ * 
  * This UDC hardware wants to implement a bit too much USB protocol, so
  * it constrains the sorts of USB configuration change events that work.
  * The errata for these chips are misleading; some "fixed" bugs from
  * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
  */
 
-#define        DRIVER_VERSION  "7-Nov-2003"
-#define DRIVER_DESC    "PXA 2xx USB Device Controller driver"
+#define        DRIVER_VERSION  "14-Dec-2003"
+#define        DRIVER_DESC     "PXA 2xx USB Device Controller driver"
 
 
 static const char driver_name [] = "pxa2xx_udc";
@@ -95,6 +94,19 @@
 #define        UDC_PROC_FILE
 #endif
 
+#ifdef CONFIG_ARCH_IXP425
+#undef USE_DMA
+
+/* cpu-specific register addresses are compiled in to this code */
+#ifdef CONFIG_ARCH_PXA
+#error "Can't configure both IXP and PXA"
+#endif
+
+#endif
+
+#include "pxa2xx_udc.h"
+
+
 #ifdef CONFIG_EMBEDDED
 /* few strings, and little code to use them */
 #undef DEBUG
@@ -215,7 +227,8 @@
        if (!_ep || !desc || ep->desc || _ep->name == ep0name
                        || desc->bDescriptorType != USB_DT_ENDPOINT
                        || ep->bEndpointAddress != desc->bEndpointAddress
-                       || ep->ep.maxpacket < desc->wMaxPacketSize) {
+                       || ep->fifo_size < le16_to_cpu
+                                               (desc->wMaxPacketSize)) {
                DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
                return -EINVAL;
        }
@@ -230,7 +243,8 @@
 
        /* hardware _could_ do smaller, but driver doesn't */
        if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-                               && desc->wMaxPacketSize != BULK_FIFO_SIZE)
+                               && le16_to_cpu (desc->wMaxPacketSize)
+                                               != BULK_FIFO_SIZE)
                        || !desc->wMaxPacketSize) {
                DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
                return -ERANGE;
@@ -246,6 +260,7 @@
        ep->dma = -1;
        ep->stopped = 0;
        ep->pio_irqs = ep->dma_irqs = 0;
+       ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
 
        /* flush fifo (mostly for OUT buffers) */
        pxa2xx_ep_fifo_flush (_ep);
@@ -254,18 +269,18 @@
 
 #ifdef USE_DMA
        /* for (some) bulk and ISO endpoints, try to get a DMA channel and
-        * bind it to the endpoint.  otherwise use PIO.
+        * bind it to the endpoint.  otherwise use PIO. 
         */
        switch (ep->bmAttributes) {
        case USB_ENDPOINT_XFER_ISOC:
-               if (desc->wMaxPacketSize % 32)
+               if (le16_to_cpu(desc->wMaxPacketSize) % 32)
                        break;
                // fall through
        case USB_ENDPOINT_XFER_BULK:
                if (!use_dma || !ep->reg_drcmr)
                        break;
                ep->dma = pxa_request_dma ((char *)_ep->name,
-                               (desc->wMaxPacketSize > 64)
+                               (le16_to_cpu (desc->wMaxPacketSize) > 64)
                                        ? DMA_PRIO_MEDIUM /* some iso */
                                        : DMA_PRIO_LOW,
                                dma_nodesc_handler, ep);
@@ -437,7 +452,7 @@
 {
        unsigned                max;
 
-       max = ep->desc->wMaxPacketSize;
+       max = le16_to_cpu(ep->desc->wMaxPacketSize);
        do {
                unsigned        count;
                int             is_last, is_short;
@@ -454,13 +469,7 @@
                        else
                                is_last = 1;
                        /* interrupt/iso maxpacket may not fill the fifo */
-                       is_short = unlikely (max < ep->ep.maxpacket);
-
-                       /* FIXME ep.maxpacket should be the current size,
-                        * modified (for periodic endpoints) when the
-                        * ep is enabled.  do that, re-init as needed,
-                        * and change maxpacket refs accordingly.
-                        */
+                       is_short = unlikely (max < ep->fifo_size);
                }
 
                DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
@@ -598,7 +607,7 @@
                        req->req.actual += min (count, bufferspace);
                } else /* zlp */
                        count = 0;
-               is_short = (count < ep->desc->wMaxPacketSize);
+               is_short = (count < ep->ep.maxpacket);
                DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
                        ep->ep.name, udccs, count,
                        is_short ? "/S" : "",
@@ -897,13 +906,14 @@
         * we can report per-packet status.  that also helps with dma.
         */
        if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                       && req->req.length > ep->desc->wMaxPacketSize))
+                       && req->req.length > le16_to_cpu
+                                               (ep->desc->wMaxPacketSize)))
                return -EMSGSIZE;
 
 #ifdef USE_DMA
        // FIXME caller may already have done the dma mapping
        if (ep->dma >= 0) {
-               _req->dma = dma_map_single(&dev->dev.dev,
+               _req->dma = dma_map_single(dev->dev,
                        _req->buf, _req->length,
                        ((ep->bEndpointAddress & USB_DIR_IN) != 0)
                                ? DMA_TO_DEVICE
@@ -1017,11 +1027,21 @@
        unsigned long           flags;
 
        ep = container_of(_ep, struct pxa2xx_ep, ep);
-       req = container_of(_req, struct pxa2xx_request, req);
-       if (!_ep || !_req || ep->ep.name == ep0name)
+       if (!_ep || ep->ep.name == ep0name)
                return -EINVAL;
 
        local_irq_save(flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               local_irq_restore(flags);
+               return -EINVAL;
+       }
+
 #ifdef USE_DMA
        if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
                cancel_dma(ep);
@@ -1034,13 +1054,10 @@
                }
        } else
 #endif
-       if (!list_empty(&req->queue))
                done(ep, req, -ECONNRESET);
-       else
-               req = 0;
-       local_irq_restore(flags);
 
-       return req ? 0 : -EOPNOTSUPP;
+       local_irq_restore(flags);
+       return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1386,8 +1403,10 @@
 
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
+#ifdef CONFIG_ARCH_PXA
         /* Disable clock for USB device */
         CKEN &= ~CKEN11_USB;
+#endif
 
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1430,8 +1449,10 @@
 {
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
+#ifdef CONFIG_ARCH_PXA
         /* Enable clock for USB device */
         CKEN |= CKEN11_USB;
+#endif
 
        /* try to clear these bits before we enable the udc */
        udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
@@ -1590,9 +1611,10 @@
        local_irq_disable();
        udc_disable(dev);
        stop_activity(dev, driver);
+       local_irq_enable();
+
        driver->unbind(&dev->gadget);
        dev->driver = 0;
-       local_irq_enable();
 
        device_del (&dev->gadget.dev);
        device_remove_file(dev->dev, &dev_attr_function);
@@ -1776,7 +1798,6 @@
                                         * else use AREN (later) not SA|OPR
                                         * USIR0_IR0 acts edge sensitive
                                         */
-                                       dev->req_pending = 0;
                                }
                                break;
                        /* ... and here, even more ... */
@@ -1853,6 +1874,7 @@
                        /* pxa210/250 erratum 131 for B0/B1 says RNE lies.
                         * still observed on a pxa255 a0.
                         */
+                       DBG(DBG_VERBOSE, "e131\n");
                        nuke(ep, -EPROTO);
 
                        /* read SETUP data, but don't trust it too much */
@@ -2043,7 +2065,7 @@
                                stop_activity (dev, dev->driver);
 
                        } else {
-                               dev_info(&dev->gadget.dev, "USB reset\n");
+                               INFO("USB reset\n");
                                dev->gadget.speed = USB_SPEED_FULL;
                                LED_CONNECTED_ON;
                                memset(&dev->stats, 0, sizeof dev->stats);
@@ -2133,11 +2155,12 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 1,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS1,
                .reg_uddr       = &UDDR1,
-               .reg_drcmr      = &DRCMR25,
+               drcmr (25)
        },
        .ep[2] = {
                .ep = {
@@ -2146,12 +2169,13 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 2,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS2,
                .reg_ubcr       = &UBCR2,
                .reg_uddr       = &UDDR2,
-               .reg_drcmr      = &DRCMR26,
+               drcmr (26)
        },
 #ifndef CONFIG_USB_PXA2XX_SMALL
        .ep[3] = {
@@ -2161,11 +2185,12 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 3,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS3,
                .reg_uddr       = &UDDR3,
-               .reg_drcmr      = &DRCMR27,
+               drcmr (27)
        },
        .ep[4] = {
                .ep = {
@@ -2174,12 +2199,13 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 4,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS4,
                .reg_ubcr       = &UBCR4,
                .reg_uddr       = &UDDR4,
-               .reg_drcmr      = &DRCMR28,
+               drcmr (28)
        },
        .ep[5] = {
                .ep = {
@@ -2188,6 +2214,7 @@
                        .maxpacket      = INT_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 5,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
                .reg_udccs      = &UDCCS5,
@@ -2202,11 +2229,12 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 6,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS6,
                .reg_uddr       = &UDDR6,
-               .reg_drcmr      = &DRCMR30,
+               drcmr (30)
        },
        .ep[7] = {
                .ep = {
@@ -2215,12 +2243,13 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 7,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS7,
                .reg_ubcr       = &UBCR7,
                .reg_uddr       = &UDDR7,
-               .reg_drcmr      = &DRCMR31,
+               drcmr (31)
        },
        .ep[8] = {
                .ep = {
@@ -2229,11 +2258,12 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 8,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS8,
                .reg_uddr       = &UDDR8,
-               .reg_drcmr      = &DRCMR32,
+               drcmr (32)
        },
        .ep[9] = {
                .ep = {
@@ -2242,12 +2272,13 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 9,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS9,
                .reg_ubcr       = &UBCR9,
                .reg_uddr       = &UDDR9,
-               .reg_drcmr      = &DRCMR33,
+               drcmr (33)
        },
        .ep[10] = {
                .ep = {
@@ -2256,6 +2287,7 @@
                        .maxpacket      = INT_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 10,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
                .reg_udccs      = &UDCCS10,
@@ -2270,11 +2302,12 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 11,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS11,
                .reg_uddr       = &UDDR11,
-               .reg_drcmr      = &DRCMR35,
+               drcmr (35)
        },
        .ep[12] = {
                .ep = {
@@ -2283,12 +2316,13 @@
                        .maxpacket      = BULK_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 12,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS12,
                .reg_ubcr       = &UBCR12,
                .reg_uddr       = &UDDR12,
-               .reg_drcmr      = &DRCMR36,
+               drcmr (36)
        },
        .ep[13] = {
                .ep = {
@@ -2297,11 +2331,12 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 13,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS13,
                .reg_uddr       = &UDDR13,
-               .reg_drcmr      = &DRCMR37,
+               drcmr (37)
        },
        .ep[14] = {
                .ep = {
@@ -2310,12 +2345,13 @@
                        .maxpacket      = ISO_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 14,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS14,
                .reg_ubcr       = &UBCR14,
                .reg_uddr       = &UDDR14,
-               .reg_drcmr      = &DRCMR38,
+               drcmr (38)
        },
        .ep[15] = {
                .ep = {
@@ -2324,6 +2360,7 @@
                        .maxpacket      = INT_FIFO_SIZE,
                },
                .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 15,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
                .reg_udccs      = &UDCCS15,
@@ -2333,8 +2370,15 @@
 };
 
 #define CP15R0_VENDOR_MASK     0xffffe000
+
+#if    defined(CONFIG_ARCH_PXA)
 #define CP15R0_XSCALE_VALUE    0x69052000      /* intel/arm/xscale */
 
+#elif  defined(CONFIG_ARCH_IXP425)
+#define CP15R0_XSCALE_VALUE    0x69054000      /* intel/arm/ixp425 */
+
+#endif
+
 #define CP15R0_PROD_MASK       0x000003f0
 #define PXA25x                 0x00000100      /* and PXA26x */
 #define PXA210                 0x00000120
@@ -2355,6 +2399,7 @@
 #define PXA210_B2              0x00000124
 #define PXA210_B1              0x00000123
 #define PXA210_B0              0x00000122
+#define IXP425_A0              0x000001c1
 
 /*
  *     probe - binds to the platform device
@@ -2374,6 +2419,7 @@
 
        /* trigger chiprev-specific logic */
        switch (chiprev & CP15R0_PRODREV_MASK) {
+#if    defined(CONFIG_ARCH_PXA)
        case PXA255_A0:
                dev->has_cfr = 1;
                break;
@@ -2388,6 +2434,11 @@
                /* fall through */
        case PXA250_C0: case PXA210_C0:
                break;
+#elif  defined(CONFIG_ARCH_IXP425)
+       case IXP425_A0:
+               out_dma = 0;
+               break;
+#endif
        default:
                out_dma = 0;
                printk(KERN_ERR "%s: unrecognized processor: %08x\n",
@@ -2443,6 +2494,7 @@
        }
        dev->got_irq = 1;
 
+#ifdef CONFIG_ARCH_LUBBOCK
        if (machine_is_lubbock()) {
                disable_irq(LUBBOCK_USB_DISC_IRQ);
                retval = request_irq(LUBBOCK_USB_DISC_IRQ,
@@ -2457,7 +2509,7 @@
                }
                dev->got_disc = 1;
        }
-
+#endif
        create_proc_files();
 
        return 0;
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
--- a/drivers/usb/gadget/pxa2xx_udc.h   Mon Feb  9 14:38:13 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.h   Mon Feb  9 14:38:13 2004
@@ -52,14 +52,15 @@
        struct list_head                        queue;
        unsigned long                           pio_irqs;
        unsigned long                           dma_irqs;
-       int                                     dma;
+       short                                   dma; 
 
+       unsigned short                          fifo_size;
        u8                                      bEndpointAddress;
        u8                                      bmAttributes;
 
        unsigned                                stopped : 1;
        unsigned                                dma_fixup : 1;
-
+                                                        
        /* UDCCS = UDC Control/Status for this EP
         * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
         * UDDR = UDC Endpoint Data Register (the fifo)
@@ -68,7 +69,12 @@
        volatile u32                            *reg_udccs;
        volatile u32                            *reg_ubcr;
        volatile u32                            *reg_uddr;
+#ifdef USE_DMA
        volatile u32                            *reg_drcmr;
+#define        drcmr(n)  .reg_drcmr = & DRCMR ## n ,
+#else
+#define        drcmr(n)  
+#endif
 };
 
 struct pxa2xx_request {
@@ -76,7 +82,7 @@
        struct list_head                        queue;
 };
 
-enum ep0_state {
+enum ep0_state { 
        EP0_IDLE,
        EP0_IN_DATA_PHASE,
        EP0_OUT_DATA_PHASE,
@@ -181,14 +187,14 @@
 {
        if (!the_controller->mach->udc_command)
                return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+       the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
 
 static inline void let_usb_appear(void)
 {
        if (!the_controller->mach->udc_command)
                return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+       the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -305,7 +311,7 @@
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 
 #define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
-
+#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
 
 
 #endif /* __LINUX_USB_GADGET_PXA2XX_H */



-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to