public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] Support for PXA27X UDC.
@ 2009-02-23 16:05 Vivek Kutal
  2009-03-05 11:15 ` Remy Bohmer
  0 siblings, 1 reply; 11+ messages in thread
From: Vivek Kutal @ 2009-02-23 16:05 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
---
 drivers/serial/usbtty.h             |    4 +-
 drivers/usb/Makefile                |    1 +
 drivers/usb/usbdcore_pxa27x.c       |  712 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-pxa/pxa-regs.h |  337 +++++++++++++----
 include/usbdcore_pxa27x.h           |   68 ++++
 5 files changed, 1049 insertions(+), 73 deletions(-)
 create mode 100644 drivers/usb/usbdcore_pxa27x.c
 create mode 100644 include/usbdcore_pxa27x.h

diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index ecefde5..5fe872e 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -27,8 +27,10 @@
 #include <usbdcore.h>
 #if defined(CONFIG_PPC)
 #include <usbdcore_mpc8xx.h>
-#elif defined(CONFIG_ARM)
+#elif defined(CONFIG_OMAP1510)
 #include <usbdcore_omap1510.h>
+#elif defined(CONFIG_PXA27X)
+#include <usbdcore_pxa27x.h>
 #endif
 
 #include <version_autogenerated.h>
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index b306a65..0a1886a 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -47,6 +47,7 @@ COBJS-y += usbdcore_ep0.o
 COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
 COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
 COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
+COBJS-$(CONFIG_PXA27X) += usbdcore_pxa27x.o
 endif
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/usb/usbdcore_pxa27x.c b/drivers/usb/usbdcore_pxa27x.c
new file mode 100644
index 0000000..6dfbf3d
--- /dev/null
+++ b/drivers/usb/usbdcore_pxa27x.c
@@ -0,0 +1,712 @@
+/*
+ * PXA27x USB device driver for u-boot.
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2008 Vivek Kutal     <vivek.kutal@azingo.com>
+ *
+ * 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
+ *
+ */
+
+
+#include <common.h>
+#include <config.h>
+#include <asm/byteorder.h>
+#include <usbdcore.h>
+#include <usbdcore_ep0.h>
+#include <asm/arch/hardware.h>
+#include <usbdcore_pxa27x.h>
+
+#define UDC_MAX_ENDPOINTS	24	/* number of endpoints on this UDC */
+
+static struct urb *ep0_urb = NULL;
+static struct usb_device_instance *udc_device;
+static int ep0state = EP0_IDLE;
+
+#ifdef USBDDBG
+static void udc_dump_buffer(char *name, u8 *buf, int len)
+{
+	int i, p, flag = 1;
+
+	usbdbg("%s - buf %p, len %d", name, buf, len);
+	for (i = p = 0; i < len; i++, p++) {
+		if (p == 0) {
+			flag = 0;
+			usbdbg("\t");
+		}
+
+		usbdbg("%02x ", buf[i]);
+
+		if (p == 15) {
+			flag = 1;
+			usbdbg("\n");
+			p = -1;
+		}
+	}
+	if (!flag)
+		usbdbg("\n");
+}
+#else
+#define udc_dump_buffer(name, buf, len)		/* void */
+#endif
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+	USIR1	= mask | USIR1;
+}
+
+/*
+ * If the endpoint has an active tx_urb, then the next packet of data from the
+ * URB is written to the tx FIFO.
+ * The total amount of data in the urb is given by urb->actual_length.
+ * The maximum amount of data that can be sent in any one packet is given by
+ * endpoint->tx_packetSize.
+ * The number of data bytes from this URB that have already been transmitted
+ * is given by endpoint->sent.
+ * endpoint->last is updated by this routine with the number of data bytes
+ * transmitted in this packet.
+ */
+static int udc_write_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->tx_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+
+	u32 *addr32 = (u32 *) &UDCDN(ep_num),
+		*data32 = (u32 *) urb->buffer;
+	u8  *addr8 = (u8 *) &UDCDN(ep_num),
+		*data8 = (u8 *) urb->buffer;
+	unsigned int i, n, w, b, is_short;
+	int timeout = 2000;	/* 2ms */
+
+	if (!urb || !urb->actual_length)
+		return -1;
+
+	n = MIN(urb->actual_length - endpoint->sent, endpoint->tx_packetSize);
+	if (n <= 0)
+		return -1;
+
+	usbdbg("write urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: sent %d, tx_packetSize %d, last %d",
+		endpoint->sent, endpoint->tx_packetSize, endpoint->last);
+#endif
+
+	is_short = n != endpoint->tx_packetSize;
+	w = n / 4;
+	b = n % 4;
+	usbdbg("n %d%s w %d b %d", n, is_short ? "-s" : "", w, b);
+	udc_dump_buffer("urb write", data8 + endpoint->sent, n);
+	/* Prepare for data send */
+
+	if (ep_num)
+		UDCCSN(ep_num) = UDCCSR_PC;
+
+	for (i = 0; i < w; i++)
+		*addr32 = data32[endpoint->sent/4 + i];
+	for (i = 0; i < b; i++)
+		*addr8 = data8[endpoint->sent + w*4 + i];
+
+	/* Set "Packet Complete" if less data then tx_packetSize */
+	if (is_short)
+		UDCCSN(ep_num) = ep_num ? UDCCSR_SP : UDCCSR0_IPR;
+
+	/* Wait for data sent */
+	while (!(UDCCSN(ep_num) & (ep_num ? UDCCSR_PC : UDCCSR0_IPR))) {
+		if (ep_num) {
+			if (timeout-- == 0)
+				return -1;
+			else
+				udelay(1);
+		};
+	}
+	endpoint->last = n;
+
+	if(ep_num) {
+		usbd_tx_complete(endpoint);
+	} else {
+		endpoint->sent += n;
+		endpoint->last -= n;
+	}
+
+	if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) {
+		urb->actual_length = 0;
+		endpoint->sent = 0;
+		endpoint->last = 0;
+	}
+
+	if ((endpoint->sent >= urb->actual_length) && (!ep_num)) {
+		usbdbg("ep0 IN stage done");
+		if(is_short)
+			ep0state = EP0_IDLE;
+		else
+			ep0state = EP0_XFER_COMPLETE;
+	}
+
+	return 0;
+}
+
+static int udc_read_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->rcv_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	u32 *addr32 = (u32 *) &UDCDN(ep_num),
+		*data32 = (u32 *) urb->buffer;
+	unsigned int i, n, is_short ;
+
+	usbdbg("read urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: rcv_packetSize %d",
+		endpoint->rcv_packetSize);
+#endif
+
+	if (UDCCSN(ep_num) & UDCCSR_BNE)
+		n = UDCBCN(ep_num) & 0x3ff;
+	else /* zlp */
+		n = 0;
+	is_short = n != endpoint->rcv_packetSize;
+
+	usbdbg("n %d%s", n, is_short ? "-s" : "");
+	for (i = 0; i < n; i += 4)
+		data32[urb->actual_length/4 + i/4] = *addr32;
+
+	udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n);
+
+	usbd_rcv_complete(endpoint, n, 0);
+
+	return 0;
+}
+
+static int udc_read_urb_ep0(void)
+{
+	u32 *addr32 = (u32 *) &UDCDN(0),
+		*data32 = (u32 *) ep0_urb->buffer;
+	u8  *addr8 = (u8 *) &UDCDN(0),
+		*data8 = (u8 *) ep0_urb->buffer;
+	unsigned int i, n, w, b;
+
+	n = UDCBCR0;
+	w = n / 4;
+	b = n % 4;
+
+	for (i = 0; i < w; i++) {
+		data32[ep0_urb->actual_length/4 + i] = *addr32;
+		ep0_urb->actual_length += 4;
+	}
+
+	for (i = 0; i < b; i++ ) {
+		data8[ep0_urb->actual_length + w*4 + i] = *addr8;
+		ep0_urb->actual_length++;
+	}
+
+	UDCCSR0 = UDCCSR0_OPC | UDCCSR0_IPR;
+	if(ep0_urb->actual_length == ep0_urb->device_request.wLength)
+		return 1;
+	return 0;
+}
+
+static void udc_handle_ep0(struct usb_endpoint_instance *endpoint)
+{
+	u32 udccsr0 = UDCCSR0;
+	u32 *data = (u32 *) &ep0_urb->device_request;
+	int i;
+
+	usbdbg("udccsr0 %x", udccsr0);
+
+    /* Clear stall status */
+	if (udccsr0 & UDCCSR0_SST) {
+		usberr("clear stall status");
+		UDCCSR0 = UDCCSR0_SST;
+		ep0state = EP0_IDLE;
+	}
+
+	/* previous request unfinished?  non-error iff back-to-back ... */
+    if ((udccsr0 & UDCCSR0_SA) != 0 && ep0state != EP0_IDLE)
+		ep0state = EP0_IDLE;
+
+	switch (ep0state) {
+		case EP0_IDLE :
+
+			udccsr0 = UDCCSR0;
+			/* Start control request? */
+			if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE))
+				== (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) {
+
+				/* Read SETUP packet.
+				 * SETUP packet size is 8 bytes (aka 2 words)
+				 */
+				usbdbg("try reading SETUP packet");
+				for (i = 0; i < 2; i++) {
+				if ((UDCCSR0 & UDCCSR0_RNE) == 0) {
+			        usberr("setup packet too short (%d)", i);
+					goto stall;
+				}
+				data[i] = UDCDR0;
+			}
+			UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);
+			if ((UDCCSR0 & UDCCSR0_RNE) != 0) {
+			    usberr("setup packet too long");
+				goto stall;
+			}
+
+			udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+
+			if(ep0_urb->device_request.wLength == 0) {
+
+				usbdbg("Zero Data control Packet\n");
+
+				if(ep0_recv_setup(ep0_urb)) {
+					usberr("Invalid Setup Packet\n");
+					udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+					goto stall;
+				}
+				UDCCSR0 = UDCCSR0_IPR;
+				ep0state = EP0_IDLE;
+			}
+			else {
+				/* Check direction */
+				if ((ep0_urb->device_request.bmRequestType
+					& USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
+					ep0state = EP0_OUT_DATA;
+					ep0_urb->buffer = (u8 *)ep0_urb->buffer_data;
+					ep0_urb->buffer_length = sizeof(ep0_urb->buffer_data);
+					ep0_urb->actual_length = 0;
+					UDCCSR0 = UDCCSR0_IPR;
+				}
+				else {
+					/* The ep0_recv_setup function has already placed our
+					 * response packet data in ep0_urb->buffer and the
+					 * packet length in ep0_urb->actual_length.
+					 */
+					if (ep0_recv_setup(ep0_urb)) {
+stall:
+						usberr("Invalid setup packet");
+						udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+						ep0state= EP0_IDLE;
+						UDCCSR0 = UDCCSR0_SA|UDCCSR0_OPC | UDCCSR0_FST | UDCCS0_FTF;
+						return;
+					}
+
+					endpoint->tx_urb = ep0_urb;
+					endpoint->sent = 0;
+					usbdbg("EP0_IN_DATA");
+					ep0state = EP0_IN_DATA;
+					if(udc_write_urb(endpoint) < 0)
+						goto stall;
+
+				}
+			}
+			return;
+		}
+		else if ((udccsr0 & (UDCCSR0_OPC |UDCCSR0_SA))
+			== (UDCCSR0_OPC|UDCCSR0_SA)) {
+			usberr("Setup Active but no data. Stalling ....\n");
+			goto stall;
+        }
+		else {
+			usbdbg("random early IRQs");
+			/* Some random early IRQs:
+			 * - we acked FST
+			 * - IPR cleared
+			 * - OPC got set, without SA (likely status stage)
+			 */
+			UDCCSR0 = udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC);
+
+		}
+		break;
+
+		case EP0_OUT_DATA :
+
+			if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {
+				if(udc_read_urb_ep0()) {
+read_complete:
+					ep0state = EP0_IDLE;
+					if (ep0_recv_setup(ep0_urb)) {
+						/* Not a setup packet, stall next EP0 transaction */
+						udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+						usberr("can't parse setup packet\n");
+						goto stall;
+					}
+				}
+			}
+			else if(!(udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_IPR)) {
+				if(ep0_urb->device_request.wLength == ep0_urb->actual_length)
+					goto read_complete;
+				usberr("Premature Status\n");
+				ep0state = EP0_IDLE;
+			}
+			break;
+
+		case EP0_IN_DATA :
+			/* GET_DESCRIPTOR etc */
+			if (udccsr0 & UDCCSR0_OPC) {
+				UDCCSR0 = UDCCSR0_OPC | UDCCSR0_FTF;
+				usberr("ep0in premature status");
+				ep0state = EP0_IDLE;
+			}
+			else {
+				/* irq was IPR clearing */
+				if(udc_write_urb(endpoint) < 0) {
+					usberr("ep0_write_error\n");
+					goto stall;
+				}
+			}
+			break;
+
+		case EP0_XFER_COMPLETE:
+			UDCCSR0 = UDCCSR0_IPR;
+			ep0state = EP0_IDLE;
+			break;
+
+		default:
+			usbdbg("Default\n");
+	}
+	USIR0 = USIR0_IR0;
+}
+
+static void udc_handle_ep(struct usb_endpoint_instance *endpoint)
+{
+	int ep_addr = endpoint->endpoint_address;
+	int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	int ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+
+	u32 flags = UDCCSN(ep_num) & (UDCCSR_SST | UDCCSR_TRN);
+	if (flags)
+		UDCCSN(ep_num) = flags;
+
+	if (ep_isout)
+		udc_read_urb(endpoint);
+	else
+		udc_write_urb(endpoint);
+
+	UDCCSN(ep_num) = UDCCSR_PC;
+}
+
+static void udc_state_changed(void)
+{
+	int config, interface, alternate;
+
+	UDCCR |= UDCCR_SMAC;
+
+	config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;
+	interface =  (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;
+	alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;
+
+	usbdbg("New UDC settings are: conf %d - inter %d - alter %d",
+		config, interface, alternate);
+
+	usbd_device_event_irq (udc_device, DEVICE_CONFIGURED, 0);
+
+	UDCISR1 = UDCISR1_IRCC;
+}
+
+
+
+void udc_irq(void)
+{
+	int			handled;
+	struct usb_endpoint_instance *endpoint;
+    int ep_num, i;
+    u32 udcisr0;
+
+	do {
+		handled = 0;
+		/* Suspend Interrupt Request */
+		if (USIR1 & UDCCR_SUSIR) {
+
+			usbdbg("Suspend\n");
+			udc_ack_int_UDCCR(UDCCR_SUSIR);
+			handled = 1;
+			ep0state = EP0_IDLE;
+		}
+
+		/* Resume Interrupt Request */
+		if (USIR1 & UDCCR_RESIR) {
+			udc_ack_int_UDCCR(UDCCR_RESIR);
+			handled = 1;
+			usbdbg( "USB resume\n");
+
+		}
+
+		if (USIR1 & (1<<31) ){
+			handled=1;
+			udc_state_changed();
+		}
+
+		/* Reset Interrupt Request */
+		if (USIR1 & UDCCR_RSTIR) {
+			udc_ack_int_UDCCR(UDCCR_RSTIR);
+			handled = 1;
+			usbdbg("Reset\n");
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+		} else {
+			if(USIR0)
+				usbdbg("UISR0: %x \n",USIR0);
+
+		    if (USIR0 & 0x2)	USIR0 = 0x2;
+
+			/* Control traffic */
+			if (USIR0  & USIR0_IR0) {
+				handled = 1;
+				udc_handle_ep0(udc_device->bus->endpoint_array);
+				USIR0 = USIR0_IR0;
+			}
+
+			endpoint = udc_device->bus->endpoint_array;
+			for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+		        ep_num = (endpoint[i].endpoint_address) & USB_ENDPOINT_NUMBER_MASK;
+		        if (!ep_num)
+		            continue;
+		        udcisr0 = UDCISR0;
+			    if (udcisr0 & UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) {
+		            UDCISR0 = UDCISR_INT(ep_num, UDC_INT_PACKETCMP);
+					udc_handle_ep(&endpoint[i]);
+
+				}
+			}
+
+		}
+
+	} while (handled);
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_OEN   (1 << 31)   /* On-the-Go Enable */
+#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 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);
+    }
+}
+
+/*
+ * udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ */
+void udc_set_nak(int ep_num)
+{
+	/* TODO */
+}
+
+/*
+ * udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ */
+void udc_unset_nak(int ep_num)
+{
+	/* TODO */
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+	return udc_write_urb(endpoint);
+}
+
+/* Associate a physical endpoint with endpoint instance */
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id, struct usb_endpoint_instance *endpoint)
+{
+	int ep_num, ep_addr, ep_isout, ep_type, ep_size;
+	int config, interface, alternate;
+	u32 tmp;
+
+	usbdbg("setting up endpoint id %d", id);
+
+	if (!endpoint) {
+		usberr("endpoint void!");
+		return;
+	}
+
+	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	if (ep_num >= UDC_MAX_ENDPOINTS) {
+		usberr("unable to setup ep %d!",ep_num);
+		return;
+	}
+
+	pio_irq_enable(ep_num);
+	if (ep_num == 0) {
+		/* Done for ep0 */
+		return;
+	}
+
+	config = 1;
+	interface = 0;
+	alternate = 0;
+
+	usbdbg("config %d - interface %d - alternate %d",
+		config, interface, alternate);
+
+	ep_addr = endpoint->endpoint_address;
+	ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+	ep_type = ep_isout ? endpoint->rcv_attributes : endpoint->tx_attributes;
+	ep_size = ep_isout ? endpoint->rcv_packetSize : endpoint->tx_packetSize;
+
+	usbdbg("addr %x, num %d, dir %s, type %s, packet size %d",
+		ep_addr, ep_num,
+		ep_isout ? "out" : "in",
+		ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" :
+		   ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" :
+		   ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???",
+		ep_size
+		);
+
+	/* Configure UDCCRx */
+	tmp = 0;
+	tmp |= (config << UDCCONR_CN_S) & UDCCONR_CN;
+	tmp |= (interface << UDCCONR_IN_S) & UDCCONR_IN;
+	tmp |= (alternate << UDCCONR_AISN_S) & UDCCONR_AISN;
+	tmp |= (ep_num << UDCCONR_EN_S) & UDCCONR_EN;
+	tmp |= (ep_type << UDCCONR_ET_S) & UDCCONR_ET;
+	tmp |= ep_isout ? 0 : UDCCONR_ED;
+	tmp |= (ep_size << UDCCONR_MPS_S ) & UDCCONR_MPS;
+	tmp |= /* UDCCONR_DE | */ UDCCONR_EE;
+
+	UDCCN(ep_num) = tmp;
+
+	usbdbg("UDCCR%c = %x", 'A' + ep_num-1, UDCCN(ep_num));
+	usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, UDCCSN(ep_num));
+}
+
+
+
+#define CONFIG_USB_DEV_PULLUP_GPIO 87
+
+/* Connect the USB device to the bus */
+void udc_connect(void)
+{
+	usbdbg("UDC connect");
+
+	/* Turn on the USB connection by enabling the pullup resistor */
+    set_GPIO_mode(CONFIG_USB_DEV_PULLUP_GPIO | GPIO_OUT);
+	GPSR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Disconnect the USB device to the bus */
+void udc_disconnect(void)
+{
+	usbdbg("UDC disconnect");
+
+	/* Turn off the USB connection by disabling the pullup resistor */
+	GPCR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Switch on the UDC */
+void udc_enable(struct usb_device_instance *device)
+{
+
+    ep0state = EP0_IDLE;
+	CKEN |= CKEN11_USB;
+
+    /* enable endpoint 0, A, B's Packet Complete Interrupt. */
+    UDCICR0 = 0x0000003f;
+    UDCICR1 = 0xa8000000;
+
+    /* clear the interrupt status/control registers */
+    UDCISR0 = 0xffffffff;
+    UDCISR1 = 0xffffffff;
+
+    /* set UDC-enable */
+    udc_set_mask_UDCCR( UDCCR_UDE);
+
+	udc_device = device;
+	if (!ep0_urb)
+		ep0_urb = usbd_alloc_urb(udc_device,udc_device->bus->endpoint_array);
+	else
+		usbinfo("ep0_urb %p already allocated", ep0_urb);
+
+	usbdbg("UDC Enabled\n");
+}
+
+/* Need to check this again */
+void udc_disable(void)
+{
+	usbdbg("disable UDC");
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Free ep0 URB */
+	if (ep0_urb) {
+		usbd_dealloc_urb(ep0_urb);
+		ep0_urb = NULL;
+	}
+
+	/* Reset device pointer */
+	udc_device = NULL;
+}
+
+/* Allow udc code to do any additional startup */
+void udc_startup_events(struct usb_device_instance *device)
+{
+	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT */
+	usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+	/* The DEVICE_CREATE event puts the USB device in the state
+	 * STATE_ATTACHED */
+	usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+	/* Some USB controller driver implementations signal
+	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+	 * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
+	 * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
+	 */
+	udc_enable(device);
+}
+
+/* Initialize h/w stuff */
+int udc_init(void)
+{
+	udc_device = NULL;
+	usbdbg("PXA27x usbd start");
+
+	/* Disable the UDC */
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Disable IRQs: we don't use them */
+	UDCICR0 = UDCICR1 = 0;
+
+	return 0;
+}
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e014568..7aeac1e 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -596,56 +596,68 @@ typedef void		(*ExcpHndlr) (void) ;
 /*
  * USB Device Controller
  */
-#ifndef CONFIG_CPU_MONAHANS
-#define UDC_RES1	__REG(0x40600004)  /* UDC Undocumented - Reserved1 */
-#define UDC_RES2	__REG(0x40600008)  /* UDC Undocumented - Reserved2 */
-#define UDC_RES3	__REG(0x4060000C)  /* UDC Undocumented - Reserved3 */
-
-#define UDCCR		__REG(0x40600000)  /* UDC Control Register */
-#define UDCCR_UDE	(1 << 0)	/* UDC enable */
-#define UDCCR_UDA	(1 << 1)	/* UDC active */
-#define UDCCR_RSM	(1 << 2)	/* Device resume */
-#define UDCCR_RESIR	(1 << 3)	/* Resume interrupt request */
-#define UDCCR_SUSIR	(1 << 4)	/* Suspend interrupt request */
-#define UDCCR_SRM	(1 << 5)	/* Suspend/resume interrupt mask */
-#define UDCCR_RSTIR	(1 << 6)	/* Reset interrupt request */
-#define UDCCR_REM	(1 << 7)	/* Reset interrupt mask */
-
-#define UDCCS0		__REG(0x40600010)  /* UDC Endpoint 0 Control/Status Register */
-#define UDCCS0_OPR	(1 << 0)	/* OUT packet ready */
-#define UDCCS0_IPR	(1 << 1)	/* IN packet ready */
-#define UDCCS0_FTF	(1 << 2)	/* Flush Tx FIFO */
-#define UDCCS0_DRWF	(1 << 3)	/* Device remote wakeup feature */
-#define UDCCS0_SST	(1 << 4)	/* Sent stall */
-#define UDCCS0_FST	(1 << 5)	/* Force stall */
-#define UDCCS0_RNE	(1 << 6)	/* Receive FIFO no empty */
-#define UDCCS0_SA	(1 << 7)	/* Setup active */
+#ifdef CONFIG_PXA27X
+
+#define UDCCR			__REG(0x40600000)	/* UDC Control Register */
+#define UDCCR_UDE		(1 << 0)		/* UDC enable */
+#define UDCCR_UDA		(1 << 1)		/* UDC active */
+#define UDCCR_RSM		(1 << 2)		/* Device resume */
+#define UDCCR_EMCE		(1 << 3)		/* Endpoint Memory Configuration Error */
+#define UDCCR_SMAC		(1 << 4)		/* Switch Endpoint Memory to Active Configuration */
+#define UDCCR_RESIR		(1 << 29)		/* Resume interrupt request */
+#define UDCCR_SUSIR		(1 << 28)		/* Suspend interrupt request */
+#define UDCCR_SM		(1 << 28)		/* Suspend interrupt mask */
+#define UDCCR_RSTIR		(1 << 27)		/* Reset interrupt request */
+#define UDCCR_REM		(1 << 27)		/* Reset interrupt mask */
+#define UDCCR_RM		(1 << 29)		/* resume interrupt mask */
+#define UDCCR_SRM		UDCCR_SM|UDCCR_RM
+#define UDCCR_OEN		(1 << 31)		/* On-the-Go Enable */
+#define UDCCR_AALTHNP	(1 << 30)		/* A-device Alternate Host Negotiation Protocol Port Support */
+#define UDCCR_AHNP		(1 << 29)		/* A-device Host Negotiation Protocol Support */
+#define UDCCR_BHNP		(1 << 28)		/* B-device Host Negotiation Protocol Enable */
+#define UDCCR_DWRE		(1 << 16)		/* Device Remote Wake-up Enable */
+#define UDCCR_ACN		(0x03 << 11)	/* Active UDC configuration Number */
+#define UDCCR_ACN_S		11
+#define UDCCR_AIN		(0x07 << 8)		/* Active UDC interface Number */
+#define UDCCR_AIN_S		8
+#define UDCCR_AAISN		(0x07 << 5)		/* Active UDC Alternate Interface  Setting Number */
+#define UDCCR_AAISN_S	5
+
+#define UDCCS0			__REG(0x40600100)	/* UDC Endpoint 0 Control/Status Register */
+#define UDCCS0_OPR		(1 << 0)			/* OUT packet ready */
+#define UDCCS0_IPR		(1 << 1)			/* IN packet ready */
+#define UDCCS0_FTF		(1 << 2)			/* Flush Tx FIFO */
+#define UDCCS0_DRWF		(1 << 16)			/* Device remote wakeup feature */
+#define UDCCS0_SST		(1 << 4)			/* Sent stall */
+#define UDCCS0_FST		(1 << 5)			/* Force stall */
+#define UDCCS0_RNE		(1 << 6)			/* Receive FIFO no empty */
+#define UDCCS0_SA		(1 << 7)			/* Setup active */
 
 /* Bulk IN - Endpoint 1,6,11 */
-#define UDCCS1		__REG(0x40600014)  /* UDC Endpoint 1 (IN) Control/Status Register */
-#define UDCCS6		__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
-#define UDCCS11		__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
-
-#define UDCCS_BI_TFS	(1 << 0)	/* Transmit FIFO service */
-#define UDCCS_BI_TPC	(1 << 1)	/* Transmit packet complete */
-#define UDCCS_BI_FTF	(1 << 2)	/* Flush Tx FIFO */
-#define UDCCS_BI_TUR	(1 << 3)	/* Transmit FIFO underrun */
-#define UDCCS_BI_SST	(1 << 4)	/* Sent stall */
-#define UDCCS_BI_FST	(1 << 5)	/* Force stall */
-#define UDCCS_BI_TSP	(1 << 7)	/* Transmit short packet */
+#define UDCCS1			__REG(0x40600104)  /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS6			__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
+#define UDCCS11			__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
+
+#define UDCCS_BI_TFS		(1 << 0)	/* Transmit FIFO service */
+#define UDCCS_BI_TPC		(1 << 1)	/* Transmit packet complete */
+#define UDCCS_BI_FTF		(1 << 8)	/* Flush Tx FIFO */
+#define UDCCS_BI_TUR		(1 << 3)	/* Transmit FIFO underrun */
+#define UDCCS_BI_SST		(1 << 4)	/* Sent stall */
+#define UDCCS_BI_FST		(1 << 5)	/* Force stall */
+#define UDCCS_BI_TSP		(1 << 7)	/* Transmit short packet */
 
 /* Bulk OUT - Endpoint 2,7,12 */
-#define UDCCS2		__REG(0x40600018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
-#define UDCCS7		__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
-#define UDCCS12		__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
-
-#define UDCCS_BO_RFS	(1 << 0)	/* Receive FIFO service */
-#define UDCCS_BO_RPC	(1 << 1)	/* Receive packet complete */
-#define UDCCS_BO_DME	(1 << 3)	/* DMA enable */
-#define UDCCS_BO_SST	(1 << 4)	/* Sent stall */
-#define UDCCS_BO_FST	(1 << 5)	/* Force stall */
-#define UDCCS_BO_RNE	(1 << 6)	/* Receive FIFO not empty */
-#define UDCCS_BO_RSP	(1 << 7)	/* Receive short packet */
+#define UDCCS2				__REG(0x40600108)  /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS7				__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
+#define UDCCS12				__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
+
+#define UDCCS_BO_RFS		(1 << 0)	/* Receive FIFO service */
+#define UDCCS_BO_RPC		(1 << 1)	/* Receive packet complete */
+#define UDCCS_BO_DME		(1 << 3)	/* DMA enable */
+#define UDCCS_BO_SST		(1 << 4)	/* Sent stall */
+#define UDCCS_BO_FST		(1 << 5)	/* Force stall */
+#define UDCCS_BO_RNE		(1 << 6)	/* Receive FIFO not empty */
+#define UDCCS_BO_RSP		(1 << 7)	/* Receive short packet */
 
 /* Isochronous IN - Endpoint 3,8,13 */
 #define UDCCS3		__REG(0x4060001C)  /* UDC Endpoint 3 (IN) Control/Status Register */
@@ -684,16 +696,16 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDCCS_INT_TSP	(1 << 7)	/* Transmit short packet */
 
 #define UFNRH		__REG(0x40600060)  /* UDC Frame Number Register High */
-#define UFNRL		__REG(0x40600064)  /* UDC Frame Number Register Low */
-#define UBCR2		__REG(0x40600068)  /* UDC Byte Count Reg 2 */
+#define UFNRL		__REG(0x40600014)  /* UDC Frame Number Register Low */
+#define UBCR2		__REG(0x40600208)  /* UDC Byte Count Reg 2 */
 #define UBCR4		__REG(0x4060006c)  /* UDC Byte Count Reg 4 */
 #define UBCR7		__REG(0x40600070)  /* UDC Byte Count Reg 7 */
 #define UBCR9		__REG(0x40600074)  /* UDC Byte Count Reg 9 */
 #define UBCR12		__REG(0x40600078)  /* UDC Byte Count Reg 12 */
 #define UBCR14		__REG(0x4060007c)  /* UDC Byte Count Reg 14 */
-#define UDDR0		__REG(0x40600080)  /* UDC Endpoint 0 Data Register */
-#define UDDR1		__REG(0x40600100)  /* UDC Endpoint 1 Data Register */
-#define UDDR2		__REG(0x40600180)  /* UDC Endpoint 2 Data Register */
+#define UDDR0		__REG(0x40600300)  /* UDC Endpoint 0 Data Register */
+#define UDDR1		__REG(0x40600304)  /* UDC Endpoint 1 Data Register */
+#define UDDR2		__REG(0x40600308)  /* UDC Endpoint 2 Data Register */
 #define UDDR3		__REG(0x40600200)  /* UDC Endpoint 3 Data Register */
 #define UDDR4		__REG(0x40600400)  /* UDC Endpoint 4 Data Register */
 #define UDDR5		__REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
@@ -708,7 +720,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDDR14		__REG(0x40600E00)  /* UDC Endpoint 14 Data Register */
 #define UDDR15		__REG(0x406000E0)  /* UDC Endpoint 15 Data Register */
 
-#define UICR0		__REG(0x40600050)  /* UDC Interrupt Control Register 0 */
+#define UICR0		__REG(0x40600004)  /* UDC Interrupt Control Register 0 */
 
 #define UICR0_IM0	(1 << 0)	/* Interrupt mask ep 0 */
 #define UICR0_IM1	(1 << 1)	/* Interrupt mask ep 1 */
@@ -719,7 +731,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR0_IM6	(1 << 6)	/* Interrupt mask ep 6 */
 #define UICR0_IM7	(1 << 7)	/* Interrupt mask ep 7 */
 
-#define UICR1		__REG(0x40600054)  /* UDC Interrupt Control Register 1 */
+#define UICR1		__REG(0x40600008)  /* UDC Interrupt Control Register 1 */
 
 #define UICR1_IM8	(1 << 0)	/* Interrupt mask ep 8 */
 #define UICR1_IM9	(1 << 1)	/* Interrupt mask ep 9 */
@@ -730,18 +742,18 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR1_IM14	(1 << 6)	/* Interrupt mask ep 14 */
 #define UICR1_IM15	(1 << 7)	/* Interrupt mask ep 15 */
 
-#define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+#define USIR0		__REG(0x4060000C)  /* UDC Status Interrupt Register 0 */
 
 #define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
-#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
-#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+#define USIR0_IR1	(1 << 2)	/* Interrup request ep 1 */
+#define USIR0_IR2	(1 << 4)	/* Interrup request ep 2 */
 #define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
 #define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
 #define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
 #define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
 #define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
 
-#define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+#define USIR1		__REG(0x40600010)  /* UDC Status Interrupt Register 1 */
 
 #define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
 #define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
@@ -751,23 +763,204 @@ typedef void		(*ExcpHndlr) (void) ;
 #define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
 #define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
 #define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
-#endif /* ! CONFIG_CPU_MONAHANS */
 
-#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
-/*
- * USB Client Controller (incomplete)
- */
-#define UDCCR		__REG(0x40600000)
-#define UDCICR0		__REG(0x40600004)
-#define UDCCIR0		__REG(0x40600008)
-#define UDCISR0		__REG(0x4060000c)
-#define UDCSIR1		__REG(0x40600010)
-#define UDCFNR		__REG(0x40600014)
-#define UDCOTGICR	__REG(0x40600018)
-#define UDCOTGISR	__REG(0x4060001c)
-#define UP2OCR		__REG(0x40600020)
-#define UP3OCR		__REG(0x40600024)
+#define UDCICR0         __REG(0x40600004)	/* UDC Interrupt Control Register0 */
+#define UDCICR1         __REG(0x40600008)	/* UDC Interrupt Control Register1 */
+#define UDCICR_FIFOERR	(1 << 1)			/* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL (1 << 0)			/* Packet Complete interrupt for EP */
+
+#define UDCICR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCICR1_IESOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCICR1_IERU	(1 << 29)	/* IntEn - Resume */
+#define UDCICR1_IESU	(1 << 28)	/* IntEn - Suspend */
+#define UDCICR1_IERS	(1 << 27)	/* IntEn - Reset */
+
+#define UDCISR0         __REG(0x4060000C) /* UDC Interrupt Status Register 0 */
+#define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status Register 1 */
+#define UDCISR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCISR1_IRSOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCISR1_IRRU	(1 << 29)	/* IntEn - Resume */
+#define UDCISR1_IRSU	(1 << 28)	/* IntEn - Suspend */
+#define UDCISR1_IRRS	(1 << 27)	/* IntEn - Reset */
+
+
+#define UDCFNR				 __REG(0x40600014) /* UDC Frame Number Register */
+#define UDCOTGICR			__REG(0x40600018) /* UDC On-The-Go interrupt control */
+#define UDCOTGICR_IESF		(1 << 24)	/* OTG SET_FEATURE command recvd */
+#define UDCOTGICR_IEXR		(1 << 17)	/* Extra Transciever Interrupt Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF		(1 << 16)	/* Extra Transciever Interrupt Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R	(1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40F	(1 << 8)	/* OTG Vbus Valid 4.0V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV44R	(1 << 7)	/* OTG Vbus Valid 4.4V Rising Edge  Interrupt Enable */
+#define UDCOTGICR_IEVV44F	(1 << 6)	/* OTG Vbus Valid 4.4V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESVR		(1 << 5)	/* OTG Session Valid Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESVF		(1 << 4)	/* OTG Session Valid Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESDR		(1 << 3)	/* OTG A-Device SRP Detect Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESDF		(1 << 2)	/* OTG A-Device SRP Detect Falling  Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR		(1 << 1)	/* OTG ID Change Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEIDF		(1 << 0)	/* OTG ID Change Falling Edge Interrupt Enable */
+
+#define UDCCSN(x)			__REG2(0x40600100, (x) << 2)
+#define UDCCSR0				__REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
+
+#define UDCCSR0_SA	(1 << 7)	/* Setup Active */
+#define UDCCSR0_RNE	(1 << 6)	/* Receive FIFO Not Empty */
+#define UDCCSR0_FST	(1 << 5)	/* Force Stall */
+#define UDCCSR0_SST	(1 << 4)	/* Sent Stall */
+#define UDCCSR0_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR0_FTF	(1 << 2)	/* Flush Transmit FIFO */
+#define UDCCSR0_IPR	(1 << 1)	/* IN Packet Ready */
+#define UDCCSR0_OPC	(1 << 0)	/* OUT Packet Complete */
+
+#define UDCCSRA         __REG(0x40600104) /* UDC Control/Status register - Endpoint A */
+#define UDCCSRB         __REG(0x40600108) /* UDC Control/Status register - Endpoint B */
+#define UDCCSRC         __REG(0x4060010C) /* UDC Control/Status register - Endpoint C */
+#define UDCCSRD         __REG(0x40600110) /* UDC Control/Status register - Endpoint D */
+#define UDCCSRE         __REG(0x40600114) /* UDC Control/Status register - Endpoint E */
+#define UDCCSRF         __REG(0x40600118) /* UDC Control/Status register - Endpoint F */
+#define UDCCSRG         __REG(0x4060011C) /* UDC Control/Status register - Endpoint G */
+#define UDCCSRH         __REG(0x40600120) /* UDC Control/Status register - Endpoint H */
+#define UDCCSRI         __REG(0x40600124) /* UDC Control/Status register - Endpoint I */
+#define UDCCSRJ         __REG(0x40600128) /* UDC Control/Status register - Endpoint J */
+#define UDCCSRK         __REG(0x4060012C) /* UDC Control/Status register - Endpoint K */
+#define UDCCSRL         __REG(0x40600130) /* UDC Control/Status register - Endpoint L */
+#define UDCCSRM         __REG(0x40600134) /* UDC Control/Status register - Endpoint M */
+#define UDCCSRN         __REG(0x40600138) /* UDC Control/Status register - Endpoint N */
+#define UDCCSRP         __REG(0x4060013C) /* UDC Control/Status register - Endpoint P */
+#define UDCCSRQ         __REG(0x40600140) /* UDC Control/Status register - Endpoint Q */
+#define UDCCSRR         __REG(0x40600144) /* UDC Control/Status register - Endpoint R */
+#define UDCCSRS         __REG(0x40600148) /* UDC Control/Status register - Endpoint S */
+#define UDCCSRT         __REG(0x4060014C) /* UDC Control/Status register - Endpoint T */
+#define UDCCSRU         __REG(0x40600150) /* UDC Control/Status register - Endpoint U */
+#define UDCCSRV         __REG(0x40600154) /* UDC Control/Status register - Endpoint V */
+#define UDCCSRW         __REG(0x40600158) /* UDC Control/Status register - Endpoint W */
+#define UDCCSRX         __REG(0x4060015C) /* UDC Control/Status register - Endpoint X */
+
+#define UDCCSR_DPE	(1 << 9)	/* Data Packet Error */
+#define UDCCSR_FEF	(1 << 8)	/* Flush Endpoint FIFO */
+#define UDCCSR_SP	(1 << 7)	/* Short Packet Control/Status */
+#define UDCCSR_BNE	(1 << 6)	/* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF	(1 << 6)	/* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST	(1 << 5)	/* Force STALL */
+#define UDCCSR_SST	(1 << 4)	/* Sent STALL */
+#define UDCCSR_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR_TRN	(1 << 2)	/* Tx/Rx NAK */
+#define UDCCSR_PC	(1 << 1)	/* Packet Complete */
+#define UDCCSR_FS	(1 << 0)	/* FIFO needs service */
+
+#define UDCBCN(x)		__REG2(0x40600200, (x)<<2)
+#define UDCBCR0         __REG(0x40600200) /* Byte Count Register - EP0 */
+#define UDCBCRA         __REG(0x40600204) /* Byte Count Register - EPA */
+#define UDCBCRB         __REG(0x40600208) /* Byte Count Register - EPB */
+#define UDCBCRC         __REG(0x4060020C) /* Byte Count Register - EPC */
+#define UDCBCRD         __REG(0x40600210) /* Byte Count Register - EPD */
+#define UDCBCRE         __REG(0x40600214) /* Byte Count Register - EPE */
+#define UDCBCRF         __REG(0x40600218) /* Byte Count Register - EPF */
+#define UDCBCRG         __REG(0x4060021C) /* Byte Count Register - EPG */
+#define UDCBCRH         __REG(0x40600220) /* Byte Count Register - EPH */
+#define UDCBCRI         __REG(0x40600224) /* Byte Count Register - EPI */
+#define UDCBCRJ         __REG(0x40600228) /* Byte Count Register - EPJ */
+#define UDCBCRK         __REG(0x4060022C) /* Byte Count Register - EPK */
+#define UDCBCRL         __REG(0x40600230) /* Byte Count Register - EPL */
+#define UDCBCRM         __REG(0x40600234) /* Byte Count Register - EPM */
+#define UDCBCRN         __REG(0x40600238) /* Byte Count Register - EPN */
+#define UDCBCRP         __REG(0x4060023C) /* Byte Count Register - EPP */
+#define UDCBCRQ         __REG(0x40600240) /* Byte Count Register - EPQ */
+#define UDCBCRR         __REG(0x40600244) /* Byte Count Register - EPR */
+#define UDCBCRS         __REG(0x40600248) /* Byte Count Register - EPS */
+#define UDCBCRT         __REG(0x4060024C) /* Byte Count Register - EPT */
+#define UDCBCRU         __REG(0x40600250) /* Byte Count Register - EPU */
+#define UDCBCRV         __REG(0x40600254) /* Byte Count Register - EPV */
+#define UDCBCRW         __REG(0x40600258) /* Byte Count Register - EPW */
+#define UDCBCRX         __REG(0x4060025C) /* Byte Count Register - EPX */
+
+#define UDCDN(x)		__REG2(0x40600300, (x)<<2)
+#define PHYS_UDCDN(x)	(0x40600300 + ((x)<<2))
+#define PUDCDN(x)		(volatile u32 *)(io_p2v(PHYS_UDCDN((x))))
+#define UDCDR0          __REG(0x40600300) /* Data Register - EP0 */
+#define UDCDRA          __REG(0x40600304) /* Data Register - EPA */
+#define UDCDRB          __REG(0x40600308) /* Data Register - EPB */
+#define UDCDRC          __REG(0x4060030C) /* Data Register - EPC */
+#define UDCDRD          __REG(0x40600310) /* Data Register - EPD */
+#define UDCDRE          __REG(0x40600314) /* Data Register - EPE */
+#define UDCDRF          __REG(0x40600318) /* Data Register - EPF */
+#define UDCDRG          __REG(0x4060031C) /* Data Register - EPG */
+#define UDCDRH          __REG(0x40600320) /* Data Register - EPH */
+#define UDCDRI          __REG(0x40600324) /* Data Register - EPI */
+#define UDCDRJ          __REG(0x40600328) /* Data Register - EPJ */
+#define UDCDRK          __REG(0x4060032C) /* Data Register - EPK */
+#define UDCDRL          __REG(0x40600330) /* Data Register - EPL */
+#define UDCDRM          __REG(0x40600334) /* Data Register - EPM */
+#define UDCDRN          __REG(0x40600338) /* Data Register - EPN */
+#define UDCDRP          __REG(0x4060033C) /* Data Register - EPP */
+#define UDCDRQ          __REG(0x40600340) /* Data Register - EPQ */
+#define UDCDRR          __REG(0x40600344) /* Data Register - EPR */
+#define UDCDRS          __REG(0x40600348) /* Data Register - EPS */
+#define UDCDRT          __REG(0x4060034C) /* Data Register - EPT */
+#define UDCDRU          __REG(0x40600350) /* Data Register - EPU */
+#define UDCDRV          __REG(0x40600354) /* Data Register - EPV */
+#define UDCDRW          __REG(0x40600358) /* Data Register - EPW */
+#define UDCDRX          __REG(0x4060035C) /* Data Register - EPX */
+
+#define UDCCN(x)		__REG2(0x40600400, (x)<<2)
+#define UDCCRA          __REG(0x40600404) /* Configuration register EPA */
+#define UDCCRB          __REG(0x40600408) /* Configuration register EPB */
+#define UDCCRC          __REG(0x4060040C) /* Configuration register EPC */
+#define UDCCRD          __REG(0x40600410) /* Configuration register EPD */
+#define UDCCRE          __REG(0x40600414) /* Configuration register EPE */
+#define UDCCRF          __REG(0x40600418) /* Configuration register EPF */
+#define UDCCRG          __REG(0x4060041C) /* Configuration register EPG */
+#define UDCCRH          __REG(0x40600420) /* Configuration register EPH */
+#define UDCCRI          __REG(0x40600424) /* Configuration register EPI */
+#define UDCCRJ          __REG(0x40600428) /* Configuration register EPJ */
+#define UDCCRK          __REG(0x4060042C) /* Configuration register EPK */
+#define UDCCRL          __REG(0x40600430) /* Configuration register EPL */
+#define UDCCRM          __REG(0x40600434) /* Configuration register EPM */
+#define UDCCRN          __REG(0x40600438) /* Configuration register EPN */
+#define UDCCRP          __REG(0x4060043C) /* Configuration register EPP */
+#define UDCCRQ          __REG(0x40600440) /* Configuration register EPQ */
+#define UDCCRR          __REG(0x40600444) /* Configuration register EPR */
+#define UDCCRS          __REG(0x40600448) /* Configuration register EPS */
+#define UDCCRT          __REG(0x4060044C) /* Configuration register EPT */
+#define UDCCRU          __REG(0x40600450) /* Configuration register EPU */
+#define UDCCRV          __REG(0x40600454) /* Configuration register EPV */
+#define UDCCRW          __REG(0x40600458) /* Configuration register EPW */
+#define UDCCRX          __REG(0x4060045C) /* Configuration register EPX */
+
+#define UDCCONR_CN		(0x03 << 25)	/* Configuration Number */
+#define UDCCONR_CN_S	(25)
+#define UDCCONR_IN		(0x07 << 22)	/* Interface Number */
+#define UDCCONR_IN_S	(22)
+#define UDCCONR_AISN	(0x07 << 19)	/* Alternate Interface Number */
+#define UDCCONR_AISN_S	(19)
+#define UDCCONR_EN		(0x0f << 15)	/* Endpoint Number */
+#define UDCCONR_EN_S	(15)
+#define UDCCONR_ET		(0x03 << 13)	/* Endpoint Type: */
+#define UDCCONR_ET_S	(13)
+#define UDCCONR_ET_INT	(0x03 << 13)	/*   Interrupt */
+#define UDCCONR_ET_BULK	(0x02 << 13)	/*   Bulk */
+#define UDCCONR_ET_ISO	(0x01 << 13)	/*   Isochronous */
+#define UDCCONR_ET_NU	(0x00 << 13)	/*   Not used */
+#define UDCCONR_ED		(1 << 12)		/* Endpoint Direction */
+#define UDCCONR_MPS		(0x3ff << 2)	/* Maximum Packet Size */
+#define UDCCONR_MPS_S	(2)
+#define UDCCONR_DE		(1 << 1)		/* Double Buffering Enable */
+#define UDCCONR_EE		(1 << 0)		/* Endpoint Enable */
+
+
+#define UDC_INT_FIFOERROR	(0x2)
+#define UDC_INT_PACKETCMP	(0x1)
+#define UDC_FNR_MASK		(0x7ff)
+#define UDCCSR_WR_MASK		(UDCCSR_DME|UDCCSR_FST)
+#define UDC_BCR_MASK		(0x3ff)
+
+
+#endif /* CONFIG_PXA27X */
+
+#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
 /*
  * USB Host Controller
diff --git a/include/usbdcore_pxa27x.h b/include/usbdcore_pxa27x.h
new file mode 100644
index 0000000..81bf3fb
--- /dev/null
+++ b/include/usbdcore_pxa27x.h
@@ -0,0 +1,68 @@
+/*
+ * PXA27x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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
+ */
+
+
+#ifndef __USBDCORE_PXA270X_H__
+#define __USBDCORE_PXA270X_H__
+
+#include <asm/byteorder.h>
+
+/* Endpoint 0 states */
+#define EP0_IDLE			0
+#define EP0_IN_DATA			1
+#define EP0_OUT_DATA		2
+#define EP0_XFER_COMPLETE   3
+
+
+/* Endpoint parameters */
+#define MAX_ENDPOINTS		4
+#define EP_MAX_PACKET_SIZE	64
+
+#define EP0_MAX_PACKET_SIZE     16
+#define UDC_OUT_ENDPOINT        0x02
+#define UDC_OUT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_IN_ENDPOINT         0x01
+#define UDC_IN_PACKET_SIZE      EP_MAX_PACKET_SIZE
+#define UDC_INT_ENDPOINT        0x05
+#define UDC_INT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_BULK_PACKET_SIZE    EP_MAX_PACKET_SIZE
+
+void udc_irq (void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak (int epid);
+
+/* Higher level functions for abstracting away from specific device */
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int  udc_init (void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint);
+
+#endif
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-02-23 16:05 [U-Boot] [PATCH v2] Support for PXA27X UDC Vivek Kutal
@ 2009-03-05 11:15 ` Remy Bohmer
  2009-03-06 11:55   ` Vivek Kutal
  2009-03-09 13:08   ` Vivek Kutal
  0 siblings, 2 replies; 11+ messages in thread
