*
  */
 
-#undef DEBUG
 // #define     VERBOSE DBG_VERBOSE
 
 #include <linux/device.h>
  * 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.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here.  IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can.  OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic).  So this driver won't
+ * bother using DMA.  (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
  */
 
-#define        DRIVER_VERSION  "4-May-2005"
+#define        DRIVER_VERSION  "30-June-2007"
 #define        DRIVER_DESC     "PXA 25x USB Device Controller driver"
 
 
 static const char ep0name [] = "ep0";
 
 
-// #define     USE_DMA
-// #define     USE_OUT_DMA
 // #define     DISABLE_TEST_MODE
 
 #ifdef CONFIG_ARCH_IXP4XX
-#undef USE_DMA
 
 /* cpu-specific register addresses are compiled in to this code */
 #ifdef CONFIG_ARCH_PXA
 #include "pxa2xx_udc.h"
 
 
-#ifdef USE_DMA
-static int use_dma = 1;
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC (use_dma, "true to use dma");
-
-static void dma_nodesc_handler (int dmach, void *_ep);
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
-
-#ifdef USE_OUT_DMA
-#define        DMASTR " (dma support)"
-#else
-#define        DMASTR " (dma in)"
-#endif
-
-#else  /* !USE_DMA */
-#define        DMASTR " (pio only)"
-#undef USE_OUT_DMA
-#endif
-
 #ifdef CONFIG_USB_PXA2XX_SMALL
 #define SIZE_STR       " (small)"
 #else
        }
 
        ep->desc = desc;
-       ep->dma = -1;
        ep->stopped = 0;
-       ep->pio_irqs = ep->dma_irqs = 0;
+       ep->pio_irqs = 0;
        ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
 
        /* flush fifo (mostly for OUT buffers) */
 
        /* ... reset halt state too, if we could ... */
 
-#ifdef USE_DMA
-       /* for (some) bulk and ISO endpoints, try to get a DMA channel and
-        * bind it to the endpoint.  otherwise use PIO.
-        */
-       switch (ep->bmAttributes) {
-       case USB_ENDPOINT_XFER_ISOC:
-               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,
-                               (le16_to_cpu (desc->wMaxPacketSize) > 64)
-                                       ? DMA_PRIO_MEDIUM /* some iso */
-                                       : DMA_PRIO_LOW,
-                               dma_nodesc_handler, ep);
-               if (ep->dma >= 0) {
-                       *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
-                       DMSG("%s using dma%d\n", _ep->name, ep->dma);
-               }
-       }
-#endif
-
        DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
        return 0;
 }
 
        nuke (ep, -ESHUTDOWN);
 
-#ifdef USE_DMA
-       if (ep->dma >= 0) {
-               *ep->reg_drcmr = 0;
-               pxa_free_dma (ep->dma);
-               ep->dma = -1;
-       }
-#endif
-
        /* flush fifo (mostly for IN buffers) */
        pxa2xx_ep_fifo_flush (_ep);
 
 }
 
 
-/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
- * no device-affinity and the heap works perfectly well for i/o buffers.
- * It wastes much less memory than dma_alloc_coherent() would, and even
- * prevents cacheline (32 bytes wide) sharing problems.
- */
 static void *
 pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
        dma_addr_t *dma, gfp_t gfp_flags)
 
        retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
        if (retval)
-#ifdef USE_DMA
-               *dma = virt_to_bus (retval);
-#else
                *dma = (dma_addr_t)~0;
-#endif
        return retval;
 }
 
                /* requests complete when all IN data is in the FIFO */
                if (is_last) {
                        done (ep, req, 0);
-                       if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
+                       if (list_empty(&ep->queue))
                                pio_irq_disable (ep->bEndpointAddress);
-#ifdef USE_DMA
-                               /* unaligned data and zlps couldn't use dma */
-                               if (unlikely(!list_empty(&ep->queue))) {
-                                       req = list_entry(ep->queue.next,
-                                               struct pxa2xx_request, queue);
-                                       kick_dma(ep,req);
-                                       return 0;
-                               }
-#endif
-                       }
                        return 1;
                }
 
        return 0;
 }
 
