Please merge to 2.6.3. This is what you saw before, with the addition of the tweak from Guennadi Liakhovetski.
Thanks in advance.
- Dave
[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)
--- a/drivers/usb/gadget/pxa2xx_udc.c Wed Feb 4 20:30:57 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.c Wed Feb 4 20:30:57 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;
--- a/drivers/usb/gadget/pxa2xx_udc.h Wed Feb 4 20:30:57 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.h Wed Feb 4 20:30:57 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 */