From: Remy Bohmer @ 2009-03-05 11:15 UTC (permalink / raw)
  To: u-boot

Hello Vivek,

2009/2/23 Vivek Kutal <vivek.kutal@azingo.com>:
> Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
> ---

Missing proper description of this patch.

> ?drivers/serial/usbtty.h ? ? ? ? ? ? | ? ?4 +-
> ?drivers/usb/Makefile ? ? ? ? ? ? ? ?| ? ?1 +
> ?drivers/usb/usbdcore_pxa27x.c ? ? ? | ?712 +++++++++++++++++++++++++++++++++++
> ?include/asm-arm/arch-pxa/pxa-regs.h | ?337 +++++++++++++----
> ?include/usbdcore_pxa27x.h ? ? ? ? ? | ? 68 ++++
> ?5 files changed, 1049 insertions(+), 73 deletions(-)
> ?create mode 100644 drivers/usb/usbdcore_pxa27x.c
> ?create mode 100644 include/usbdcore_pxa27x.h
>
> diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
> index ecefde5..5fe872e 100644
> --- a/drivers/serial/usbtty.h
> +++ b/drivers/serial/usbtty.h

I get 46 errors and 101 warnings while running linux/checkpatch.pl on
this patch.
Please clean up and resubmit.

Kind Regards,