-#ifdef USE_DMA
-
-#define        MAX_IN_DMA      ((DCMD_LENGTH + 1) - BULK_FIFO_SIZE)
-
-static void
-start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in)
-{
-       u32     dcmd = req->req.length;
-       u32     buf = req->req.dma;
-       u32     fifo = io_v2p ((u32)ep->reg_uddr);
-
-       /* caller guarantees there's a packet or more remaining
-        *  - IN may end with a short packet (TSP set separately),
-        *  - OUT is always full length
-        */
-       buf += req->req.actual;
-       dcmd -= req->req.actual;
-       ep->dma_fixup = 0;
-
-       /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
-       DCSR(ep->dma) = DCSR_NODESC;
-       if (is_in) {
-               DSADR(ep->dma) = buf;
-               DTADR(ep->dma) = fifo;
-               if (dcmd > MAX_IN_DMA)
-                       dcmd = MAX_IN_DMA;
-               else
-                       ep->dma_fixup = (dcmd % ep->ep.maxpacket) != 0;
-               dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-                       | DCMD_FLOWTRG | DCMD_INCSRCADDR;
-       } else {
-#ifdef USE_OUT_DMA
-               DSADR(ep->dma) = fifo;
-               DTADR(ep->dma) = buf;
-               if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
-                       dcmd = ep->ep.maxpacket;
-               dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-                       | DCMD_FLOWSRC | DCMD_INCTRGADDR;
-#endif
-       }
-       DCMD(ep->dma) = dcmd;
-       DCSR(ep->dma) = DCSR_RUN | DCSR_NODESC
-               | (unlikely(is_in)
-                       ? DCSR_STOPIRQEN        /* use dma_nodesc_handler() */
-                       : 0);                   /* use handle_ep() */
-}
-
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-       int     is_in = ep->bEndpointAddress & USB_DIR_IN;
-
-       if (is_in) {
-               /* unaligned tx buffers and zlps only work with PIO */
-               if ((req->req.dma & 0x0f) != 0
-                               || unlikely((req->req.length - req->req.actual)
-                                               == 0)) {
-                       pio_irq_enable(ep->bEndpointAddress);
-                       if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0)
-                               (void) write_fifo(ep, req);
-               } else {
-                       start_dma_nodesc(ep, req, USB_DIR_IN);
-               }
-       } else {
-               if ((req->req.length - req->req.actual) < ep->ep.maxpacket) {
-                       DMSG("%s short dma read...\n", ep->ep.name);
-                       /* we're always set up for pio out */
-                       read_fifo (ep, req);
-               } else {
-                       *ep->reg_udccs = UDCCS_BO_DME
-                               | (*ep->reg_udccs & UDCCS_BO_FST);
-                       start_dma_nodesc(ep, req, USB_DIR_OUT);
-               }
-       }
-}
-
-static void cancel_dma(struct pxa2xx_ep *ep)
-{
-       struct pxa2xx_request   *req;
-       u32                     tmp;
-
-       if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
-               return;
-
-       DCSR(ep->dma) = 0;
-       while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
-               cpu_relax();
-
-       req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-       tmp = DCMD(ep->dma) & DCMD_LENGTH;
-       req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
-
-       /* the last tx packet may be incomplete, so flush the fifo.
-        * FIXME correct req.actual if we can
-        */
-       if (ep->bEndpointAddress & USB_DIR_IN)
-               *ep->reg_udccs = UDCCS_BI_FTF;
-}
-
-/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
-static void dma_nodesc_handler(int dmach, void *_ep)
-{
-       struct pxa2xx_ep        *ep = _ep;
-       struct pxa2xx_request   *req;
-       u32                     tmp, completed;
-
-       local_irq_disable();
-
-       req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-
-       ep->dma_irqs++;
-       ep->dev->stats.irqs++;
-       HEX_DISPLAY(ep->dev->stats.irqs);
-
-       /* ack/clear */
-       tmp = DCSR(ep->dma);
-       DCSR(ep->dma) = tmp;
-       if ((tmp & DCSR_STOPSTATE) == 0
-                       || (DDADR(ep->dma) & DDADR_STOP) != 0) {
-               DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n",
-                       ep->ep.name, DCSR(ep->dma), DDADR(ep->dma));
-               goto done;
-       }
-       DCSR(ep->dma) = 0;      /* clear DCSR_STOPSTATE */
-
-       /* update transfer status */
-       completed = tmp & DCSR_BUSERR;
-       if (ep->bEndpointAddress & USB_DIR_IN)
-               tmp = DSADR(ep->dma);
-       else
-               tmp = DTADR(ep->dma);
-       req->req.actual = tmp - req->req.dma;
-
-       /* FIXME seems we sometimes see partial transfers... */
-
-       if (unlikely(completed != 0))
-               req->req.status = -EIO;
-       else if (req->req.actual) {
-               /* these registers have zeroes in low bits; they miscount
-                * some (end-of-transfer) short packets:  tx 14 as tx 12
-                */
-               if (ep->dma_fixup)
-                       req->req.actual = min(req->req.actual + 3,
-                                               req->req.length);
-
-               tmp = (req->req.length - req->req.actual);
-               completed = (tmp == 0);
-               if (completed && (ep->bEndpointAddress & USB_DIR_IN)) {
-
-                       /* maybe validate final short packet ... */
-                       if ((req->req.actual % ep->ep.maxpacket) != 0)
-                               *ep->reg_udccs = UDCCS_BI_TSP/*|UDCCS_BI_TPC*/;
-
-                       /* ... or zlp, using pio fallback */
-                       else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK
-                                       && req->req.zero) {
-                               DMSG("%s zlp terminate ...\n", ep->ep.name);
-                               completed = 0;
-                       }
-               }
-       }
-
-       if (likely(completed)) {
-               done(ep, req, 0);
-
-               /* maybe re-activate after completion */
-               if (ep->stopped || list_empty(&ep->queue))
-                       goto done;
-               req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-       }
-       kick_dma(ep, req);
-done:
-       local_irq_enable();
-}
-
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 static int
                                                (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,
-                       _req->buf, _req->length,
-                       ((ep->bEndpointAddress & USB_DIR_IN) != 0)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
-       }
-#endif
-
        DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
