Commit bf1ca153 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

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