Remy

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-05 11:15 ` Remy Bohmer
@ 2009-03-06 11:55   ` Vivek Kutal
  2009-03-06 14:26     ` Remy Bohmer
  2009-03-09 13:08   ` Vivek Kutal
  1 sibling, 1 reply; 11+ messages in thread
From: Vivek Kutal @ 2009-03-06 11:55 UTC (permalink / raw)
  To: u-boot

Hi Remy,
                There are around ~70 warnings generated for pxa-regs.h
for having more than 80 chars in a line, I have taken all the macro
definitions from the linux kernel source code should I fix those
warnings too ? Also pxa-regs.h already has many line with more than 80
chars.

--
Thanks
Vivek Kutal

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-06 11:55   ` Vivek Kutal
@ 2009-03-06 14:26     ` Remy Bohmer
  0 siblings, 0 replies; 11+ messages in thread
From: Remy Bohmer @ 2009-03-06 14:26 UTC (permalink / raw)
  To: u-boot

Hello Vivek,

2009/3/6 Vivek Kutal <vivek.kutal@azingo.com>:
> Hi Remy,
> ? ? ? ? ? ? ? ?There are around ~70 warnings generated for pxa-regs.h
> for having more than 80 chars in a line, I have taken all the macro
> definitions from the linux kernel source code should I fix those
> warnings too ? Also pxa-regs.h already has many line with more than 80
> chars.

Thanks for asking.
If you look here: http://www.denx.de/wiki/U-Boot/CodingStyle, you will
see that source files originating from different projects (for example
the MTD subsystem or the hush shell code from the BusyBox project)
may, after careful consideration, be exempted from these rules. For
such files, the original coding style may be kept to ease subsequent
migration to newer versions of those sources.
Maybe you should also read this: http://www.denx.de/wiki/U-Boot/Patches

Kind regards,

Remy

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-05 11:15 ` Remy Bohmer
  2009-03-06 11:55   ` Vivek Kutal
@ 2009-03-09 13:08   ` Vivek Kutal
  2009-03-09 23:46     ` Kim Phillips
  1 sibling, 1 reply; 11+ messages in thread
From: Vivek Kutal @ 2009-03-09 13:08 UTC (permalink / raw)
  To: u-boot

	This Patch adds Support for PXA27X UDC.

Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
---
 Resending after code cleanup.

 drivers/serial/usbtty.h             |    4 +-
 drivers/usb/Makefile                |    1 +
 drivers/usb/usbdcore_pxa27x.c       |  719 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-pxa/pxa-regs.h |  296 ++++++++++++---
 include/usbdcore_pxa27x.h           |   69 ++++
 5 files changed, 1035 insertions(+), 54 deletions(-)
 create mode 100644 drivers/usb/usbdcore_pxa27x.c
 create mode 100644 include/usbdcore_pxa27x.h

diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index ecefde5..5fe872e 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -27,8 +27,10 @@
 #include <usbdcore.h>
 #if defined(CONFIG_PPC)
 #include <usbdcore_mpc8xx.h>
-#elif defined(CONFIG_ARM)
+#elif defined(CONFIG_OMAP1510)
 #include <usbdcore_omap1510.h>
+#elif defined(CONFIG_PXA27X)
+#include <usbdcore_pxa27x.h>
 #endif
 
 #include <version_autogenerated.h>
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index b306a65..0a1886a 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -47,6 +47,7 @@ COBJS-y += usbdcore_ep0.o
 COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
 COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
 COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