-            _ep->name, _req, _req->length, _req->buf);
+               _ep->name, _req, _req->length, _req->buf);
 
        local_irq_save(flags);
 
                                local_irq_restore (flags);
                                return -EL2HLT;
                        }
-#ifdef USE_DMA
-               /* either start dma or prime pio pump */
-               } else if (ep->dma >= 0) {
-                       kick_dma(ep, req);
-#endif
                /* can the FIFO can satisfy the request immediately? */
                } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
                        if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
                        req = NULL;
                }
 
-               if (likely (req && ep->desc) && ep->dma < 0)
+               if (likely (req && ep->desc))
                        pio_irq_enable(ep->bEndpointAddress);
        }
 
        struct pxa2xx_request *req;
 
        /* called with irqs blocked */
-#ifdef USE_DMA
-       if (ep->dma >= 0 && !ep->stopped)
-               cancel_dma(ep);
-#endif
        while (!list_empty(&ep->queue)) {
                req = list_entry(ep->queue.next,
                                struct pxa2xx_request,
                return -EINVAL;
        }
 
-#ifdef USE_DMA
-       if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
-               cancel_dma(ep);
-               done(ep, req, -ECONNRESET);
-               /* restart i/o */
-               if (!list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                                       struct pxa2xx_request, queue);
-                       kick_dma(ep, req);
-               }
-       } else
-#endif
-               done(ep, req, -ECONNRESET);
+       done(ep, req, -ECONNRESET);
 
        local_irq_restore(flags);
        return 0;
        /* basic device status */
        t = scnprintf(next, size, DRIVER_DESC "\n"
                "%s version: %s\nGadget driver: %s\nHost %s\n\n",
-               driver_name, DRIVER_VERSION SIZE_STR DMASTR,
+               driver_name, DRIVER_VERSION SIZE_STR "(pio)",
                dev->driver ? dev->driver->driver.name : "(none)",
                is_vbus_present() ? "full speed" : "disconnected");
        size -= t;
        for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
                struct pxa2xx_ep        *ep = &dev->ep [i];
                struct pxa2xx_request   *req;
-               int                     t;
 
                if (i != 0) {
                        const struct usb_endpoint_descriptor    *d;
                                continue;
                        tmp = *dev->ep [i].reg_udccs;
                        t = scnprintf(next, size,
-                               "%s max %d %s udccs %02x irqs %lu/%lu\n",
+                               "%s max %d %s udccs %02x irqs %lu\n",
                                ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
-                               (ep->dma >= 0) ? "dma" : "pio", tmp,
-                               ep->pio_irqs, ep->dma_irqs);
+                               "pio", tmp, ep->pio_irqs);
                        /* TODO translate all five groups of udccs bits! */
 
                } else /* ep0 should only have one transfer queued */
                        continue;
                }
                list_for_each_entry(req, &ep->queue, queue) {
-#ifdef USE_DMA
-                       if (ep->dma >= 0 && req->queue.prev == &ep->queue)
-                               t = scnprintf(next, size,
-                                       "\treq %p len %d/%d "
-                                       "buf %p (dma%d dcmd %08x)\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf,
-                                       ep->dma, DCMD(ep->dma)
-                                       // low 13 bits == bytes-to-go
-                                       );
-                       else
-#endif
-                               t = scnprintf(next, size,
+                       t = scnprintf(next, size,
                                        "\treq %p len %d/%d buf %p\n",
                                        &req->req, req->req.actual,
                                        req->req.length, req->req.buf);
 
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
-       LED_CONNECTED_OFF;
 }
 
 
                ep->desc = NULL;
                ep->stopped = 0;
                INIT_LIST_HEAD (&ep->queue);
-               ep->pio_irqs = ep->dma_irqs = 0;
+               ep->pio_irqs = 0;
        }
 
        /* the rest was statically initialized, and is read-only */
        del_timer_sync(&dev->timer);
 
        /* report disconnect; the driver is already quiesced */
-       LED_CONNECTED_OFF;
        if (driver)
                driver->disconnect(&dev->gadget);
 
        int                     vbus;
 
        dev->stats.irqs++;
-       HEX_DISPLAY(dev->stats.irqs);
        switch (irq) {
        case LUBBOCK_USB_IRQ:
-               LED_CONNECTED_ON;
                vbus = 1;
                disable_irq(LUBBOCK_USB_IRQ);
                enable_irq(LUBBOCK_USB_DISC_IRQ);
                break;
        case LUBBOCK_USB_DISC_IRQ:
-               LED_CONNECTED_OFF;
                vbus = 0;
                disable_irq(LUBBOCK_USB_DISC_IRQ);
                enable_irq(LUBBOCK_USB_IRQ);
 
                        /* fifos can hold packets, ready for reading... */
                        if (likely(req)) {
-#ifdef USE_OUT_DMA
-// TODO didn't yet debug out-dma.  this approach assumes
-// the worst about short packets and RPC; it might be better.
-
-                               if (likely(ep->dma >= 0)) {
-                                       if (!(udccs & UDCCS_BO_RSP)) {
-                                               *ep->reg_udccs = UDCCS_BO_RPC;
-                                               ep->dma_irqs++;
-                                               return;
-                                       }
-                               }
-#endif
                                completed = read_fifo(ep, req);
                        } else
                                pio_irq_disable (ep->bEndpointAddress);
        int                     handled;
 
        dev->stats.irqs++;
-       HEX_DISPLAY(dev->stats.irqs);
        do {
                u32             udccr = UDCCR;
 
                        } else {
                                DBG(DBG_VERBOSE, "USB reset end\n");
                                dev->gadget.speed = USB_SPEED_FULL;
-                               LED_CONNECTED_ON;
                                memset(&dev->stats, 0, sizeof dev->stats);
                                /* driver and endpoints are still reset */
                        }
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS1,
                .reg_uddr       = &UDDR1,
-               drcmr (25)
        },
        .ep[2] = {
                .ep = {
                .reg_udccs      = &UDCCS2,
                .reg_ubcr       = &UBCR2,
                .reg_uddr       = &UDDR2,
-               drcmr (26)
        },
 #ifndef CONFIG_USB_PXA2XX_SMALL
        .ep[3] = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS3,
                .reg_uddr       = &UDDR3,
-               drcmr (27)
        },
        .ep[4] = {
                .ep = {
                .reg_udccs      = &UDCCS4,
                .reg_ubcr       = &UBCR4,
                .reg_uddr       = &UDDR4,
-               drcmr (28)
        },
        .ep[5] = {
                .ep = {
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS6,
                .reg_uddr       = &UDDR6,
-               drcmr (30)
        },
        .ep[7] = {
                .ep = {
                .reg_udccs      = &UDCCS7,
                .reg_ubcr       = &UBCR7,
                .reg_uddr       = &UDDR7,
-               drcmr (31)
        },
        .ep[8] = {
                .ep = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS8,
                .reg_uddr       = &UDDR8,
-               drcmr (32)
        },
        .ep[9] = {
                .ep = {
                .reg_udccs      = &UDCCS9,
                .reg_ubcr       = &UBCR9,
                .reg_uddr       = &UDDR9,
-               drcmr (33)
        },
        .ep[10] = {
                .ep = {
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
                .reg_udccs      = &UDCCS11,
                .reg_uddr       = &UDDR11,
-               drcmr (35)
        },
        .ep[12] = {
                .ep = {
                .reg_udccs      = &UDCCS12,
                .reg_ubcr       = &UBCR12,
                .reg_uddr       = &UDDR12,
-               drcmr (36)
        },
        .ep[13] = {
                .ep = {
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
                .reg_udccs      = &UDCCS13,
                .reg_uddr       = &UDDR13,
-               drcmr (37)
        },
        .ep[14] = {
                .ep = {
                .reg_udccs      = &UDCCS14,
                .reg_ubcr       = &UBCR14,
                .reg_uddr       = &UDDR14,
-               drcmr (38)
        },
        .ep[15] = {
                .ep = {
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
        struct pxa2xx_udc *dev = &memory;
-       int retval, out_dma = 1, vbus_irq, irq;
+       int retval, vbus_irq, irq;
        u32 chiprev;
 
        /* insist on Intel/ARM/XScale */
        case PXA250_B2: case PXA210_B2:
        case PXA250_B1: case PXA210_B1:
        case PXA250_B0: case PXA210_B0:
-               out_dma = 0;
+               /* OUT-DMA is broken ... */
                /* fall through */
        case PXA250_C0: case PXA210_C0:
                break;
        case IXP425_B0:
        case IXP465_AD:
                dev->has_cfr = 1;
-               out_dma = 0;
                break;
 #endif
        default:
-               out_dma = 0;
                printk(KERN_ERR "%s: unrecognized processor: %08x\n",
                        driver_name, chiprev);
                /* iop3xx, ixp4xx, ... */
        if (irq < 0)
                return -ENODEV;
 
-       pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
+       pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
                dev->has_cfr ? "" : " (!cfr)",
-               out_dma ? "" : " (broken dma-out)",
-               SIZE_STR DMASTR
+               SIZE_STR "(pio)"
                );
 
-#ifdef USE_DMA
-#ifndef        USE_OUT_DMA
-       out_dma = 0;
-#endif
-       /* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */
-       if (!out_dma) {
-               DMSG("disabled OUT dma\n");
-               dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;
-               dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;
-               dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;
-       }
-#endif
-
        /* other non-static parts of init */
        dev->dev = &pdev->dev;
        dev->mach = pdev->dev.platform_data;
                        free_irq(LUBBOCK_USB_DISC_IRQ, dev);
                        goto lubbock_fail0;
                }
-#ifdef DEBUG
-               /* with U-Boot (but not BLOB), hex is off by default */
-               HEX_DISPLAY(dev->stats.irqs);
-               LUB_DISC_BLNK_LED &= 0xff;
-#endif
        } else
 #endif
        if (vbus_irq) {