diff options
46 files changed, 19975 insertions, 0 deletions
diff --git a/packages/linux/linux-2.6.21/.mtn2git_empty b/packages/linux/linux-2.6.21/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-2.6.21/.mtn2git_empty diff --git a/packages/linux/linux-2.6.21/270-usb-gadget-udc.patch b/packages/linux/linux-2.6.21/270-usb-gadget-udc.patch new file mode 100644 index 0000000000..630d188ea0 --- /dev/null +++ b/packages/linux/linux-2.6.21/270-usb-gadget-udc.patch @@ -0,0 +1,2739 @@ +Index: linux-2.6.21gum/drivers/usb/gadget/Kconfig +=================================================================== +--- linux-2.6.21gum.orig/drivers/usb/gadget/Kconfig ++++ linux-2.6.21gum/drivers/usb/gadget/Kconfig +@@ -129,6 +129,28 @@ config USB_PXA2XX_SMALL + default y if USB_ETH + default y if USB_G_SERIAL + ++config USB_GADGET_PXA27X ++ boolean "PXA 27x" ++ depends on ARCH_PXA && PXA27x ++ help ++ Intel's PXA 27x series XScale ARM-5TE processors include ++ an integrated full speed USB 1.1 device controller. ++ ++ Say "y" to link the driver statically, or "m" to build a ++ dynamically linked module called "pxa27x_udc" and force all ++ gadget drivers to also be dynamically linked. ++ ++config USB_PXA27X ++ tristate ++ depends on USB_GADGET_PXA27X ++ default USB_GADGET ++ select USB_GADGET_SELECTED ++ ++config USB_PXA27X_DMA ++ bool # "Use DMA support" ++ depends on USB_GADGET_PXA27X ++ default n ++ + config USB_GADGET_GOKU + boolean "Toshiba TC86C001 'Goku-S'" + depends on PCI +Index: linux-2.6.21gum/drivers/usb/gadget/Makefile +=================================================================== +--- linux-2.6.21gum.orig/drivers/usb/gadget/Makefile ++++ linux-2.6.21gum/drivers/usb/gadget/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o + obj-$(CONFIG_USB_GOKU) += goku_udc.o + obj-$(CONFIG_USB_OMAP) += omap_udc.o + obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o ++obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o + obj-$(CONFIG_USB_AT91) += at91_udc.o + obj-$(CONFIG_USB_GADGET_GUMSTIX) += gumstix_gadget.o + +Index: linux-2.6.21gum/drivers/usb/gadget/pxa27x_udc.c +=================================================================== +--- /dev/null ++++ linux-2.6.21gum/drivers/usb/gadget/pxa27x_udc.c +@@ -0,0 +1,2352 @@ ++/* ++ * linux/drivers/usb/gadget/pxa27x_udc.c ++ * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers ++ * ++ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) ++ * Copyright (C) 2003 Robert Schwebel, Pengutronix ++ * Copyright (C) 2003 Benedikt Spranger, Pengutronix ++ * Copyright (C) 2003 David Brownell ++ * Copyright (C) 2003 Joshua Wise ++ * Copyright (C) 2004 Intel Corporation ++ * Copyright (C) 2005 SDG Systems, LLC (Aric Blumer) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#undef DEBUG ++ // #define DEBUG 1 ++ //#define VERBOSE DBG_VERBOSE ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/ioport.h> ++#include <linux/types.h> ++#include <linux/version.h> ++#include <linux/errno.h> ++#include <linux/delay.h> ++#include <linux/sched.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/timer.h> ++#include <linux/list.h> ++#include <linux/interrupt.h> ++#include <linux/proc_fs.h> ++#include <linux/mm.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <linux/irq.h> ++ ++#include <asm/byteorder.h> ++#include <asm/dma.h> ++#include <asm/io.h> ++#include <asm/system.h> ++#include <asm/mach-types.h> ++#include <asm/unaligned.h> ++#include <asm/hardware.h> ++#include <asm/mach/irq.h> ++#include <asm/arch/pxa-regs.h> ++ ++#include <linux/usb/ch9.h> ++#include <linux/usb_gadget.h> ++ ++#include <asm/arch/udc.h> ++ ++ ++/* ++ * This driver handles the USB Device Controller (UDC) in Intel's PXA 27777777x ++ * series processors. ++ * 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 "21-Jul-2005" ++#define DRIVER_DESC "PXA 27x USB Device Controller driver" ++ ++ ++static const char driver_name [] = "pxa27x_udc"; ++ ++static const char ep0name [] = "ep0"; ++ ++ ++#define USE_DMA ++//#define DISABLE_TEST_MODE ++ ++#ifdef CONFIG_PROC_FS ++#define UDC_PROC_FILE ++#endif ++ ++#include "pxa27x_udc.h" ++ ++#if 0 ++#ifdef CONFIG_EMBEDDED ++/* few strings, and little code to use them */ ++#undef DEBUG ++#undef UDC_PROC_FILE ++#endif ++#endif ++ ++#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 pxa27x_ep *ep, struct pxa27x_request *req); ++ ++#define DMASTR " (dma support)" ++ ++#else /* !USE_DMA */ ++#define DMASTR " (pio only)" ++#endif ++ ++#ifdef CONFIG_USB_PXA27X_SMALL ++#define SIZE_STR " (small)" ++#else ++#define SIZE_STR "" ++#endif ++ ++#ifdef DISABLE_TEST_MODE ++/* (mode == 0) == no undocumented chip tweaks ++ * (mode & 1) == double buffer bulk IN ++ * (mode & 2) == double buffer bulk OUT ++ * ... so mode = 3 (or 7, 15, etc) does it for both ++ */ ++static ushort fifo_mode = 0; ++module_param(fifo_mode, ushort, 0); ++MODULE_PARM_DESC (fifo_mode, "pxa27x udc fifo mode"); ++#endif ++ ++#define UDCISR0_IR0 0x3 ++#define UDCISR_INT_MASK (UDC_INT_FIFOERROR | UDC_INT_PACKETCMP) ++#define UDCICR_INT_MASK UDCISR_INT_MASK ++ ++#define UDCCSR_MASK (UDCCSR_FST | UDCCSR_DME) ++/* --------------------------------------------------------------------------- ++ * endpoint related parts of the api to the usb controller hardware, ++ * used by gadget driver; and the inner talker-to-hardware core. ++ * --------------------------------------------------------------------------- ++ */ ++ ++static void pxa27x_ep_fifo_flush (struct usb_ep *ep); ++static void nuke (struct pxa27x_ep *, int status); ++ ++static void pio_irq_enable(int ep_num) ++{ ++ if (ep_num < 16) ++ UDCICR0 |= 3 << (ep_num * 2); ++ else { ++ ep_num -= 16; ++ UDCICR1 |= 3 << (ep_num * 2); ++ } ++} ++ ++static void pio_irq_disable(int ep_num) ++{ ++ ep_num &= 0xf; ++ if (ep_num < 16) ++ UDCICR0 &= ~(3 << (ep_num * 2)); ++ else { ++ ep_num -= 16; ++ UDCICR1 &= ~(3 << (ep_num * 2)); ++ } ++} ++ ++/* The UDCCR reg contains mask and interrupt status bits, ++ * so using '|=' isn't safe as it may ack an interrupt. ++ */ ++#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_UDE) ++ ++static inline void udc_set_mask_UDCCR(int mask) ++{ ++ UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); ++} ++ ++static inline void udc_clear_mask_UDCCR(int mask) ++{ ++ UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); ++} ++ ++static inline void udc_ack_int_UDCCR(int mask) ++{ ++ /* udccr contains the bits we dont want to change */ ++ __u32 udccr = UDCCR & UDCCR_MASK_BITS; ++ ++ UDCCR = udccr | (mask & ~UDCCR_MASK_BITS); ++} ++ ++/* ++ * endpoint enable/disable ++ * ++ * we need to verify the descriptors used to enable endpoints. since pxa27x ++ * endpoint configurations are fixed, and are pretty much always enabled, ++ * there's not a lot to manage here. ++ * ++ * because pxa27x can't selectively initialize bulk (or interrupt) endpoints, ++ * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except ++ * for a single interface (with only the default altsetting) and for gadget ++ * drivers that don't halt endpoints (not reset by set_interface). that also ++ * means that if you use ISO, you must violate the USB spec rule that all ++ * iso endpoints must be in non-default altsettings. ++ */ ++static int pxa27x_ep_enable (struct usb_ep *_ep, ++ const struct usb_endpoint_descriptor *desc) ++{ ++ struct pxa27x_ep *ep; ++ struct pxa27x_udc *dev; ++ ++ ep = container_of (_ep, struct pxa27x_ep, ep); ++ if (!_ep || !desc || _ep->name == ep0name ++ || desc->bDescriptorType != USB_DT_ENDPOINT ++ || ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { ++ DMSG("%s, bad ep or descriptor\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ /* xfer types must match, except that interrupt ~= bulk */ ++ if( ep->ep_type != USB_ENDPOINT_XFER_BULK ++ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { ++ DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name); ++ return -EINVAL; ++ } ++ ++ /* hardware _could_ do smaller, but driver doesn't */ ++ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK ++ && le16_to_cpu (desc->wMaxPacketSize) ++ != BULK_FIFO_SIZE) ++ || !desc->wMaxPacketSize) { ++ DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); ++ return -ERANGE; ++ } ++ ++ dev = ep->dev; ++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { ++ DMSG("%s, bogus device state\n", __FUNCTION__); ++ return -ESHUTDOWN; ++ } ++ ++ ep->desc = desc; ++ 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) */ ++ pxa27x_ep_fifo_flush (_ep); ++ ++ /* ... 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. ++ */ ++ DMSG("%s: called attributes=%d\n", __FUNCTION__, ep->ep_type); ++ switch (ep->ep_type) { ++ 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); ++ } ++ default: ++ break; ++ } ++#endif ++ DBG(DBG_VERBOSE, "enabled %s\n", _ep->name); ++ return 0; ++} ++ ++static int pxa27x_ep_disable (struct usb_ep *_ep) ++{ ++ struct pxa27x_ep *ep; ++ ++ ep = container_of (_ep, struct pxa27x_ep, ep); ++ if (!_ep || !ep->desc) { ++ DMSG("%s, %s not enabled\n", __FUNCTION__, ++ _ep ? ep->ep.name : NULL); ++ return -EINVAL; ++ } ++ 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) */ ++ pxa27x_ep_fifo_flush (_ep); ++ ++ ep->desc = 0; ++ ep->stopped = 1; ++ ++ DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); ++ return 0; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* for the pxa27x, these can just wrap kmalloc/kfree. gadget drivers ++ * must still pass correctly initialized endpoints, since other controller ++ * drivers may care about how it's currently set up (dma issues etc). ++ */ ++ ++/* ++ * pxa27x_ep_alloc_request - allocate a request data structure ++ */ ++static struct usb_request * ++pxa27x_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags) ++{ ++ struct pxa27x_request *req; ++ ++ req = kmalloc (sizeof *req, gfp_flags); ++ if (!req) ++ return 0; ++ ++ memset (req, 0, sizeof *req); ++ INIT_LIST_HEAD (&req->queue); ++ return &req->req; ++} ++ ++ ++/* ++ * pxa27x_ep_free_request - deallocate a request data structure ++ */ ++static void ++pxa27x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) ++{ ++ struct pxa27x_request *req; ++ ++ req = container_of(_req, struct pxa27x_request, req); ++ WARN_ON (!list_empty (&req->queue)); ++ kfree(req); ++} ++ ++ ++/* 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 * ++pxa27x_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, ++ dma_addr_t *dma, unsigned gfp_flags) ++{ ++ char *retval; ++ ++ retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM)); ++ if (retval) ++ *dma = virt_to_bus (retval); ++ return retval; ++} ++ ++static void ++pxa27x_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, ++ unsigned bytes) ++{ ++ kfree (buf); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * done - retire a request; caller blocked irqs ++ */ ++static void done(struct pxa27x_ep *ep, struct pxa27x_request *req, int status) ++{ ++ list_del_init(&req->queue); ++ if (likely (req->req.status == -EINPROGRESS)) ++ req->req.status = status; ++ else ++ status = req->req.status; ++ ++ if (status && status != -ESHUTDOWN) ++ DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n", ++ ep->ep.name, &req->req, status, ++ req->req.actual, req->req.length); ++ ++ /* don't modify queue heads during completion callback */ ++ req->req.complete(&ep->ep, &req->req); ++} ++ ++ ++static inline void ep0_idle (struct pxa27x_udc *dev) ++{ ++ dev->ep0state = EP0_IDLE; ++ LED_EP0_OFF; ++} ++ ++static int ++write_packet(volatile u32 *uddr, struct pxa27x_request *req, unsigned max) ++{ ++ u32 *buf; ++ int length, count, remain; ++ ++ buf = (u32*)(req->req.buf + req->req.actual); ++ prefetch(buf); ++ ++ /* how big will this packet be? */ ++ length = min(req->req.length - req->req.actual, max); ++ req->req.actual += length; ++ ++ remain = length & 0x3; ++ count = length & ~(0x3); ++ ++ while (likely(count)) { ++ *uddr = *buf++; ++ count -= 4; ++ } ++ ++ if (remain) { ++ volatile u8* reg=(u8*)uddr; ++ char *rd =(u8*)buf; ++ ++ while (remain--) { ++ *reg=*rd++; ++ } ++ } ++ ++ return length; ++} ++ ++/* ++ * write to an IN endpoint fifo, as many packets as possible. ++ * irqs will use this to write the rest later. ++ * caller guarantees at least one packet buffer is ready (or a zlp). ++ */ ++static int ++write_fifo (struct pxa27x_ep *ep, struct pxa27x_request *req) ++{ ++ unsigned max; ++ ++ max = le16_to_cpu(ep->desc->wMaxPacketSize); ++ do { ++ int count; ++ int is_last, is_short; ++ ++ count = write_packet(ep->reg_udcdr, req, max); ++ ++ /* last packet is usually short (or a zlp) */ ++ if (unlikely (count != max)) ++ is_last = is_short = 1; ++ else { ++ if (likely(req->req.length != req->req.actual) ++ || req->req.zero) ++ is_last = 0; ++ else ++ is_last = 1; ++ /* interrupt/iso maxpacket may not fill the fifo */ ++ is_short = unlikely (max < ep->fifo_size); ++ } ++ ++ DMSG("wrote %s count:%d bytes%s%s %d left %p\n", ++ ep->ep.name, count, ++ is_last ? "/L" : "", is_short ? "/S" : "", ++ req->req.length - req->req.actual, &req->req); ++ ++ /* let loose that packet. maybe try writing another one, ++ * double buffering might work. TSP, TPC, and TFS ++ * bit values are the same for all normal IN endpoints. ++ */ ++ *ep->reg_udccsr = UDCCSR_PC; ++ if (is_short) ++ *ep->reg_udccsr = UDCCSR_SP; ++ ++ /* 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)) { ++ pio_irq_disable (ep->ep_num); ++#ifdef USE_DMA ++ /* unaligned data and zlps couldn't use dma */ ++ if (unlikely(!list_empty(&ep->queue))) { ++ req = list_entry(ep->queue.next, ++ struct pxa27x_request, queue); ++ kick_dma(ep,req); ++ return 0; ++ } ++#endif ++ } ++ return 1; ++ } ++ ++ // TODO experiment: how robust can fifo mode tweaking be? ++ // double buffering is off in the default fifo mode, which ++ // prevents TFS from being set here. ++ ++ } while (*ep->reg_udccsr & UDCCSR_FS); ++ return 0; ++} ++ ++/* caller asserts req->pending (ep0 irq status nyet cleared); starts ++ * ep0 data stage. these chips want very simple state transitions. ++ */ ++static inline ++void ep0start(struct pxa27x_udc *dev, u32 flags, const char *tag) ++{ ++ UDCCSR0 = flags|UDCCSR0_SA|UDCCSR0_OPC; ++ UDCISR0 = UDCICR_INT(0, UDC_INT_FIFOERROR | UDC_INT_PACKETCMP); ++ dev->req_pending = 0; ++ DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n", ++ __FUNCTION__, tag, UDCCSR0, flags); ++} ++ ++static int ++write_ep0_fifo (struct pxa27x_ep *ep, struct pxa27x_request *req) ++{ ++ unsigned count; ++ int is_short; ++ ++ count = write_packet(&UDCDR0, req, EP0_FIFO_SIZE); ++ ep->dev->stats.write.bytes += count; ++ ++ /* last packet "must be" short (or a zlp) */ ++ is_short = (count != EP0_FIFO_SIZE); ++ ++ DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count, ++ req->req.length - req->req.actual, &req->req); ++ ++ if (unlikely (is_short)) { ++ if (ep->dev->req_pending) ++ ep0start(ep->dev, UDCCSR0_IPR, "short IN"); ++ else ++ UDCCSR0 = UDCCSR0_IPR; ++ ++ count = req->req.length; ++ done (ep, req, 0); ++ ep0_idle(ep->dev); ++#if 0 ++ /* This seems to get rid of lost status irqs in some cases: ++ * host responds quickly, or next request involves config ++ * change automagic, or should have been hidden, or ... ++ * ++ * FIXME get rid of all udelays possible... ++ */ ++ if (count >= EP0_FIFO_SIZE) { ++ count = 100; ++ do { ++ if ((UDCCSR0 & UDCCSR0_OPC) != 0) { ++ /* clear OPC, generate ack */ ++ UDCCSR0 = UDCCSR0_OPC; ++ break; ++ } ++ count--; ++ udelay(1); ++ } while (count); ++ } ++#endif ++ } else if (ep->dev->req_pending) ++ ep0start(ep->dev, 0, "IN"); ++ return is_short; ++} ++ ++ ++/* ++ * read_fifo - unload packet(s) from the fifo we use for usb OUT ++ * transfers and put them into the request. caller should have made ++ * sure there's at least one packet ready. ++ * ++ * returns true if the request completed because of short packet or the ++ * request buffer having filled (and maybe overran till end-of-packet). ++ */ ++static int ++read_fifo (struct pxa27x_ep *ep, struct pxa27x_request *req) ++{ ++ for (;;) { ++ u32 *buf; ++ int bufferspace, count, is_short; ++ ++ /* make sure there's a packet in the FIFO.*/ ++ if (unlikely ((*ep->reg_udccsr & UDCCSR_PC) == 0)) ++ break; ++ buf =(u32*) (req->req.buf + req->req.actual); ++ prefetchw(buf); ++ bufferspace = req->req.length - req->req.actual; ++ ++ /* read all bytes from this packet */ ++ if (likely (*ep->reg_udccsr & UDCCSR_BNE)) { ++ count = 0x3ff & *ep->reg_udcbcr; ++ req->req.actual += min (count, bufferspace); ++ } else /* zlp */ ++ count = 0; ++ ++ is_short = (count < ep->ep.maxpacket); ++ DMSG("read %s udccsr:%02x, count:%d bytes%s req %p %d/%d\n", ++ ep->ep.name, *ep->reg_udccsr, count, ++ is_short ? "/S" : "", ++ &req->req, req->req.actual, req->req.length); ++ ++// dump_regs(ep->ep_num ); ++ count = min(count, bufferspace); ++ while (likely (count > 0)) { ++ *buf++ = *ep->reg_udcdr; ++ count -= 4; ++ } ++ DMSG("Buf:0x%p\n", req->req.buf); ++ ++ *ep->reg_udccsr = UDCCSR_PC; ++ /* RPC/RSP/RNE could now reflect the other packet buffer */ ++ ++ /* completion */ ++ if (is_short || req->req.actual == req->req.length) { ++ done (ep, req, 0); ++ if (list_empty(&ep->queue)) ++ pio_irq_disable (ep->ep_num); ++ return 1; ++ } ++ ++ /* finished that packet. the next one may be waiting... */ ++ } ++ return 0; ++} ++ ++/* ++ * special ep0 version of the above. no UBCR0 or double buffering; status ++ * handshaking is magic. most device protocols don't need control-OUT. ++ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other ++ * protocols do use them. ++ */ ++static int ++read_ep0_fifo (struct pxa27x_ep *ep, struct pxa27x_request *req) ++{ ++ u32 *buf, word; ++ unsigned bufferspace; ++ ++ buf = (u32*) (req->req.buf + req->req.actual); ++ bufferspace = req->req.length - req->req.actual; ++ ++ while (UDCCSR0 & UDCCSR0_RNE) { |