+COBJS-$(CONFIG_PXA27X) += usbdcore_pxa27x.o
 endif
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/usb/usbdcore_pxa27x.c b/drivers/usb/usbdcore_pxa27x.c
new file mode 100644
index 0000000..9674452
--- /dev/null
+++ b/drivers/usb/usbdcore_pxa27x.c
@@ -0,0 +1,719 @@
+/*
+ * PXA27x USB device driver for u-boot.
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A.  <info@eurotech.it>
+ * Copyright (C) 2008 Vivek Kutal      <vivek.kutal@azingo.com>
+ *
+ * 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
+ *
+ */
+
+
+#include <common.h>
+#include <config.h>
+#include <asm/byteorder.h>
+#include <usbdcore.h>
+#include <usbdcore_ep0.h>
+#include <asm/arch/hardware.h>
+#include <usbdcore_pxa27x.h>
+
+/* number of endpoints on this UDC */
+#define UDC_MAX_ENDPOINTS	24
+
+static struct urb *ep0_urb;
+static struct usb_device_instance *udc_device;
+static int ep0state = EP0_IDLE;
+
+#ifdef USBDDBG
+static void udc_dump_buffer(char *name, u8 *buf, int len)
+{
+	int i, p, flag = 1;
+
+	usbdbg("%s - buf %p, len %d", name, buf, len);
+	for (i = p = 0; i < len; i++, p++) {
+		if (p == 0) {
+			flag = 0;
+			usbdbg("\t");
+		}
+
+		usbdbg("%02x ", buf[i]);
+
+		if (p == 15) {
+			flag = 1;
+			usbdbg("\n");
+			p = -1;
+		}
+	}
+	if (!flag)
+		usbdbg("\n");
+}
+#else
+#define udc_dump_buffer(name, buf, len)		/* void */
+#endif
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+	USIR1	= mask | USIR1;
+}
+
+/*
+ * If the endpoint has an active tx_urb, then the next packet of data from the
+ * URB is written to the tx FIFO.
+ * The total amount of data in the urb is given by urb->actual_length.
+ * The maximum amount of data that can be sent in any one packet is given by
+ * endpoint->tx_packetSize.
+ * The number of data bytes from this URB that have already been transmitted
+ * is given by endpoint->sent.
+ * endpoint->last is updated by this routine with the number of data bytes
+ * transmitted in this packet.
+ */
+static int udc_write_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->tx_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+
+	u32 *addr32 = (u32 *) &UDCDN(ep_num),
+		*data32 = (u32 *) urb->buffer;
+	u8  *addr8 = (u8 *) &UDCDN(ep_num),
+		*data8 = (u8 *) urb->buffer;
+	unsigned int i, n, w, b, is_short;
+	int timeout = 2000;	/* 2ms */
+
+	if (!urb || !urb->actual_length)
+		return -1;
+
+	n = MIN(urb->actual_length - endpoint->sent, endpoint->tx_packetSize);
+	if (n <= 0)
+		return -1;
+
+	usbdbg("write urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: sent %d, tx_packetSize %d, last %d",
+		endpoint->sent, endpoint->tx_packetSize, endpoint->last);
+#endif
+
+	is_short = n != endpoint->tx_packetSize;
+	w = n / 4;
+	b = n % 4;
+	usbdbg("n %d%s w %d b %d", n, is_short ? "-s" : "", w, b);
+	udc_dump_buffer("urb write", data8 + endpoint->sent, n);
+
+	/* Prepare for data send */
+	if (ep_num)
+		UDCCSN(ep_num) = UDCCSR_PC;
+
+	for (i = 0; i < w; i++)
+		*addr32 = data32[endpoint->sent/4 + i];
+	for (i = 0; i < b; i++)
+		*addr8 = data8[endpoint->sent + w*4 + i];
+
+	/* Set "Packet Complete" if less data then tx_packetSize */
+	if (is_short)
+		UDCCSN(ep_num) = ep_num ? UDCCSR_SP : UDCCSR0_IPR;
+
+	/* Wait for data sent */
+	while (!(UDCCSN(ep_num) & (ep_num ? UDCCSR_PC : UDCCSR0_IPR))) {
+		if (ep_num) {
+			if (timeout-- == 0)
+				return -1;
+			else
+				udelay(1);
+		};
+	}
+	endpoint->last = n;
+
+	if (ep_num) {
+		usbd_tx_complete(endpoint);
+	} else {
+		endpoint->sent += n;
+		endpoint->last -= n;
+	}
+
+	if ((endpoint->tx_urb->actual_length - endpoint->sent) <= 0) {
+		urb->actual_length = 0;
+		endpoint->sent = 0;
+		endpoint->last = 0;
+	}
+
+	if ((endpoint->sent >= urb->actual_length) && (!ep_num)) {
+		usbdbg("ep0 IN stage done");
+		if (is_short)
+			ep0state = EP0_IDLE;
+		else
+			ep0state = EP0_XFER_COMPLETE;
+	}
+
+	return 0;
+}
+
+static int udc_read_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->rcv_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	u32 *addr32 = (u32 *) &UDCDN(ep_num),
+		*data32 = (u32 *) urb->buffer;
+	unsigned int i, n, is_short ;
+
+	usbdbg("read urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: rcv_packetSize %d",
+		endpoint->rcv_packetSize);
+#endif
+
+	if (UDCCSN(ep_num) & UDCCSR_BNE)
+		n = UDCBCN(ep_num) & 0x3ff;
+	else /* zlp */
+		n = 0;
+	is_short = n != endpoint->rcv_packetSize;
+
+	usbdbg("n %d%s", n, is_short ? "-s" : "");
+	for (i = 0; i < n; i += 4)
+		data32[urb->actual_length/4 + i/4] = *addr32;
+
+	udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n);
+
+	usbd_rcv_complete(endpoint, n, 0);
+
+	return 0;
+}
+
+static int udc_read_urb_ep0(void)
+{
+	u32 *addr32 = (u32 *) &UDCDN(0);
+	u32 *data32 = (u32 *) ep0_urb->buffer;
+	u8 *addr8 = (u8 *) &UDCDN(0);
+	u8 *data8 = (u8 *) ep0_urb->buffer;
+	unsigned int i, n, w, b;
+
+	n = UDCBCR0;
+	w = n / 4;
+	b = n % 4;
+
+	for (i = 0; i < w; i++) {
+		data32[ep0_urb->actual_length/4 + i] = *addr32;
+		ep0_urb->actual_length += 4;
+	}
+
+	for (i = 0; i < b; i++) {
+		data8[ep0_urb->actual_length + w*4 + i] = *addr8;
+		ep0_urb->actual_length++;
+	}
+
+	UDCCSR0 = UDCCSR0_OPC | UDCCSR0_IPR;
+	if (ep0_urb->actual_length == ep0_urb->device_request.wLength)
+		return 1;
+	return 0;
+}
+
+static void udc_handle_ep0(struct usb_endpoint_instance *endpoint)
+{
+	u32 udccsr0 = UDCCSR0;
+	u32 *data = (u32 *) &ep0_urb->device_request;
+	int i;
+
+	usbdbg("udccsr0 %x", udccsr0);
+
+	/* Clear stall status */
+	if (udccsr0 & UDCCSR0_SST) {
+		usberr("clear stall status");
+		UDCCSR0 = UDCCSR0_SST;
+		ep0state = EP0_IDLE;
+	}
+
+	/* previous request unfinished?  non-error iff back-to-back ... */
+	if ((udccsr0 & UDCCSR0_SA) != 0 && ep0state != EP0_IDLE)
+		ep0state = EP0_IDLE;
+
+	switch (ep0state) {
+
+	case EP0_IDLE:
+
+		udccsr0 = UDCCSR0;
+		/* Start control request? */
+		if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE))
+			== (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) {
+
+			/* Read SETUP packet.
+			 * SETUP packet size is 8 bytes (aka 2 words)
+			 */
+			usbdbg("try reading SETUP packet");
+			for (i = 0; i < 2; i++) {
+				if ((UDCCSR0 & UDCCSR0_RNE) == 0) {
+					usberr("setup packet too short:%d", i);
+					goto stall;
+				}
+				data[i] = UDCDR0;
+			}
+
+			UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);
+			if ((UDCCSR0 & UDCCSR0_RNE) != 0) {
+				usberr("setup packet too long");
+				goto stall;
+			}
+
+			udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+
+			if (ep0_urb->device_request.wLength == 0) {
+				usbdbg("Zero Data control Packet\n");
+				if (ep0_recv_setup(ep0_urb)) {
+					usberr("Invalid Setup Packet\n");
+					udc_dump_buffer("ep0 setup read",
+								(u8 *)data, 8);
+					goto stall;
+				}
+				UDCCSR0 = UDCCSR0_IPR;
+				ep0state = EP0_IDLE;
+			} else {
+				/* Check direction */
+				if (ep0_urb->device_request.bmRequestType &
+				USB_REQ_DIRECTION_MASK == USB_REQ_HOST2DEVICE) {
+					ep0state = EP0_OUT_DATA;
+					ep0_urb->buffer =
+						(u8 *)ep0_urb->buffer_data;
+					ep0_urb->buffer_length =
+						sizeof(ep0_urb->buffer_data);
+					ep0_urb->actual_length = 0;
+					UDCCSR0 = UDCCSR0_IPR;
+				} else {
+					/* The ep0_recv_setup function has
+					 * already placed our response packet
+					 * data in ep0_urb->buffer and the
+					 * packet length in
+					 * ep0_urb->actual_length.
+					 */
+					if (ep0_recv_setup(ep0_urb)) {
+stall:
+						usberr("Invalid setup packet");
+						udc_dump_buffer("ep0 setup read"
+							, (u8 *) data, 8);
+						ep0state = EP0_IDLE;
+
+						UDCCSR0 = UDCCSR0_SA |
+						UDCCSR0_OPC | UDCCSR0_FST |
+						UDCCS0_FTF;
+
+						return;
+					}
+
+					endpoint->tx_urb = ep0_urb;
+					endpoint->sent = 0;
+					usbdbg("EP0_IN_DATA");
+					ep0state = EP0_IN_DATA;
+					if (udc_write_urb(endpoint) < 0)
+						goto stall;
+
+				}
+			}
+			return;
+		} else if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA))
+			== (UDCCSR0_OPC|UDCCSR0_SA)) {
+			usberr("Setup Active but no data. Stalling ....\n");
+			goto stall;
+		} else {
+			usbdbg("random early IRQs");
+			/* Some random early IRQs:
+			 * - we acked FST
+			 * - IPR cleared
+			 * - OPC got set, without SA (likely status stage)
+			 */
+			UDCCSR0 = udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC);
+		}
+		break;
+
+	case EP0_OUT_DATA:
+
+		if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {
+			if (udc_read_urb_ep0()) {
+read_complete:
+				ep0state = EP0_IDLE;
+				if (ep0_recv_setup(ep0_urb)) {
+					/* Not a setup packet, stall next
+					 * EP0 transaction
+					 */
+					udc_dump_buffer("ep0 setup read",
+							(u8 *) data, 8);
+					usberr("can't parse setup packet\n");
+					goto stall;
+				}
+			}
+		} else if (!(udccsr0 & UDCCSR0_OPC) &&
+				!(udccsr0 & UDCCSR0_IPR)) {
+			if (ep0_urb->device_request.wLength ==
+				ep0_urb->actual_length)
+				goto read_complete;
+
+			usberr("Premature Status\n");
+			ep0state = EP0_IDLE;
+		}
+		break;
+
+	case EP0_IN_DATA:
+		/* GET_DESCRIPTOR etc */
+		if (udccsr0 & UDCCSR0_OPC) {
+			UDCCSR0 = UDCCSR0_OPC | UDCCSR0_FTF;
+			usberr("ep0in premature status");
+			ep0state = EP0_IDLE;
+		} else {
+			/* irq was IPR clearing */
+			if (udc_write_urb(endpoint) < 0) {
+				usberr("ep0_write_error\n");
+				goto stall;
+			}
+		}
+		break;
+
+	case EP0_XFER_COMPLETE:
+		UDCCSR0 = UDCCSR0_IPR;
+		ep0state = EP0_IDLE;
+		break;
+
+	default:
+		usbdbg("Default\n");
+	}
+	USIR0 = USIR0_IR0;
+}
+
+static void udc_handle_ep(struct usb_endpoint_instance *endpoint)
+{
+	int ep_addr = endpoint->endpoint_address;
+	int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	int ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+
+	u32 flags = UDCCSN(ep_num) & (UDCCSR_SST | UDCCSR_TRN);
+	if (flags)
+		UDCCSN(ep_num) = flags;
+
+	if (ep_isout)
+		udc_read_urb(endpoint);
+	else
+		udc_write_urb(endpoint);
+
+	UDCCSN(ep_num) = UDCCSR_PC;
+}
+
+static void udc_state_changed(void)
+{
+	int config, interface, alternate;
+
+	UDCCR |= UDCCR_SMAC;
+
+	config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;
+	interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;
+	alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;
+
+	usbdbg("New UDC settings are: conf %d - inter %d - alter %d",
+		config, interface, alternate);
+
+	usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+	UDCISR1 = UDCISR1_IRCC;
+}
+
+void udc_irq(void)
+{
+	int handled;
+	struct usb_endpoint_instance *endpoint;
+	int ep_num, i;
+	u32 udcisr0;
+
+	do {
+		handled = 0;
+		/* Suspend Interrupt Request */
+		if (USIR1 & UDCCR_SUSIR) {
+			usbdbg("Suspend\n");
+			udc_ack_int_UDCCR(UDCCR_SUSIR);
+			handled = 1;
+			ep0state = EP0_IDLE;
+		}
+
+		/* Resume Interrupt Request */
+		if (USIR1 & UDCCR_RESIR) {
+			udc_ack_int_UDCCR(UDCCR_RESIR);
+			handled = 1;
+			usbdbg("USB resume\n");
+		}
+
+		if (USIR1 & (1<<31)) {
+			handled = 1;
+			udc_state_changed();
+		}
+
+		/* Reset Interrupt Request */
+		if (USIR1 & UDCCR_RSTIR) {
+			udc_ack_int_UDCCR(UDCCR_RSTIR);
+			handled = 1;
+			usbdbg("Reset\n");
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+		} else {
+			if (USIR0)
+				usbdbg("UISR0: %x \n", USIR0);
+
+			if (USIR0 & 0x2)
+				USIR0 = 0x2;
+
+			/* Control traffic */
+			if (USIR0  & USIR0_IR0) {
+				handled = 1;
+				udc_handle_ep0(udc_device->bus->endpoint_array);
+				USIR0 = USIR0_IR0;
+			}
+
+			endpoint = udc_device->bus->endpoint_array;
+			for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+				ep_num = (endpoint[i].endpoint_address) &
+						USB_ENDPOINT_NUMBER_MASK;
+				if (!ep_num)
+					continue;
+				udcisr0 = UDCISR0;
+				if (udcisr0 &
+					UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) {
+					UDCISR0 = UDCISR_INT(ep_num,
+							 UDC_INT_PACKETCMP);
+					udc_handle_ep(&endpoint[i]);
+				}
+			}
+		}
+
+	} while (handled);
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_OEN		(1 << 31)   /* On-the-Go Enable */
+#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 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);
+	}
+}
+
+/*
+ * udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ */
+void udc_set_nak(int ep_num)
+{
+	/* TODO */
+}
+
+/*
+ * udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ */
+void udc_unset_nak(int ep_num)
+{
+	/* TODO */
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+	return udc_write_urb(endpoint);
+}
+
+/* Associate a physical endpoint with endpoint instance */
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
+				struct usb_endpoint_instance *endpoint)
+{
+	int ep_num, ep_addr, ep_isout, ep_type, ep_size;
+	int config, interface, alternate;
+	u32 tmp;
+
+	usbdbg("setting up endpoint id %d", id);
+
+	if (!endpoint) {
+		usberr("endpoint void!");
+		return;
+	}
+
+	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	if (ep_num >= UDC_MAX_ENDPOINTS) {
+		usberr("unable to setup ep %d!", ep_num);
+		return;
+	}
+
+	pio_irq_enable(ep_num);
+	if (ep_num == 0) {
+		/* Done for ep0 */
+		return;
+	}
+
+	config = 1;
+	interface = 0;
+	alternate = 0;
+
+	usbdbg("config %d - interface %d - alternate %d",
+		config, interface, alternate);
+
+	ep_addr = endpoint->endpoint_address;
+	ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+	ep_type = ep_isout ? endpoint->rcv_attributes : endpoint->tx_attributes;
+	ep_size = ep_isout ? endpoint->rcv_packetSize : endpoint->tx_packetSize;
+
+	usbdbg("addr %x, num %d, dir %s, type %s, packet size %d",
+		ep_addr, ep_num,
+		ep_isout ? "out" : "in",
+		ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" :
+		ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" :
+		ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???",
+		ep_size
+		);
+
+	/* Configure UDCCRx */
+	tmp = 0;
+	tmp |= (config << UDCCONR_CN_S) & UDCCONR_CN;
+	tmp |= (interface << UDCCONR_IN_S) & UDCCONR_IN;
+	tmp |= (alternate << UDCCONR_AISN_S) & UDCCONR_AISN;
+	tmp |= (ep_num << UDCCONR_EN_S) & UDCCONR_EN;
+	tmp |= (ep_type << UDCCONR_ET_S) & UDCCONR_ET;
+	tmp |= ep_isout ? 0 : UDCCONR_ED;
+	tmp |= (ep_size << UDCCONR_MPS_S) & UDCCONR_MPS;
+	tmp |= UDCCONR_EE;
+
+	UDCCN(ep_num) = tmp;
+
+	usbdbg("UDCCR%c = %x", 'A' + ep_num-1, UDCCN(ep_num));
+	usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, UDCCSN(ep_num));
+}
+
+#define CONFIG_USB_DEV_PULLUP_GPIO 87
+
+/* Connect the USB device to the bus */
+void udc_connect(void)
+{
+	usbdbg("UDC connect");
+
+	/* Turn on the USB connection by enabling the pullup resistor */
+	set_GPIO_mode(CONFIG_USB_DEV_PULLUP_GPIO | GPIO_OUT);
+	GPSR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Disconnect the USB device to the bus */
+void udc_disconnect(void)
+{
+	usbdbg("UDC disconnect");
+
+	/* Turn off the USB connection by disabling the pullup resistor */
+	GPCR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Switch on the UDC */
+void udc_enable(struct usb_device_instance *device)
+{
+
+	ep0state = EP0_IDLE;
+	CKEN |= CKEN11_USB;
+
+	/* enable endpoint 0, A, B's Packet Complete Interrupt. */
+	UDCICR0 = 0x0000003f;
+	UDCICR1 = 0xa8000000;
+
+	/* clear the interrupt status/control registers */
+	UDCISR0 = 0xffffffff;
+	UDCISR1 = 0xffffffff;
+
+	/* set UDC-enable */
+	udc_set_mask_UDCCR(UDCCR_UDE);
+
+	udc_device = device;
+	if (!ep0_urb)
+		ep0_urb = usbd_alloc_urb(udc_device,
+				udc_device->bus->endpoint_array);
+	else
+		usbinfo("ep0_urb %p already allocated", ep0_urb);
+
+	usbdbg("UDC Enabled\n");
+}
+
+/* Need to check this again */
+void udc_disable(void)
+{
+	usbdbg("disable UDC");
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Free ep0 URB */
+	if (ep0_urb) {
+		usbd_dealloc_urb(ep0_urb);
+		ep0_urb = NULL;
+	}
+
+	/* Reset device pointer */
+	udc_device = NULL;
+}
+
+/* Allow udc code to do any additional startup */
+void udc_startup_events(struct usb_device_instance *device)
+{
+	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT */
+	usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+	/* The DEVICE_CREATE event puts the USB device in the state
+	 * STATE_ATTACHED */
+	usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+	/* Some USB controller driver implementations signal
+	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+	 * DEVICE_HUB_CONFIGURED causes a transition to the state
+	 * STATE_POWERED, and DEVICE_RESET causes a transition to
+	 * the state STATE_DEFAULT.
+	 */
+	udc_enable(device);
+}
+
+/* Initialize h/w stuff */
+int udc_init(void)
+{
+	udc_device = NULL;
+	usbdbg("PXA27x usbd start");
+
+	/* Disable the UDC */
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Disable IRQs: we don't use them */
+	UDCICR0 = UDCICR1 = 0;
+
+	return 0;
+}
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e014568..a8d30e2 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -596,46 +596,58 @@ typedef void		(*ExcpHndlr) (void) ;
 /*
  * USB Device Controller
  */
-#ifndef CONFIG_CPU_MONAHANS
-#define UDC_RES1	__REG(0x40600004)  /* UDC Undocumented - Reserved1 */
-#define UDC_RES2	__REG(0x40600008)  /* UDC Undocumented - Reserved2 */
-#define UDC_RES3	__REG(0x4060000C)  /* UDC Undocumented - Reserved3 */
-
-#define UDCCR		__REG(0x40600000)  /* UDC Control Register */
-#define UDCCR_UDE	(1 << 0)	/* UDC enable */
-#define UDCCR_UDA	(1 << 1)	/* UDC active */
-#define UDCCR_RSM	(1 << 2)	/* Device resume */
-#define UDCCR_RESIR	(1 << 3)	/* Resume interrupt request */
-#define UDCCR_SUSIR	(1 << 4)	/* Suspend interrupt request */
-#define UDCCR_SRM	(1 << 5)	/* Suspend/resume interrupt mask */
-#define UDCCR_RSTIR	(1 << 6)	/* Reset interrupt request */
-#define UDCCR_REM	(1 << 7)	/* Reset interrupt mask */
-
-#define UDCCS0		__REG(0x40600010)  /* UDC Endpoint 0 Control/Status Register */
-#define UDCCS0_OPR	(1 << 0)	/* OUT packet ready */
-#define UDCCS0_IPR	(1 << 1)	/* IN packet ready */
-#define UDCCS0_FTF	(1 << 2)	/* Flush Tx FIFO */
-#define UDCCS0_DRWF	(1 << 3)	/* Device remote wakeup feature */
-#define UDCCS0_SST	(1 << 4)	/* Sent stall */
-#define UDCCS0_FST	(1 << 5)	/* Force stall */
-#define UDCCS0_RNE	(1 << 6)	/* Receive FIFO no empty */
-#define UDCCS0_SA	(1 << 7)	/* Setup active */
+#ifdef CONFIG_PXA27X
+
+#define UDCCR		__REG(0x40600000)	/* UDC Control Register */
+#define UDCCR_UDE	(1 << 0)		/* UDC enable */
+#define UDCCR_UDA	(1 << 1)		/* UDC active */
+#define UDCCR_RSM	(1 << 2)		/* Device resume */
+#define UDCCR_EMCE	(1 << 3)		/* Endpoint Memory Configuration Error */
+#define UDCCR_SMAC	(1 << 4)		/* Switch Endpoint Memory to Active Configuration */
+#define UDCCR_RESIR	(1 << 29)		/* Resume interrupt request */
+#define UDCCR_SUSIR	(1 << 28)		/* Suspend interrupt request */
+#define UDCCR_SM	(1 << 28)		/* Suspend interrupt mask */
+#define UDCCR_RSTIR	(1 << 27)		/* Reset interrupt request */
+#define UDCCR_REM	(1 << 27)		/* Reset interrupt mask */
+#define UDCCR_RM	(1 << 29)		/* resume interrupt mask */
+#define UDCCR_SRM	(UDCCR_SM|UDCCR_RM)
+#define UDCCR_OEN	(1 << 31)		/* On-the-Go Enable */
+#define UDCCR_AALTHNP	(1 << 30)		/* A-device Alternate Host Negotiation Protocol Port Support */
+#define UDCCR_AHNP	(1 << 29)		/* A-device Host Negotiation Protocol Support */
+#define UDCCR_BHNP	(1 << 28)		/* B-device Host Negotiation Protocol Enable */
+#define UDCCR_DWRE	(1 << 16)		/* Device Remote Wake-up Enable */
+#define UDCCR_ACN	(0x03 << 11)		/* Active UDC configuration Number */
+#define UDCCR_ACN_S	11
+#define UDCCR_AIN	(0x07 << 8)		/* Active UDC interface Number */
+#define UDCCR_AIN_S	8
+#define UDCCR_AAISN	(0x07 << 5)		/* Active UDC Alternate Interface  Setting Number */
+#define UDCCR_AAISN_S	5
+
+#define UDCCS0		__REG(0x40600100)	/* UDC Endpoint 0 Control/Status Register */
+#define UDCCS0_OPR	(1 << 0)		/* OUT packet ready */
+#define UDCCS0_IPR	(1 << 1)		/* IN packet ready */
+#define UDCCS0_FTF	(1 << 2)		/* Flush Tx FIFO */
+#define UDCCS0_DRWF	(1 << 16)		/* Device remote wakeup feature */
+#define UDCCS0_SST	(1 << 4)		/* Sent stall */
+#define UDCCS0_FST	(1 << 5)		/* Force stall */
+#define UDCCS0_RNE	(1 << 6)		/* Receive FIFO no empty */
+#define UDCCS0_SA	(1 << 7)		/* Setup active */
 
 /* Bulk IN - Endpoint 1,6,11 */
-#define UDCCS1		__REG(0x40600014)  /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS1		__REG(0x40600104)  /* UDC Endpoint 1 (IN) Control/Status Register */
 #define UDCCS6		__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
 #define UDCCS11		__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
 
 #define UDCCS_BI_TFS	(1 << 0)	/* Transmit FIFO service */
 #define UDCCS_BI_TPC	(1 << 1)	/* Transmit packet complete */
-#define UDCCS_BI_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS_BI_FTF	(1 << 8)	/* Flush Tx FIFO */
 #define UDCCS_BI_TUR	(1 << 3)	/* Transmit FIFO underrun */
 #define UDCCS_BI_SST	(1 << 4)	/* Sent stall */
 #define UDCCS_BI_FST	(1 << 5)	/* Force stall */
 #define UDCCS_BI_TSP	(1 << 7)	/* Transmit short packet */
 
 /* Bulk OUT - Endpoint 2,7,12 */
-#define UDCCS2		__REG(0x40600018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS2		__REG(0x40600108)  /* UDC Endpoint 2 (OUT) Control/Status Register */
 #define UDCCS7		__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
 #define UDCCS12		__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
 
@@ -684,16 +696,16 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDCCS_INT_TSP	(1 << 7)	/* Transmit short packet */
 
 #define UFNRH		__REG(0x40600060)  /* UDC Frame Number Register High */
-#define UFNRL		__REG(0x40600064)  /* UDC Frame Number Register Low */
-#define UBCR2		__REG(0x40600068)  /* UDC Byte Count Reg 2 */
+#define UFNRL		__REG(0x40600014)  /* UDC Frame Number Register Low */
+#define UBCR2		__REG(0x40600208)  /* UDC Byte Count Reg 2 */
 #define UBCR4		__REG(0x4060006c)  /* UDC Byte Count Reg 4 */
 #define UBCR7		__REG(0x40600070)  /* UDC Byte Count Reg 7 */
 #define UBCR9		__REG(0x40600074)  /* UDC Byte Count Reg 9 */
 #define UBCR12		__REG(0x40600078)  /* UDC Byte Count Reg 12 */
 #define UBCR14		__REG(0x4060007c)  /* UDC Byte Count Reg 14 */
-#define UDDR0		__REG(0x40600080)  /* UDC Endpoint 0 Data Register */
-#define UDDR1		__REG(0x40600100)  /* UDC Endpoint 1 Data Register */
-#define UDDR2		__REG(0x40600180)  /* UDC Endpoint 2 Data Register */
+#define UDDR0		__REG(0x40600300)  /* UDC Endpoint 0 Data Register */
+#define UDDR1		__REG(0x40600304)  /* UDC Endpoint 1 Data Register */
+#define UDDR2		__REG(0x40600308)  /* UDC Endpoint 2 Data Register */
 #define UDDR3		__REG(0x40600200)  /* UDC Endpoint 3 Data Register */
 #define UDDR4		__REG(0x40600400)  /* UDC Endpoint 4 Data Register */
 #define UDDR5		__REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
@@ -708,7 +720,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDDR14		__REG(0x40600E00)  /* UDC Endpoint 14 Data Register */
 #define UDDR15		__REG(0x406000E0)  /* UDC Endpoint 15 Data Register */
 
-#define UICR0		__REG(0x40600050)  /* UDC Interrupt Control Register 0 */
+#define UICR0		__REG(0x40600004)  /* UDC Interrupt Control Register 0 */
 
 #define UICR0_IM0	(1 << 0)	/* Interrupt mask ep 0 */
 #define UICR0_IM1	(1 << 1)	/* Interrupt mask ep 1 */
@@ -719,7 +731,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR0_IM6	(1 << 6)	/* Interrupt mask ep 6 */
 #define UICR0_IM7	(1 << 7)	/* Interrupt mask ep 7 */
 
-#define UICR1		__REG(0x40600054)  /* UDC Interrupt Control Register 1 */
+#define UICR1		__REG(0x40600008)  /* UDC Interrupt Control Register 1 */
 
 #define UICR1_IM8	(1 << 0)	/* Interrupt mask ep 8 */
 #define UICR1_IM9	(1 << 1)	/* Interrupt mask ep 9 */
@@ -730,18 +742,18 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR1_IM14	(1 << 6)	/* Interrupt mask ep 14 */
 #define UICR1_IM15	(1 << 7)	/* Interrupt mask ep 15 */
 
-#define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+#define USIR0		__REG(0x4060000C)  /* UDC Status Interrupt Register 0 */
 
 #define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
-#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
-#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+#define USIR0_IR1	(1 << 2)	/* Interrup request ep 1 */
+#define USIR0_IR2	(1 << 4)	/* Interrup request ep 2 */
 #define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
 #define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
 #define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
 #define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
 #define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
 
-#define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+#define USIR1		__REG(0x40600010)  /* UDC Status Interrupt Register 1 */
 
 #define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
 #define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
@@ -751,23 +763,201 @@ typedef void		(*ExcpHndlr) (void) ;
 #define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
 #define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
 #define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
-#endif /* ! CONFIG_CPU_MONAHANS */
 
-#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
-/*
- * USB Client Controller (incomplete)
- */
-#define UDCCR		__REG(0x40600000)
-#define UDCICR0		__REG(0x40600004)
-#define UDCCIR0		__REG(0x40600008)
-#define UDCISR0		__REG(0x4060000c)
-#define UDCSIR1		__REG(0x40600010)
-#define UDCFNR		__REG(0x40600014)
-#define UDCOTGICR	__REG(0x40600018)
-#define UDCOTGISR	__REG(0x4060001c)
-#define UP2OCR		__REG(0x40600020)
-#define UP3OCR		__REG(0x40600024)
+#define UDCICR0         __REG(0x40600004)	/* UDC Interrupt Control Register0 */
+#define UDCICR1         __REG(0x40600008)	/* UDC Interrupt Control Register1 */
+#define UDCICR_FIFOERR	(1 << 1)			/* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL (1 << 0)			/* Packet Complete interrupt for EP */
+
+#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCICR1_IESOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCICR1_IERU	(1 << 29)	/* IntEn - Resume */
+#define UDCICR1_IESU	(1 << 28)	/* IntEn - Suspend */
+#define UDCICR1_IERS	(1 << 27)	/* IntEn - Reset */
+
+#define UDCISR0         __REG(0x4060000C) /* UDC Interrupt Status Register 0 */
+#define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status Register 1 */
+#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCISR1_IRSOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCISR1_IRRU	(1 << 29)	/* IntEn - Resume */
+#define UDCISR1_IRSU	(1 << 28)	/* IntEn - Suspend */
+#define UDCISR1_IRRS	(1 << 27)	/* IntEn - Reset */
+
+
+#define UDCFNR			__REG(0x40600014) /* UDC Frame Number Register */
+#define UDCOTGICR		__REG(0x40600018) /* UDC On-The-Go interrupt control */
+#define UDCOTGICR_IESF		(1 << 24)	/* OTG SET_FEATURE command recvd */
+#define UDCOTGICR_IEXR		(1 << 17)	/* Extra Transciever Interrupt Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF		(1 << 16)	/* Extra Transciever Interrupt Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R	(1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40F	(1 << 8)	/* OTG Vbus Valid 4.0V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV44R	(1 << 7)	/* OTG Vbus Valid 4.4V Rising Edge  Interrupt Enable */
+#define UDCOTGICR_IEVV44F	(1 << 6)	/* OTG Vbus Valid 4.4V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESVR		(1 << 5)	/* OTG Session Valid Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESVF		(1 << 4)	/* OTG Session Valid Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESDR		(1 << 3)	/* OTG A-Device SRP Detect Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESDF		(1 << 2)	/* OTG A-Device SRP Detect Falling  Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR		(1 << 1)	/* OTG ID Change Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEIDF		(1 << 0)	/* OTG ID Change Falling Edge Interrupt Enable */
+
+#define UDCCSN(x)	__REG2(0x40600100, (x) << 2)
+#define UDCCSR0		__REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
+
+#define UDCCSR0_SA	(1 << 7)	/* Setup Active */
+#define UDCCSR0_RNE	(1 << 6)	/* Receive FIFO Not Empty */
+#define UDCCSR0_FST	(1 << 5)	/* Force Stall */
+#define UDCCSR0_SST	(1 << 4)	/* Sent Stall */
+#define UDCCSR0_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR0_FTF	(1 << 2)	/* Flush Transmit FIFO */
+#define UDCCSR0_IPR	(1 << 1)	/* IN Packet Ready */
+#define UDCCSR0_OPC	(1 << 0)	/* OUT Packet Complete */
+
+#define UDCCSRA         __REG(0x40600104) /* UDC Control/Status register - Endpoint A */
+#define UDCCSRB         __REG(0x40600108) /* UDC Control/Status register - Endpoint B */
+#define UDCCSRC         __REG(0x4060010C) /* UDC Control/Status register - Endpoint C */
+#define UDCCSRD         __REG(0x40600110) /* UDC Control/Status register - Endpoint D */
+#define UDCCSRE         __REG(0x40600114) /* UDC Control/Status register - Endpoint E */
+#define UDCCSRF         __REG(0x40600118) /* UDC Control/Status register - Endpoint F */
+#define UDCCSRG         __REG(0x4060011C) /* UDC Control/Status register - Endpoint G */
+#define UDCCSRH         __REG(0x40600120) /* UDC Control/Status register - Endpoint H */
+#define UDCCSRI         __REG(0x40600124) /* UDC Control/Status register - Endpoint I */
+#define UDCCSRJ         __REG(0x40600128) /* UDC Control/Status register - Endpoint J */
+#define UDCCSRK         __REG(0x4060012C) /* UDC Control/Status register - Endpoint K */
+#define UDCCSRL         __REG(0x40600130) /* UDC Control/Status register - Endpoint L */
+#define UDCCSRM         __REG(0x40600134) /* UDC Control/Status register - Endpoint M */
+#define UDCCSRN         __REG(0x40600138) /* UDC Control/Status register - Endpoint N */
+#define UDCCSRP         __REG(0x4060013C) /* UDC Control/Status register - Endpoint P */
+#define UDCCSRQ         __REG(0x40600140) /* UDC Control/Status register - Endpoint Q */
+#define UDCCSRR         __REG(0x40600144) /* UDC Control/Status register - Endpoint R */
+#define UDCCSRS         __REG(0x40600148) /* UDC Control/Status register - Endpoint S */
+#define UDCCSRT         __REG(0x4060014C) /* UDC Control/Status register - Endpoint T */
+#define UDCCSRU         __REG(0x40600150) /* UDC Control/Status register - Endpoint U */
+#define UDCCSRV         __REG(0x40600154) /* UDC Control/Status register - Endpoint V */
+#define UDCCSRW         __REG(0x40600158) /* UDC Control/Status register - Endpoint W */
+#define UDCCSRX         __REG(0x4060015C) /* UDC Control/Status register - Endpoint X */
+
+#define UDCCSR_DPE	(1 << 9)	/* Data Packet Error */
+#define UDCCSR_FEF	(1 << 8)	/* Flush Endpoint FIFO */
+#define UDCCSR_SP	(1 << 7)	/* Short Packet Control/Status */
+#define UDCCSR_BNE	(1 << 6)	/* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF	(1 << 6)	/* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST	(1 << 5)	/* Force STALL */
+#define UDCCSR_SST	(1 << 4)	/* Sent STALL */
+#define UDCCSR_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR_TRN	(1 << 2)	/* Tx/Rx NAK */
+#define UDCCSR_PC	(1 << 1)	/* Packet Complete */
+#define UDCCSR_FS	(1 << 0)	/* FIFO needs service */
+
+#define UDCBCN(x)	__REG2(0x40600200, (x)<<2)
+#define UDCBCR0         __REG(0x40600200) /* Byte Count Register - EP0 */
+#define UDCBCRA         __REG(0x40600204) /* Byte Count Register - EPA */
+#define UDCBCRB         __REG(0x40600208) /* Byte Count Register - EPB */
+#define UDCBCRC         __REG(0x4060020C) /* Byte Count Register - EPC */
+#define UDCBCRD         __REG(0x40600210) /* Byte Count Register - EPD */
+#define UDCBCRE         __REG(0x40600214) /* Byte Count Register - EPE */
+#define UDCBCRF         __REG(0x40600218) /* Byte Count Register - EPF */
+#define UDCBCRG         __REG(0x4060021C) /* Byte Count Register - EPG */
+#define UDCBCRH         __REG(0x40600220) /* Byte Count Register - EPH */
+#define UDCBCRI         __REG(0x40600224) /* Byte Count Register - EPI */
+#define UDCBCRJ         __REG(0x40600228) /* Byte Count Register - EPJ */
+#define UDCBCRK         __REG(0x4060022C) /* Byte Count Register - EPK */
+#define UDCBCRL         __REG(0x40600230) /* Byte Count Register - EPL */
+#define UDCBCRM         __REG(0x40600234) /* Byte Count Register - EPM */
+#define UDCBCRN         __REG(0x40600238) /* Byte Count Register - EPN */
+#define UDCBCRP         __REG(0x4060023C) /* Byte Count Register - EPP */
+#define UDCBCRQ         __REG(0x40600240) /* Byte Count Register - EPQ */
+#define UDCBCRR         __REG(0x40600244) /* Byte Count Register - EPR */
+#define UDCBCRS         __REG(0x40600248) /* Byte Count Register - EPS */
+#define UDCBCRT         __REG(0x4060024C) /* Byte Count Register - EPT */
+#define UDCBCRU         __REG(0x40600250) /* Byte Count Register - EPU */
+#define UDCBCRV         __REG(0x40600254) /* Byte Count Register - EPV */
+#define UDCBCRW         __REG(0x40600258) /* Byte Count Register - EPW */
+#define UDCBCRX         __REG(0x4060025C) /* Byte Count Register - EPX */
+
+#define UDCDN(x)	__REG2(0x40600300, (x)<<2)
+#define UDCDR0          __REG(0x40600300) /* Data Register - EP0 */
+#define UDCDRA          __REG(0x40600304) /* Data Register - EPA */
+#define UDCDRB          __REG(0x40600308) /* Data Register - EPB */
+#define UDCDRC          __REG(0x4060030C) /* Data Register - EPC */
+#define UDCDRD          __REG(0x40600310) /* Data Register - EPD */
+#define UDCDRE          __REG(0x40600314) /* Data Register - EPE */
+#define UDCDRF          __REG(0x40600318) /* Data Register - EPF */
+#define UDCDRG          __REG(0x4060031C) /* Data Register - EPG */
+#define UDCDRH          __REG(0x40600320) /* Data Register - EPH */
+#define UDCDRI          __REG(0x40600324) /* Data Register - EPI */
+#define UDCDRJ          __REG(0x40600328) /* Data Register - EPJ */
+#define UDCDRK          __REG(0x4060032C) /* Data Register - EPK */
+#define UDCDRL          __REG(0x40600330) /* Data Register - EPL */
+#define UDCDRM          __REG(0x40600334) /* Data Register - EPM */
+#define UDCDRN          __REG(0x40600338) /* Data Register - EPN */
+#define UDCDRP          __REG(0x4060033C) /* Data Register - EPP */
+#define UDCDRQ          __REG(0x40600340) /* Data Register - EPQ */
+#define UDCDRR          __REG(0x40600344) /* Data Register - EPR */
+#define UDCDRS          __REG(0x40600348) /* Data Register - EPS */
+#define UDCDRT          __REG(0x4060034C) /* Data Register - EPT */
+#define UDCDRU          __REG(0x40600350) /* Data Register - EPU */
+#define UDCDRV          __REG(0x40600354) /* Data Register - EPV */
+#define UDCDRW          __REG(0x40600358) /* Data Register - EPW */
+#define UDCDRX          __REG(0x4060035C) /* Data Register - EPX */
+
+#define UDCCN(x)	__REG2(0x40600400, (x)<<2)
+#define UDCCRA          __REG(0x40600404) /* Configuration register EPA */
+#define UDCCRB          __REG(0x40600408) /* Configuration register EPB */
+#define UDCCRC          __REG(0x4060040C) /* Configuration register EPC */
+#define UDCCRD          __REG(0x40600410) /* Configuration register EPD */
+#define UDCCRE          __REG(0x40600414) /* Configuration register EPE */
+#define UDCCRF          __REG(0x40600418) /* Configuration register EPF */
+#define UDCCRG          __REG(0x4060041C) /* Configuration register EPG */
+#define UDCCRH          __REG(0x40600420) /* Configuration register EPH */
+#define UDCCRI          __REG(0x40600424) /* Configuration register EPI */
+#define UDCCRJ          __REG(0x40600428) /* Configuration register EPJ */
+#define UDCCRK          __REG(0x4060042C) /* Configuration register EPK */
+#define UDCCRL          __REG(0x40600430) /* Configuration register EPL */
+#define UDCCRM          __REG(0x40600434) /* Configuration register EPM */
+#define UDCCRN          __REG(0x40600438) /* Configuration register EPN */
+#define UDCCRP          __REG(0x4060043C) /* Configuration register EPP */
+#define UDCCRQ          __REG(0x40600440) /* Configuration register EPQ */
+#define UDCCRR          __REG(0x40600444) /* Configuration register EPR */
+#define UDCCRS          __REG(0x40600448) /* Configuration register EPS */
+#define UDCCRT          __REG(0x4060044C) /* Configuration register EPT */
+#define UDCCRU          __REG(0x40600450) /* Configuration register EPU */
+#define UDCCRV          __REG(0x40600454) /* Configuration register EPV */
+#define UDCCRW          __REG(0x40600458) /* Configuration register EPW */
+#define UDCCRX          __REG(0x4060045C) /* Configuration register EPX */
+
+#define UDCCONR_CN	(0x03 << 25)	/* Configuration Number */
+#define UDCCONR_CN_S	(25)
+#define UDCCONR_IN	(0x07 << 22)	/* Interface Number */
+#define UDCCONR_IN_S	(22)
+#define UDCCONR_AISN	(0x07 << 19)	/* Alternate Interface Number */
+#define UDCCONR_AISN_S	(19)
+#define UDCCONR_EN	(0x0f << 15)	/* Endpoint Number */
+#define UDCCONR_EN_S	(15)
+#define UDCCONR_ET	(0x03 << 13)	/* Endpoint Type: */
+#define UDCCONR_ET_S	(13)
+#define UDCCONR_ET_INT	(0x03 << 13)	/* Interrupt */
+#define UDCCONR_ET_BULK	(0x02 << 13)	/* Bulk */
+#define UDCCONR_ET_ISO	(0x01 << 13)	/* Isochronous */
+#define UDCCONR_ET_NU	(0x00 << 13)	/* Not used */
+#define UDCCONR_ED	(1 << 12)	/* Endpoint Direction */
+#define UDCCONR_MPS	(0x3ff << 2)	/* Maximum Packet Size */
+#define UDCCONR_MPS_S	(2)
+#define UDCCONR_DE	(1 << 1)	/* Double Buffering Enable */
+#define UDCCONR_EE	(1 << 0)	/* Endpoint Enable */
+
+
+#define UDC_INT_FIFOERROR	(0x2)
+#define UDC_INT_PACKETCMP	(0x1)
+#define UDC_FNR_MASK		(0x7ff)
+#define UDCCSR_WR_MASK		(UDCCSR_DME|UDCCSR_FST)
+#define UDC_BCR_MASK		(0x3ff)
+
+#endif /* CONFIG_PXA27X */
+
+#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
 /*
  * USB Host Controller
diff --git a/include/usbdcore_pxa27x.h b/include/usbdcore_pxa27x.h
new file mode 100644
index 0000000..e6d8121
--- /dev/null
+++ b/include/usbdcore_pxa27x.h
@@ -0,0 +1,69 @@
+/*
+ * PXA27x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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
+ */
+
+
+#ifndef __USBDCORE_PXA270X_H__
+#define __USBDCORE_PXA270X_H__
+
+#include <asm/byteorder.h>
+
+/* Endpoint 0 states */
+#define EP0_IDLE		0
+#define EP0_IN_DATA		1
+#define EP0_OUT_DATA		2
+#define EP0_XFER_COMPLETE	3
+
+
+/* Endpoint parameters */
+#define MAX_ENDPOINTS		4
+#define EP_MAX_PACKET_SIZE	64
+
+#define EP0_MAX_PACKET_SIZE     16
+#define UDC_OUT_ENDPOINT        0x02
+#define UDC_OUT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_IN_ENDPOINT         0x01
+#define UDC_IN_PACKET_SIZE      EP_MAX_PACKET_SIZE
+#define UDC_INT_ENDPOINT        0x05
+#define UDC_INT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_BULK_PACKET_SIZE    EP_MAX_PACKET_SIZE
+
+void udc_irq(void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak(int epid);
+
+/* Higher level functions for abstracting away from specific device */
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int  udc_init(void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device,
+	 unsigned int ep, struct usb_endpoint_instance *endpoint);
+
+#endif
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-09 13:08   ` Vivek Kutal
@ 2009-03-09 23:46     ` Kim Phillips
  2009-03-10 11:20       ` Vivek Kutal
  0 siblings, 1 reply; 11+ messages in thread
From: Kim Phillips @ 2009-03-09 23:46 UTC (permalink / raw)
  To: u-boot

On Mon,  9 Mar 2009 18:38:47 +0530
Vivek Kutal <vivek.kutal@azingo.com> wrote:

> +#ifdef USBDDBG
> +static void udc_dump_buffer(char *name, u8 *buf, int len)
> +{
> +	int i, p, flag = 1;
> +
> +	usbdbg("%s - buf %p, len %d", name, buf, len);
> +	for (i = p = 0; i < len; i++, p++) {
> +		if (p == 0) {
> +			flag = 0;
> +			usbdbg("\t");
> +		}
> +
> +		usbdbg("%02x ", buf[i]);
> +
> +		if (p == 15) {
> +			flag = 1;
> +			usbdbg("\n");
> +			p = -1;
> +		}
> +	}
> +	if (!flag)
> +		usbdbg("\n");
> +}
> +#else
> +#define udc_dump_buffer(name, buf, len)		/* void */
> +#endif

can we not reinvent the wheel here and use
lib_generic/display_options.c's print_buffer()?

> +static int udc_write_urb(struct usb_endpoint_instance *endpoint)
> +{
> +	struct urb *urb = endpoint->tx_urb;
> +	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
> +

no blank line here please.

> +	u32 *addr32 = (u32 *) &UDCDN(ep_num),
> +		*data32 = (u32 *) urb->buffer;
> +	u8  *addr8 = (u8 *) &UDCDN(ep_num),
> +		*data8 = (u8 *) urb->buffer;

alignment (or give data* their own entire line).

> +				/* Check direction */
> +				if (ep0_urb->device_request.bmRequestType &
> +				USB_REQ_DIRECTION_MASK == USB_REQ_HOST2DEVICE) {

alignment.  Might need to add parens for clarity.

Kim

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-09 23:46     ` Kim Phillips
@ 2009-03-10 11:20       ` Vivek Kutal
  2009-04-03 21:28         ` Wolfgang Denk
  2009-04-06 18:46         ` Remy Bohmer
  0 siblings, 2 replies; 11+ messages in thread
From: Vivek Kutal @ 2009-03-10 11:20 UTC (permalink / raw)
  To: u-boot

	This Patch adds Support for PXA27X UDC.

Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
---
 Resinding after doing the changes suggested by Kim.

 drivers/serial/usbtty.h             |    4 +-
 drivers/usb/Makefile                |    1 +
 drivers/usb/usbdcore_pxa27x.c       |  702 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-pxa/pxa-regs.h |  296 ++++++++++++---
 include/usbdcore_pxa27x.h           |   69 ++++
 5 files changed, 1018 insertions(+), 54 deletions(-)
 create mode 100644 drivers/usb/usbdcore_pxa27x.c
 create mode 100644 include/usbdcore_pxa27x.h

diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index ecefde5..5fe872e 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -27,8 +27,10 @@
 #include <usbdcore.h>
 #if defined(CONFIG_PPC)
 #include <usbdcore_mpc8xx.h>
-#elif defined(CONFIG_ARM)
+#elif defined(CONFIG_OMAP1510)
 #include <usbdcore_omap1510.h>
+#elif defined(CONFIG_PXA27X)
+#include <usbdcore_pxa27x.h>
 #endif
 
 #include <version_autogenerated.h>
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index b306a65..0a1886a 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -47,6 +47,7 @@ COBJS-y += usbdcore_ep0.o
 COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
 COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
 COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
+COBJS-$(CONFIG_PXA27X) += usbdcore_pxa27x.o
 endif
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/usb/usbdcore_pxa27x.c b/drivers/usb/usbdcore_pxa27x.c
new file mode 100644
index 0000000..8b893f7
--- /dev/null
+++ b/drivers/usb/usbdcore_pxa27x.c
@@ -0,0 +1,702 @@
+/*
+ * PXA27x USB device driver for u-boot.
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A.  <info@eurotech.it>
+ * Copyright (C) 2008 Vivek Kutal      <vivek.kutal@azingo.com>
+ *
+ * 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
+ *
+ */
+
+
+#include <common.h>
+#include <config.h>
+#include <asm/byteorder.h>
+#include <usbdcore.h>
+#include <usbdcore_ep0.h>
+#include <asm/arch/hardware.h>
+#include <usbdcore_pxa27x.h>
+
+/* number of endpoints on this UDC */
+#define UDC_MAX_ENDPOINTS	24
+
+static struct urb *ep0_urb;
+static struct usb_device_instance *udc_device;
+static int ep0state = EP0_IDLE;
+
+#ifdef USBDDBG
+static void udc_dump_buffer(char *name, u8 *buf, int len)
+{
+	usbdbg("%s - buf %p, len %d", name, buf, len);
+	print_buffer(0, buf, 1, len, 0);
+}
+#else
+#define udc_dump_buffer(name, buf, len)		/* void */
+#endif
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+	USIR1	= mask | USIR1;
+}
+
+/*
+ * If the endpoint has an active tx_urb, then the next packet of data from the
+ * URB is written to the tx FIFO.
+ * The total amount of data in the urb is given by urb->actual_length.
+ * The maximum amount of data that can be sent in any one packet is given by
+ * endpoint->tx_packetSize.
+ * The number of data bytes from this URB that have already been transmitted
+ * is given by endpoint->sent.
+ * endpoint->last is updated by this routine with the number of data bytes
+ * transmitted in this packet.
+ */
+static int udc_write_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->tx_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	u32 *addr32 = (u32 *) &UDCDN(ep_num);
+	u32 *data32 = (u32 *) urb->buffer;
+	u8  *addr8 = (u8 *) &UDCDN(ep_num);
+	u8  *data8 = (u8 *) urb->buffer;
+	unsigned int i, n, w, b, is_short;
+	int timeout = 2000;	/* 2ms */
+
+	if (!urb || !urb->actual_length)
+		return -1;
+
+	n = MIN(urb->actual_length - endpoint->sent, endpoint->tx_packetSize);
+	if (n <= 0)
+		return -1;
+
+	usbdbg("write urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: sent %d, tx_packetSize %d, last %d",
+		endpoint->sent, endpoint->tx_packetSize, endpoint->last);
+#endif
+
+	is_short = n != endpoint->tx_packetSize;
+	w = n / 4;
+	b = n % 4;
+	usbdbg("n %d%s w %d b %d", n, is_short ? "-s" : "", w, b);
+	udc_dump_buffer("urb write", data8 + endpoint->sent, n);
+
+	/* Prepare for data send */
+	if (ep_num)
+		UDCCSN(ep_num) = UDCCSR_PC;
+
+	for (i = 0; i < w; i++)
+		*addr32 = data32[endpoint->sent/4 + i];
+	for (i = 0; i < b; i++)
+		*addr8 = data8[endpoint->sent + w*4 + i];
+
+	/* Set "Packet Complete" if less data then tx_packetSize */
+	if (is_short)
+		UDCCSN(ep_num) = ep_num ? UDCCSR_SP : UDCCSR0_IPR;
+
+	/* Wait for data sent */
+	while (!(UDCCSN(ep_num) & (ep_num ? UDCCSR_PC : UDCCSR0_IPR))) {
+		if (ep_num) {
+			if (timeout-- == 0)
+				return -1;
+			else
+				udelay(1);
+		};
+	}
+	endpoint->last = n;
+
+	if (ep_num) {
+		usbd_tx_complete(endpoint);
+	} else {
+		endpoint->sent += n;
+		endpoint->last -= n;
+	}
+
+	if ((endpoint->tx_urb->actual_length - endpoint->sent) <= 0) {
+		urb->actual_length = 0;
+		endpoint->sent = 0;
+		endpoint->last = 0;
+	}
+
+	if ((endpoint->sent >= urb->actual_length) && (!ep_num)) {
+		usbdbg("ep0 IN stage done");
+		if (is_short)
+			ep0state = EP0_IDLE;
+		else
+			ep0state = EP0_XFER_COMPLETE;
+	}
+
+	return 0;
+}
+
+static int udc_read_urb(struct usb_endpoint_instance *endpoint)
+{
+	struct urb *urb = endpoint->rcv_urb;
+	int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	u32 *addr32 = (u32 *) &UDCDN(ep_num);
+	u32 *data32 = (u32 *) urb->buffer;
+	unsigned int i, n, is_short ;
+
+	usbdbg("read urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+	usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+		urb->buffer, urb->buffer_length, urb->actual_length);
+	usbdbg("endpoint: rcv_packetSize %d",
+		endpoint->rcv_packetSize);
+#endif
+
+	if (UDCCSN(ep_num) & UDCCSR_BNE)
+		n = UDCBCN(ep_num) & 0x3ff;
+	else /* zlp */
+		n = 0;
+	is_short = n != endpoint->rcv_packetSize;
+
+	usbdbg("n %d%s", n, is_short ? "-s" : "");
+	for (i = 0; i < n; i += 4)
+		data32[urb->actual_length/4 + i/4] = *addr32;
+
+	udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n);
+	usbd_rcv_complete(endpoint, n, 0);
+
+	return 0;
+}
+
+static int udc_read_urb_ep0(void)
+{
+	u32 *addr32 = (u32 *) &UDCDN(0);
+	u32 *data32 = (u32 *) ep0_urb->buffer;
+	u8 *addr8 = (u8 *) &UDCDN(0);
+	u8 *data8 = (u8 *) ep0_urb->buffer;
+	unsigned int i, n, w, b;
+
+	n = UDCBCR0;
+	w = n / 4;
+	b = n % 4;
+
+	for (i = 0; i < w; i++) {
+		data32[ep0_urb->actual_length/4 + i] = *addr32;
+		ep0_urb->actual_length += 4;
+	}
+
+	for (i = 0; i < b; i++) {
+		data8[ep0_urb->actual_length + w*4 + i] = *addr8;
+		ep0_urb->actual_length++;
+	}
+
+	UDCCSR0 = UDCCSR0_OPC | UDCCSR0_IPR;
+	if (ep0_urb->actual_length == ep0_urb->device_request.wLength)
+		return 1;
+
+	return 0;
+}
+
+static void udc_handle_ep0(struct usb_endpoint_instance *endpoint)
+{
+	u32 udccsr0 = UDCCSR0;
+	u32 *data = (u32 *) &ep0_urb->device_request;
+	int i;
+
+	usbdbg("udccsr0 %x", udccsr0);
+
+	/* Clear stall status */
+	if (udccsr0 & UDCCSR0_SST) {
+		usberr("clear stall status");
+		UDCCSR0 = UDCCSR0_SST;
+		ep0state = EP0_IDLE;
+	}
+
+	/* previous request unfinished?  non-error iff back-to-back ... */
+	if ((udccsr0 & UDCCSR0_SA) != 0 && ep0state != EP0_IDLE)
+		ep0state = EP0_IDLE;
+
+	switch (ep0state) {
+
+	case EP0_IDLE:
+
+		udccsr0 = UDCCSR0;
+		/* Start control request? */
+		if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE))
+			== (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) {
+
+			/* Read SETUP packet.
+			 * SETUP packet size is 8 bytes (aka 2 words)
+			 */
+			usbdbg("try reading SETUP packet");
+			for (i = 0; i < 2; i++) {
+				if ((UDCCSR0 & UDCCSR0_RNE) == 0) {
+					usberr("setup packet too short:%d", i);
+					goto stall;
+				}
+				data[i] = UDCDR0;
+			}
+
+			UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);
+			if ((UDCCSR0 & UDCCSR0_RNE) != 0) {
+				usberr("setup packet too long");
+				goto stall;
+			}
+
+			udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+
+			if (ep0_urb->device_request.wLength == 0) {
+				usbdbg("Zero Data control Packet\n");
+				if (ep0_recv_setup(ep0_urb)) {
+					usberr("Invalid Setup Packet\n");
+					udc_dump_buffer("ep0 setup read",
+								(u8 *)data, 8);
+					goto stall;
+				}
+				UDCCSR0 = UDCCSR0_IPR;
+				ep0state = EP0_IDLE;
+			} else {
+				/* Check direction */
+				if ((ep0_urb->device_request.bmRequestType &
+						USB_REQ_DIRECTION_MASK)
+						== USB_REQ_HOST2DEVICE) {
+					ep0state = EP0_OUT_DATA;
+					ep0_urb->buffer =
+						(u8 *)ep0_urb->buffer_data;
+					ep0_urb->buffer_length =
+						sizeof(ep0_urb->buffer_data);
+					ep0_urb->actual_length = 0;
+					UDCCSR0 = UDCCSR0_IPR;
+				} else {
+					/* The ep0_recv_setup function has
+					 * already placed our response packet
+					 * data in ep0_urb->buffer and the
+					 * packet length in
+					 * ep0_urb->actual_length.
+					 */
+					if (ep0_recv_setup(ep0_urb)) {
+stall:
+						usberr("Invalid setup packet");
+						udc_dump_buffer("ep0 setup read"
+							, (u8 *) data, 8);
+						ep0state = EP0_IDLE;
+
+						UDCCSR0 = UDCCSR0_SA |
+						UDCCSR0_OPC | UDCCSR0_FST |
+						UDCCS0_FTF;
+
+						return;
+					}
+
+					endpoint->tx_urb = ep0_urb;
+					endpoint->sent = 0;
+					usbdbg("EP0_IN_DATA");
+					ep0state = EP0_IN_DATA;
+					if (udc_write_urb(endpoint) < 0)
+						goto stall;
+
+				}
+			}
+			return;
+		} else if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA))
+			== (UDCCSR0_OPC|UDCCSR0_SA)) {
+			usberr("Setup Active but no data. Stalling ....\n");
+			goto stall;
+		} else {
+			usbdbg("random early IRQs");
+			/* Some random early IRQs:
+			 * - we acked FST
+			 * - IPR cleared
+			 * - OPC got set, without SA (likely status stage)
+			 */
+			UDCCSR0 = udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC);
+		}
+		break;
+
+	case EP0_OUT_DATA:
+
+		if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {
+			if (udc_read_urb_ep0()) {
+read_complete:
+				ep0state = EP0_IDLE;
+				if (ep0_recv_setup(ep0_urb)) {
+					/* Not a setup packet, stall next
+					 * EP0 transaction
+					 */
+					udc_dump_buffer("ep0 setup read",
+							(u8 *) data, 8);
+					usberr("can't parse setup packet\n");
+					goto stall;
+				}
+			}
+		} else if (!(udccsr0 & UDCCSR0_OPC) &&
+				!(udccsr0 & UDCCSR0_IPR)) {
+			if (ep0_urb->device_request.wLength ==
+				ep0_urb->actual_length)
+				goto read_complete;
+
+			usberr("Premature Status\n");
+			ep0state = EP0_IDLE;
+		}
+		break;
+
+	case EP0_IN_DATA:
+		/* GET_DESCRIPTOR etc */
+		if (udccsr0 & UDCCSR0_OPC) {
+			UDCCSR0 = UDCCSR0_OPC | UDCCSR0_FTF;
+			usberr("ep0in premature status");
+			ep0state = EP0_IDLE;
+		} else {
+			/* irq was IPR clearing */
+			if (udc_write_urb(endpoint) < 0) {
+				usberr("ep0_write_error\n");
+				goto stall;
+			}
+		}
+		break;
+
+	case EP0_XFER_COMPLETE:
+		UDCCSR0 = UDCCSR0_IPR;
+		ep0state = EP0_IDLE;
+		break;
+
+	default:
+		usbdbg("Default\n");
+	}
+	USIR0 = USIR0_IR0;
+}
+
+static void udc_handle_ep(struct usb_endpoint_instance *endpoint)
+{
+	int ep_addr = endpoint->endpoint_address;
+	int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	int ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+
+	u32 flags = UDCCSN(ep_num) & (UDCCSR_SST | UDCCSR_TRN);
+	if (flags)
+		UDCCSN(ep_num) = flags;
+
+	if (ep_isout)
+		udc_read_urb(endpoint);
+	else
+		udc_write_urb(endpoint);
+
+	UDCCSN(ep_num) = UDCCSR_PC;
+}
+
+static void udc_state_changed(void)
+{
+	int config, interface, alternate;
+
+	UDCCR |= UDCCR_SMAC;
+
+	config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;
+	interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;
+	alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;
+
+	usbdbg("New UDC settings are: conf %d - inter %d - alter %d",
+		config, interface, alternate);
+
+	usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+	UDCISR1 = UDCISR1_IRCC;
+}
+
+void udc_irq(void)
+{
+	int handled;
+	struct usb_endpoint_instance *endpoint;
+	int ep_num, i;
+	u32 udcisr0;
+
+	do {
+		handled = 0;
+		/* Suspend Interrupt Request */
+		if (USIR1 & UDCCR_SUSIR) {
+			usbdbg("Suspend\n");
+			udc_ack_int_UDCCR(UDCCR_SUSIR);
+			handled = 1;
+			ep0state = EP0_IDLE;
+		}
+
+		/* Resume Interrupt Request */
+		if (USIR1 & UDCCR_RESIR) {
+			udc_ack_int_UDCCR(UDCCR_RESIR);
+			handled = 1;
+			usbdbg("USB resume\n");
+		}
+
+		if (USIR1 & (1<<31)) {
+			handled = 1;
+			udc_state_changed();
+		}
+
+		/* Reset Interrupt Request */
+		if (USIR1 & UDCCR_RSTIR) {
+			udc_ack_int_UDCCR(UDCCR_RSTIR);
+			handled = 1;
+			usbdbg("Reset\n");
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+		} else {
+			if (USIR0)
+				usbdbg("UISR0: %x \n", USIR0);
+
+			if (USIR0 & 0x2)
+				USIR0 = 0x2;
+
+			/* Control traffic */
+			if (USIR0  & USIR0_IR0) {
+				handled = 1;
+				udc_handle_ep0(udc_device->bus->endpoint_array);
+				USIR0 = USIR0_IR0;
+			}
+
+			endpoint = udc_device->bus->endpoint_array;
+			for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+				ep_num = (endpoint[i].endpoint_address) &
+						USB_ENDPOINT_NUMBER_MASK;
+				if (!ep_num)
+					continue;
+				udcisr0 = UDCISR0;
+				if (udcisr0 &
+					UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) {
+					UDCISR0 = UDCISR_INT(ep_num,
+							 UDC_INT_PACKETCMP);
+					udc_handle_ep(&endpoint[i]);
+				}
+			}
+		}
+
+	} while (handled);
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_OEN		(1 << 31)   /* On-the-Go Enable */
+#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 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);
+	}
+}
+
+/*
+ * udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ */
+void udc_set_nak(int ep_num)
+{
+	/* TODO */
+}
+
+/*
+ * udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ */
+void udc_unset_nak(int ep_num)
+{
+	/* TODO */
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+	return udc_write_urb(endpoint);
+}
+
+/* Associate a physical endpoint with endpoint instance */
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
+				struct usb_endpoint_instance *endpoint)
+{
+	int ep_num, ep_addr, ep_isout, ep_type, ep_size;
+	int config, interface, alternate;
+	u32 tmp;
+
+	usbdbg("setting up endpoint id %d", id);
+
+	if (!endpoint) {
+		usberr("endpoint void!");
+		return;
+	}
+
+	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+	if (ep_num >= UDC_MAX_ENDPOINTS) {
+		usberr("unable to setup ep %d!", ep_num);
+		return;
+	}
+
+	pio_irq_enable(ep_num);
+	if (ep_num == 0) {
+		/* Done for ep0 */
+		return;
+	}
+
+	config = 1;
+	interface = 0;
+	alternate = 0;
+
+	usbdbg("config %d - interface %d - alternate %d",
+		config, interface, alternate);
+
+	ep_addr = endpoint->endpoint_address;
+	ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+	ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+	ep_type = ep_isout ? endpoint->rcv_attributes : endpoint->tx_attributes;
+	ep_size = ep_isout ? endpoint->rcv_packetSize : endpoint->tx_packetSize;
+
+	usbdbg("addr %x, num %d, dir %s, type %s, packet size %d",
+		ep_addr, ep_num,
+		ep_isout ? "out" : "in",
+		ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" :
+		ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" :
+		ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???",
+		ep_size
+		);
+
+	/* Configure UDCCRx */
+	tmp = 0;
+	tmp |= (config << UDCCONR_CN_S) & UDCCONR_CN;
+	tmp |= (interface << UDCCONR_IN_S) & UDCCONR_IN;
+	tmp |= (alternate << UDCCONR_AISN_S) & UDCCONR_AISN;
+	tmp |= (ep_num << UDCCONR_EN_S) & UDCCONR_EN;
+	tmp |= (ep_type << UDCCONR_ET_S) & UDCCONR_ET;
+	tmp |= ep_isout ? 0 : UDCCONR_ED;
+	tmp |= (ep_size << UDCCONR_MPS_S) & UDCCONR_MPS;
+	tmp |= UDCCONR_EE;
+
+	UDCCN(ep_num) = tmp;
+
+	usbdbg("UDCCR%c = %x", 'A' + ep_num-1, UDCCN(ep_num));
+	usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, UDCCSN(ep_num));
+}
+
+#define CONFIG_USB_DEV_PULLUP_GPIO 87
+
+/* Connect the USB device to the bus */
+void udc_connect(void)
+{
+	usbdbg("UDC connect");
+
+	/* Turn on the USB connection by enabling the pullup resistor */
+	set_GPIO_mode(CONFIG_USB_DEV_PULLUP_GPIO | GPIO_OUT);
+	GPSR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Disconnect the USB device to the bus */
+void udc_disconnect(void)
+{
+	usbdbg("UDC disconnect");
+
+	/* Turn off the USB connection by disabling the pullup resistor */
+	GPCR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Switch on the UDC */
+void udc_enable(struct usb_device_instance *device)
+{
+
+	ep0state = EP0_IDLE;
+	CKEN |= CKEN11_USB;
+
+	/* enable endpoint 0, A, B's Packet Complete Interrupt. */
+	UDCICR0 = 0x0000003f;
+	UDCICR1 = 0xa8000000;
+
+	/* clear the interrupt status/control registers */
+	UDCISR0 = 0xffffffff;
+	UDCISR1 = 0xffffffff;
+
+	/* set UDC-enable */
+	udc_set_mask_UDCCR(UDCCR_UDE);
+
+	udc_device = device;
+	if (!ep0_urb)
+		ep0_urb = usbd_alloc_urb(udc_device,
+				udc_device->bus->endpoint_array);
+	else
+		usbinfo("ep0_urb %p already allocated", ep0_urb);
+
+	usbdbg("UDC Enabled\n");
+}
+
+/* Need to check this again */
+void udc_disable(void)
+{
+	usbdbg("disable UDC");
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Free ep0 URB */
+	if (ep0_urb) {
+		usbd_dealloc_urb(ep0_urb);
+		ep0_urb = NULL;
+	}
+
+	/* Reset device pointer */
+	udc_device = NULL;
+}
+
+/* Allow udc code to do any additional startup */
+void udc_startup_events(struct usb_device_instance *device)
+{
+	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT */
+	usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+	/* The DEVICE_CREATE event puts the USB device in the state
+	 * STATE_ATTACHED */
+	usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+	/* Some USB controller driver implementations signal
+	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+	 * DEVICE_HUB_CONFIGURED causes a transition to the state
+	 * STATE_POWERED, and DEVICE_RESET causes a transition to
+	 * the state STATE_DEFAULT.
+	 */
+	udc_enable(device);
+}
+
+/* Initialize h/w stuff */
+int udc_init(void)
+{
+	udc_device = NULL;
+	usbdbg("PXA27x usbd start");
+
+	/* Disable the UDC */
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* Disable clock for USB device */
+	CKEN &= ~CKEN11_USB;
+
+	/* Disable IRQs: we don't use them */
+	UDCICR0 = UDCICR1 = 0;
+
+	return 0;
+}
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e014568..a8d30e2 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -596,46 +596,58 @@ typedef void		(*ExcpHndlr) (void) ;
 /*
  * USB Device Controller
  */
-#ifndef CONFIG_CPU_MONAHANS
-#define UDC_RES1	__REG(0x40600004)  /* UDC Undocumented - Reserved1 */
-#define UDC_RES2	__REG(0x40600008)  /* UDC Undocumented - Reserved2 */
-#define UDC_RES3	__REG(0x4060000C)  /* UDC Undocumented - Reserved3 */
-
-#define UDCCR		__REG(0x40600000)  /* UDC Control Register */
-#define UDCCR_UDE	(1 << 0)	/* UDC enable */
-#define UDCCR_UDA	(1 << 1)	/* UDC active */
-#define UDCCR_RSM	(1 << 2)	/* Device resume */
-#define UDCCR_RESIR	(1 << 3)	/* Resume interrupt request */
-#define UDCCR_SUSIR	(1 << 4)	/* Suspend interrupt request */
-#define UDCCR_SRM	(1 << 5)	/* Suspend/resume interrupt mask */
-#define UDCCR_RSTIR	(1 << 6)	/* Reset interrupt request */
-#define UDCCR_REM	(1 << 7)	/* Reset interrupt mask */
-
-#define UDCCS0		__REG(0x40600010)  /* UDC Endpoint 0 Control/Status Register */
-#define UDCCS0_OPR	(1 << 0)	/* OUT packet ready */
-#define UDCCS0_IPR	(1 << 1)	/* IN packet ready */
-#define UDCCS0_FTF	(1 << 2)	/* Flush Tx FIFO */
-#define UDCCS0_DRWF	(1 << 3)	/* Device remote wakeup feature */
-#define UDCCS0_SST	(1 << 4)	/* Sent stall */
-#define UDCCS0_FST	(1 << 5)	/* Force stall */
-#define UDCCS0_RNE	(1 << 6)	/* Receive FIFO no empty */
-#define UDCCS0_SA	(1 << 7)	/* Setup active */
+#ifdef CONFIG_PXA27X
+
+#define UDCCR		__REG(0x40600000)	/* UDC Control Register */
+#define UDCCR_UDE	(1 << 0)		/* UDC enable */
+#define UDCCR_UDA	(1 << 1)		/* UDC active */
+#define UDCCR_RSM	(1 << 2)		/* Device resume */
+#define UDCCR_EMCE	(1 << 3)		/* Endpoint Memory Configuration Error */
+#define UDCCR_SMAC	(1 << 4)		/* Switch Endpoint Memory to Active Configuration */
+#define UDCCR_RESIR	(1 << 29)		/* Resume interrupt request */
+#define UDCCR_SUSIR	(1 << 28)		/* Suspend interrupt request */
+#define UDCCR_SM	(1 << 28)		/* Suspend interrupt mask */
+#define UDCCR_RSTIR	(1 << 27)		/* Reset interrupt request */
+#define UDCCR_REM	(1 << 27)		/* Reset interrupt mask */
+#define UDCCR_RM	(1 << 29)		/* resume interrupt mask */
+#define UDCCR_SRM	(UDCCR_SM|UDCCR_RM)
+#define UDCCR_OEN	(1 << 31)		/* On-the-Go Enable */
+#define UDCCR_AALTHNP	(1 << 30)		/* A-device Alternate Host Negotiation Protocol Port Support */
+#define UDCCR_AHNP	(1 << 29)		/* A-device Host Negotiation Protocol Support */
+#define UDCCR_BHNP	(1 << 28)		/* B-device Host Negotiation Protocol Enable */
+#define UDCCR_DWRE	(1 << 16)		/* Device Remote Wake-up Enable */
+#define UDCCR_ACN	(0x03 << 11)		/* Active UDC configuration Number */
+#define UDCCR_ACN_S	11
+#define UDCCR_AIN	(0x07 << 8)		/* Active UDC interface Number */
+#define UDCCR_AIN_S	8
+#define UDCCR_AAISN	(0x07 << 5)		/* Active UDC Alternate Interface  Setting Number */
+#define UDCCR_AAISN_S	5
+
+#define UDCCS0		__REG(0x40600100)	/* UDC Endpoint 0 Control/Status Register */
+#define UDCCS0_OPR	(1 << 0)		/* OUT packet ready */
+#define UDCCS0_IPR	(1 << 1)		/* IN packet ready */
+#define UDCCS0_FTF	(1 << 2)		/* Flush Tx FIFO */
+#define UDCCS0_DRWF	(1 << 16)		/* Device remote wakeup feature */
+#define UDCCS0_SST	(1 << 4)		/* Sent stall */
+#define UDCCS0_FST	(1 << 5)		/* Force stall */
+#define UDCCS0_RNE	(1 << 6)		/* Receive FIFO no empty */
+#define UDCCS0_SA	(1 << 7)		/* Setup active */
 
 /* Bulk IN - Endpoint 1,6,11 */
-#define UDCCS1		__REG(0x40600014)  /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS1		__REG(0x40600104)  /* UDC Endpoint 1 (IN) Control/Status Register */
 #define UDCCS6		__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
 #define UDCCS11		__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
 
 #define UDCCS_BI_TFS	(1 << 0)	/* Transmit FIFO service */
 #define UDCCS_BI_TPC	(1 << 1)	/* Transmit packet complete */
-#define UDCCS_BI_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS_BI_FTF	(1 << 8)	/* Flush Tx FIFO */
 #define UDCCS_BI_TUR	(1 << 3)	/* Transmit FIFO underrun */
 #define UDCCS_BI_SST	(1 << 4)	/* Sent stall */
 #define UDCCS_BI_FST	(1 << 5)	/* Force stall */
 #define UDCCS_BI_TSP	(1 << 7)	/* Transmit short packet */
 
 /* Bulk OUT - Endpoint 2,7,12 */
-#define UDCCS2		__REG(0x40600018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS2		__REG(0x40600108)  /* UDC Endpoint 2 (OUT) Control/Status Register */
 #define UDCCS7		__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
 #define UDCCS12		__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
 
@@ -684,16 +696,16 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDCCS_INT_TSP	(1 << 7)	/* Transmit short packet */
 
 #define UFNRH		__REG(0x40600060)  /* UDC Frame Number Register High */
-#define UFNRL		__REG(0x40600064)  /* UDC Frame Number Register Low */
-#define UBCR2		__REG(0x40600068)  /* UDC Byte Count Reg 2 */
+#define UFNRL		__REG(0x40600014)  /* UDC Frame Number Register Low */
+#define UBCR2		__REG(0x40600208)  /* UDC Byte Count Reg 2 */
 #define UBCR4		__REG(0x4060006c)  /* UDC Byte Count Reg 4 */
 #define UBCR7		__REG(0x40600070)  /* UDC Byte Count Reg 7 */
 #define UBCR9		__REG(0x40600074)  /* UDC Byte Count Reg 9 */
 #define UBCR12		__REG(0x40600078)  /* UDC Byte Count Reg 12 */
 #define UBCR14		__REG(0x4060007c)  /* UDC Byte Count Reg 14 */
-#define UDDR0		__REG(0x40600080)  /* UDC Endpoint 0 Data Register */
-#define UDDR1		__REG(0x40600100)  /* UDC Endpoint 1 Data Register */
-#define UDDR2		__REG(0x40600180)  /* UDC Endpoint 2 Data Register */
+#define UDDR0		__REG(0x40600300)  /* UDC Endpoint 0 Data Register */
+#define UDDR1		__REG(0x40600304)  /* UDC Endpoint 1 Data Register */
+#define UDDR2		__REG(0x40600308)  /* UDC Endpoint 2 Data Register */
 #define UDDR3		__REG(0x40600200)  /* UDC Endpoint 3 Data Register */
 #define UDDR4		__REG(0x40600400)  /* UDC Endpoint 4 Data Register */
 #define UDDR5		__REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
@@ -708,7 +720,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UDDR14		__REG(0x40600E00)  /* UDC Endpoint 14 Data Register */
 #define UDDR15		__REG(0x406000E0)  /* UDC Endpoint 15 Data Register */
 
-#define UICR0		__REG(0x40600050)  /* UDC Interrupt Control Register 0 */
+#define UICR0		__REG(0x40600004)  /* UDC Interrupt Control Register 0 */
 
 #define UICR0_IM0	(1 << 0)	/* Interrupt mask ep 0 */
 #define UICR0_IM1	(1 << 1)	/* Interrupt mask ep 1 */
@@ -719,7 +731,7 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR0_IM6	(1 << 6)	/* Interrupt mask ep 6 */
 #define UICR0_IM7	(1 << 7)	/* Interrupt mask ep 7 */
 
-#define UICR1		__REG(0x40600054)  /* UDC Interrupt Control Register 1 */
+#define UICR1		__REG(0x40600008)  /* UDC Interrupt Control Register 1 */
 
 #define UICR1_IM8	(1 << 0)	/* Interrupt mask ep 8 */
 #define UICR1_IM9	(1 << 1)	/* Interrupt mask ep 9 */
@@ -730,18 +742,18 @@ typedef void		(*ExcpHndlr) (void) ;
 #define UICR1_IM14	(1 << 6)	/* Interrupt mask ep 14 */
 #define UICR1_IM15	(1 << 7)	/* Interrupt mask ep 15 */
 
-#define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+#define USIR0		__REG(0x4060000C)  /* UDC Status Interrupt Register 0 */
 
 #define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
-#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
-#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+#define USIR0_IR1	(1 << 2)	/* Interrup request ep 1 */
+#define USIR0_IR2	(1 << 4)	/* Interrup request ep 2 */
 #define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
 #define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
 #define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
 #define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
 #define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
 
-#define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+#define USIR1		__REG(0x40600010)  /* UDC Status Interrupt Register 1 */
 
 #define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
 #define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
@@ -751,23 +763,201 @@ typedef void		(*ExcpHndlr) (void) ;
 #define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
 #define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
 #define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
-#endif /* ! CONFIG_CPU_MONAHANS */
 
-#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
-/*
- * USB Client Controller (incomplete)
- */
-#define UDCCR		__REG(0x40600000)
-#define UDCICR0		__REG(0x40600004)
-#define UDCCIR0		__REG(0x40600008)
-#define UDCISR0		__REG(0x4060000c)
-#define UDCSIR1		__REG(0x40600010)
-#define UDCFNR		__REG(0x40600014)
-#define UDCOTGICR	__REG(0x40600018)
-#define UDCOTGISR	__REG(0x4060001c)
-#define UP2OCR		__REG(0x40600020)
-#define UP3OCR		__REG(0x40600024)
+#define UDCICR0         __REG(0x40600004)	/* UDC Interrupt Control Register0 */
+#define UDCICR1         __REG(0x40600008)	/* UDC Interrupt Control Register1 */
+#define UDCICR_FIFOERR	(1 << 1)			/* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL (1 << 0)			/* Packet Complete interrupt for EP */
+
+#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCICR1_IESOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCICR1_IERU	(1 << 29)	/* IntEn - Resume */
+#define UDCICR1_IESU	(1 << 28)	/* IntEn - Suspend */
+#define UDCICR1_IERS	(1 << 27)	/* IntEn - Reset */
+
+#define UDCISR0         __REG(0x4060000C) /* UDC Interrupt Status Register 0 */
+#define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status Register 1 */
+#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC	(1 << 31)	/* IntEn - Configuration Change */
+#define UDCISR1_IRSOF	(1 << 30)	/* IntEn - Start of Frame */
+#define UDCISR1_IRRU	(1 << 29)	/* IntEn - Resume */
+#define UDCISR1_IRSU	(1 << 28)	/* IntEn - Suspend */
+#define UDCISR1_IRRS	(1 << 27)	/* IntEn - Reset */
+
+
+#define UDCFNR			__REG(0x40600014) /* UDC Frame Number Register */
+#define UDCOTGICR		__REG(0x40600018) /* UDC On-The-Go interrupt control */
+#define UDCOTGICR_IESF		(1 << 24)	/* OTG SET_FEATURE command recvd */
+#define UDCOTGICR_IEXR		(1 << 17)	/* Extra Transciever Interrupt Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF		(1 << 16)	/* Extra Transciever Interrupt Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R	(1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40F	(1 << 8)	/* OTG Vbus Valid 4.0V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV44R	(1 << 7)	/* OTG Vbus Valid 4.4V Rising Edge  Interrupt Enable */
+#define UDCOTGICR_IEVV44F	(1 << 6)	/* OTG Vbus Valid 4.4V Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESVR		(1 << 5)	/* OTG Session Valid Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESVF		(1 << 4)	/* OTG Session Valid Falling Edge Interrupt Enable */
+#define UDCOTGICR_IESDR		(1 << 3)	/* OTG A-Device SRP Detect Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESDF		(1 << 2)	/* OTG A-Device SRP Detect Falling  Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR		(1 << 1)	/* OTG ID Change Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEIDF		(1 << 0)	/* OTG ID Change Falling Edge Interrupt Enable */
+
+#define UDCCSN(x)	__REG2(0x40600100, (x) << 2)
+#define UDCCSR0		__REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
+
+#define UDCCSR0_SA	(1 << 7)	/* Setup Active */
+#define UDCCSR0_RNE	(1 << 6)	/* Receive FIFO Not Empty */
+#define UDCCSR0_FST	(1 << 5)	/* Force Stall */
+#define UDCCSR0_SST	(1 << 4)	/* Sent Stall */
+#define UDCCSR0_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR0_FTF	(1 << 2)	/* Flush Transmit FIFO */
+#define UDCCSR0_IPR	(1 << 1)	/* IN Packet Ready */
+#define UDCCSR0_OPC	(1 << 0)	/* OUT Packet Complete */
+
+#define UDCCSRA         __REG(0x40600104) /* UDC Control/Status register - Endpoint A */
+#define UDCCSRB         __REG(0x40600108) /* UDC Control/Status register - Endpoint B */
+#define UDCCSRC         __REG(0x4060010C) /* UDC Control/Status register - Endpoint C */
+#define UDCCSRD         __REG(0x40600110) /* UDC Control/Status register - Endpoint D */
+#define UDCCSRE         __REG(0x40600114) /* UDC Control/Status register - Endpoint E */
+#define UDCCSRF         __REG(0x40600118) /* UDC Control/Status register - Endpoint F */
+#define UDCCSRG         __REG(0x4060011C) /* UDC Control/Status register - Endpoint G */
+#define UDCCSRH         __REG(0x40600120) /* UDC Control/Status register - Endpoint H */
+#define UDCCSRI         __REG(0x40600124) /* UDC Control/Status register - Endpoint I */
+#define UDCCSRJ         __REG(0x40600128) /* UDC Control/Status register - Endpoint J */
+#define UDCCSRK         __REG(0x4060012C) /* UDC Control/Status register - Endpoint K */
+#define UDCCSRL         __REG(0x40600130) /* UDC Control/Status register - Endpoint L */
+#define UDCCSRM         __REG(0x40600134) /* UDC Control/Status register - Endpoint M */
+#define UDCCSRN         __REG(0x40600138) /* UDC Control/Status register - Endpoint N */
+#define UDCCSRP         __REG(0x4060013C) /* UDC Control/Status register - Endpoint P */
+#define UDCCSRQ         __REG(0x40600140) /* UDC Control/Status register - Endpoint Q */
+#define UDCCSRR         __REG(0x40600144) /* UDC Control/Status register - Endpoint R */
+#define UDCCSRS         __REG(0x40600148) /* UDC Control/Status register - Endpoint S */
+#define UDCCSRT         __REG(0x4060014C) /* UDC Control/Status register - Endpoint T */
+#define UDCCSRU         __REG(0x40600150) /* UDC Control/Status register - Endpoint U */
+#define UDCCSRV         __REG(0x40600154) /* UDC Control/Status register - Endpoint V */
+#define UDCCSRW         __REG(0x40600158) /* UDC Control/Status register - Endpoint W */
+#define UDCCSRX         __REG(0x4060015C) /* UDC Control/Status register - Endpoint X */
+
+#define UDCCSR_DPE	(1 << 9)	/* Data Packet Error */
+#define UDCCSR_FEF	(1 << 8)	/* Flush Endpoint FIFO */
+#define UDCCSR_SP	(1 << 7)	/* Short Packet Control/Status */
+#define UDCCSR_BNE	(1 << 6)	/* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF	(1 << 6)	/* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST	(1 << 5)	/* Force STALL */
+#define UDCCSR_SST	(1 << 4)	/* Sent STALL */
+#define UDCCSR_DME	(1 << 3)	/* DMA Enable */
+#define UDCCSR_TRN	(1 << 2)	/* Tx/Rx NAK */
+#define UDCCSR_PC	(1 << 1)	/* Packet Complete */
+#define UDCCSR_FS	(1 << 0)	/* FIFO needs service */
+
+#define UDCBCN(x)	__REG2(0x40600200, (x)<<2)
+#define UDCBCR0         __REG(0x40600200) /* Byte Count Register - EP0 */
+#define UDCBCRA         __REG(0x40600204) /* Byte Count Register - EPA */
+#define UDCBCRB         __REG(0x40600208) /* Byte Count Register - EPB */
+#define UDCBCRC         __REG(0x4060020C) /* Byte Count Register - EPC */
+#define UDCBCRD         __REG(0x40600210) /* Byte Count Register - EPD */
+#define UDCBCRE         __REG(0x40600214) /* Byte Count Register - EPE */
+#define UDCBCRF         __REG(0x40600218) /* Byte Count Register - EPF */
+#define UDCBCRG         __REG(0x4060021C) /* Byte Count Register - EPG */
+#define UDCBCRH         __REG(0x40600220) /* Byte Count Register - EPH */
+#define UDCBCRI         __REG(0x40600224) /* Byte Count Register - EPI */
+#define UDCBCRJ         __REG(0x40600228) /* Byte Count Register - EPJ */
+#define UDCBCRK         __REG(0x4060022C) /* Byte Count Register - EPK */
+#define UDCBCRL         __REG(0x40600230) /* Byte Count Register - EPL */
+#define UDCBCRM         __REG(0x40600234) /* Byte Count Register - EPM */
+#define UDCBCRN         __REG(0x40600238) /* Byte Count Register - EPN */
+#define UDCBCRP         __REG(0x4060023C) /* Byte Count Register - EPP */
+#define UDCBCRQ         __REG(0x40600240) /* Byte Count Register - EPQ */
+#define UDCBCRR         __REG(0x40600244) /* Byte Count Register - EPR */
+#define UDCBCRS         __REG(0x40600248) /* Byte Count Register - EPS */
+#define UDCBCRT         __REG(0x4060024C) /* Byte Count Register - EPT */
+#define UDCBCRU         __REG(0x40600250) /* Byte Count Register - EPU */
+#define UDCBCRV         __REG(0x40600254) /* Byte Count Register - EPV */
+#define UDCBCRW         __REG(0x40600258) /* Byte Count Register - EPW */
+#define UDCBCRX         __REG(0x4060025C) /* Byte Count Register - EPX */
+
+#define UDCDN(x)	__REG2(0x40600300, (x)<<2)
+#define UDCDR0          __REG(0x40600300) /* Data Register - EP0 */
+#define UDCDRA          __REG(0x40600304) /* Data Register - EPA */
+#define UDCDRB          __REG(0x40600308) /* Data Register - EPB */
+#define UDCDRC          __REG(0x4060030C) /* Data Register - EPC */
+#define UDCDRD          __REG(0x40600310) /* Data Register - EPD */
+#define UDCDRE          __REG(0x40600314) /* Data Register - EPE */
+#define UDCDRF          __REG(0x40600318) /* Data Register - EPF */
+#define UDCDRG          __REG(0x4060031C) /* Data Register - EPG */
+#define UDCDRH          __REG(0x40600320) /* Data Register - EPH */
+#define UDCDRI          __REG(0x40600324) /* Data Register - EPI */
+#define UDCDRJ          __REG(0x40600328) /* Data Register - EPJ */
+#define UDCDRK          __REG(0x4060032C) /* Data Register - EPK */
+#define UDCDRL          __REG(0x40600330) /* Data Register - EPL */
+#define UDCDRM          __REG(0x40600334) /* Data Register - EPM */
+#define UDCDRN          __REG(0x40600338) /* Data Register - EPN */
+#define UDCDRP          __REG(0x4060033C) /* Data Register - EPP */
+#define UDCDRQ          __REG(0x40600340) /* Data Register - EPQ */
+#define UDCDRR          __REG(0x40600344) /* Data Register - EPR */
+#define UDCDRS          __REG(0x40600348) /* Data Register - EPS */
+#define UDCDRT          __REG(0x4060034C) /* Data Register - EPT */
+#define UDCDRU          __REG(0x40600350) /* Data Register - EPU */
+#define UDCDRV          __REG(0x40600354) /* Data Register - EPV */
+#define UDCDRW          __REG(0x40600358) /* Data Register - EPW */
+#define UDCDRX          __REG(0x4060035C) /* Data Register - EPX */
+
+#define UDCCN(x)	__REG2(0x40600400, (x)<<2)
+#define UDCCRA          __REG(0x40600404) /* Configuration register EPA */
+#define UDCCRB          __REG(0x40600408) /* Configuration register EPB */
+#define UDCCRC          __REG(0x4060040C) /* Configuration register EPC */
+#define UDCCRD          __REG(0x40600410) /* Configuration register EPD */
+#define UDCCRE          __REG(0x40600414) /* Configuration register EPE */
+#define UDCCRF          __REG(0x40600418) /* Configuration register EPF */
+#define UDCCRG          __REG(0x4060041C) /* Configuration register EPG */
+#define UDCCRH          __REG(0x40600420) /* Configuration register EPH */
+#define UDCCRI          __REG(0x40600424) /* Configuration register EPI */
+#define UDCCRJ          __REG(0x40600428) /* Configuration register EPJ */
+#define UDCCRK          __REG(0x4060042C) /* Configuration register EPK */
+#define UDCCRL          __REG(0x40600430) /* Configuration register EPL */
+#define UDCCRM          __REG(0x40600434) /* Configuration register EPM */
+#define UDCCRN          __REG(0x40600438) /* Configuration register EPN */
+#define UDCCRP          __REG(0x4060043C) /* Configuration register EPP */
+#define UDCCRQ          __REG(0x40600440) /* Configuration register EPQ */
+#define UDCCRR          __REG(0x40600444) /* Configuration register EPR */
+#define UDCCRS          __REG(0x40600448) /* Configuration register EPS */
+#define UDCCRT          __REG(0x4060044C) /* Configuration register EPT */
+#define UDCCRU          __REG(0x40600450) /* Configuration register EPU */
+#define UDCCRV          __REG(0x40600454) /* Configuration register EPV */
+#define UDCCRW          __REG(0x40600458) /* Configuration register EPW */
+#define UDCCRX          __REG(0x4060045C) /* Configuration register EPX */
+
+#define UDCCONR_CN	(0x03 << 25)	/* Configuration Number */
+#define UDCCONR_CN_S	(25)
+#define UDCCONR_IN	(0x07 << 22)	/* Interface Number */
+#define UDCCONR_IN_S	(22)
+#define UDCCONR_AISN	(0x07 << 19)	/* Alternate Interface Number */
+#define UDCCONR_AISN_S	(19)
+#define UDCCONR_EN	(0x0f << 15)	/* Endpoint Number */
+#define UDCCONR_EN_S	(15)
+#define UDCCONR_ET	(0x03 << 13)	/* Endpoint Type: */
+#define UDCCONR_ET_S	(13)
+#define UDCCONR_ET_INT	(0x03 << 13)	/* Interrupt */
+#define UDCCONR_ET_BULK	(0x02 << 13)	/* Bulk */
+#define UDCCONR_ET_ISO	(0x01 << 13)	/* Isochronous */
+#define UDCCONR_ET_NU	(0x00 << 13)	/* Not used */
+#define UDCCONR_ED	(1 << 12)	/* Endpoint Direction */
+#define UDCCONR_MPS	(0x3ff << 2)	/* Maximum Packet Size */
+#define UDCCONR_MPS_S	(2)
+#define UDCCONR_DE	(1 << 1)	/* Double Buffering Enable */
+#define UDCCONR_EE	(1 << 0)	/* Endpoint Enable */
+
+
+#define UDC_INT_FIFOERROR	(0x2)
+#define UDC_INT_PACKETCMP	(0x1)
+#define UDC_FNR_MASK		(0x7ff)
+#define UDCCSR_WR_MASK		(UDCCSR_DME|UDCCSR_FST)
+#define UDC_BCR_MASK		(0x3ff)
+
+#endif /* CONFIG_PXA27X */
+
+#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS)
 
 /*
  * USB Host Controller
diff --git a/include/usbdcore_pxa27x.h b/include/usbdcore_pxa27x.h
new file mode 100644
index 0000000..e6d8121
--- /dev/null
+++ b/include/usbdcore_pxa27x.h
@@ -0,0 +1,69 @@
+/*
+ * PXA27x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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
+ */
+
+
+#ifndef __USBDCORE_PXA270X_H__
+#define __USBDCORE_PXA270X_H__
+
+#include <asm/byteorder.h>
+
+/* Endpoint 0 states */
+#define EP0_IDLE		0
+#define EP0_IN_DATA		1
+#define EP0_OUT_DATA		2
+#define EP0_XFER_COMPLETE	3
+
+
+/* Endpoint parameters */
+#define MAX_ENDPOINTS		4
+#define EP_MAX_PACKET_SIZE	64
+
+#define EP0_MAX_PACKET_SIZE     16
+#define UDC_OUT_ENDPOINT        0x02
+#define UDC_OUT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_IN_ENDPOINT         0x01
+#define UDC_IN_PACKET_SIZE      EP_MAX_PACKET_SIZE
+#define UDC_INT_ENDPOINT        0x05
+#define UDC_INT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_BULK_PACKET_SIZE    EP_MAX_PACKET_SIZE
+
+void udc_irq(void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak(int epid);
+
+/* Higher level functions for abstracting away from specific device */
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int  udc_init(void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device,
+	 unsigned int ep, struct usb_endpoint_instance *endpoint);
+
+#endif
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-10 11:20       ` Vivek Kutal
@ 2009-04-03 21:28         ` Wolfgang Denk
  2009-04-04 16:04           ` Jean-Christophe PLAGNIOL-VILLARD
  2009-04-06 18:46         ` Remy Bohmer
  1 sibling, 1 reply; 11+ messages in thread
From: Wolfgang Denk @ 2009-04-03 21:28 UTC (permalink / raw)
  To: u-boot

Dear Jean-Christophe & Remy,

In message <1236684053-21368-1-git-send-email-vivek.kutal@azingo.com> Vivek Kutal wrote:
> 	This Patch adds Support for PXA27X UDC.
> 
> Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
> ---
>  Resinding after doing the changes suggested by Kim.
> 
>  drivers/serial/usbtty.h             |    4 +-
>  drivers/usb/Makefile                |    1 +
>  drivers/usb/usbdcore_pxa27x.c       |  702 +++++++++++++++++++++++++++++++++++
>  include/asm-arm/arch-pxa/pxa-regs.h |  296 ++++++++++++---
>  include/usbdcore_pxa27x.h           |   69 ++++
>  5 files changed, 1018 insertions(+), 54 deletions(-)
>  create mode 100644 drivers/usb/usbdcore_pxa27x.c
>  create mode 100644 include/usbdcore_pxa27x.h

Is this going to go through the USB or through the PXA tree?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-04-03 21:28         ` Wolfgang Denk
@ 2009-04-04 16:04           ` Jean-Christophe PLAGNIOL-VILLARD
  2009-04-05  8:00             ` Remy Bohmer
  0 siblings, 1 reply; 11+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-04-04 16:04 UTC (permalink / raw)
  To: u-boot

On 23:28 Fri 03 Apr     , Wolfgang Denk wrote:
> Dear Jean-Christophe & Remy,
> 
> In message <1236684053-21368-1-git-send-email-vivek.kutal@azingo.com> Vivek Kutal wrote:
> > 	This Patch adds Support for PXA27X UDC.
> > 
> > Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
> > ---
> >  Resinding after doing the changes suggested by Kim.
> > 
> >  drivers/serial/usbtty.h             |    4 +-
> >  drivers/usb/Makefile                |    1 +
> >  drivers/usb/usbdcore_pxa27x.c       |  702 +++++++++++++++++++++++++++++++++++
> >  include/asm-arm/arch-pxa/pxa-regs.h |  296 ++++++++++++---
> >  include/usbdcore_pxa27x.h           |   69 ++++
> >  5 files changed, 1018 insertions(+), 54 deletions(-)
> >  create mode 100644 drivers/usb/usbdcore_pxa27x.c
> >  create mode 100644 include/usbdcore_pxa27x.h
> 
> Is this going to go through the USB or through the PXA tree?
USB I guess
But the patch will need to rebase due to the last usb dev

Best Regards,
J.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-04-04 16:04           ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-04-05  8:00             ` Remy Bohmer
  0 siblings, 0 replies; 11+ messages in thread
From: Remy Bohmer @ 2009-04-05  8:00 UTC (permalink / raw)
  To: u-boot

Hello All,

>> Is this going to go through the USB or through the PXA tree?
> USB I guess
> But the patch will need to rebase due to the last usb dev

USB is fine with me.

Kind Regards,

Remy

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH v2] Support for PXA27X UDC.
  2009-03-10 11:20       ` Vivek Kutal
  2009-04-03 21:28         ` Wolfgang Denk
@ 2009-04-06 18:46         ` Remy Bohmer
  1 sibling, 0 replies; 11+ messages in thread
From: Remy Bohmer @ 2009-04-06 18:46 UTC (permalink / raw)
  To: u-boot

Hello Vivek,

2009/3/10 Vivek Kutal <vivek.kutal@azingo.com>:
> ? ? ? ?This Patch adds Support for PXA27X UDC.
>
> Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
> ---
> ?Resinding after doing the changes suggested by Kim.

Applied to U-boot usb.
Thanks.

Remy

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-04-06 18:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-23 16:05 [U-Boot] [PATCH v2] Support for PXA27X UDC Vivek Kutal
2009-03-05 11:15 ` Remy Bohmer
2009-03-06 11:55   ` Vivek Kutal
2009-03-06 14:26     ` Remy Bohmer
2009-03-09 13:08   ` Vivek Kutal
2009-03-09 23:46     ` Kim Phillips
2009-03-10 11:20       ` Vivek Kutal
2009-04-03 21:28         ` Wolfgang Denk
2009-04-04 16:04           ` Jean-Christophe PLAGNIOL-VILLARD
2009-04-05  8:00             ` Remy Bohmer
2009-04-06 18:46         ` Remy Bohmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox