From: Marcel <korg...@home.nl>

Atmel USBA UDC cleanup

Atmel USBA UDC cleanup

more cleanup of Atmel USBA UDC

Some more cleaning of Atmel USBA UDC

further cleaning of Atmel USBA UDC

Signed-off-by: Marcel <korg...@home.nl>
---
 drivers/usb/gadget/Makefile         |    1 +
 drivers/usb/gadget/atmel_usba_udc.c | 1438 +++++++++++++++++++++++++++++++++++
 include/usb/atmel_usba_udc.h        |  398 ++++++++++
 3 files changed, 1837 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/atmel_usba_udc.c
 create mode 100644 include/usb/atmel_usba_udc.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 0846233..024844d 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB   := $(obj)libusb_gadget.o
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_AT91) += at91_udc.o
+COBJS-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o
 else
 # Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
 ifdef CONFIG_USB_DEVICE
diff --git a/drivers/usb/gadget/atmel_usba_udc.c 
b/drivers/usb/gadget/atmel_usba_udc.c
new file mode 100644
index 0000000..6d02de6
--- /dev/null
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -0,0 +1,1438 @@
+/*
+ * Driver for the Atmel USBA high speed USB device controller
+ *
+ * Copyright (C) 2011 Marcel Janssen, Admesy B.V.
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <linux/list.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/mtd/compat.h>
+#include <linux/porting-compat.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/io.h>
+
+#include <usb/atmel_usba_udc.h>
+
+#define __iomem
+
+#define memcpy_toio(a, b, c)        memcpy((a), (b), (c))
+#define memcpy_fromio(a, b, c)      memcpy((a), (b), (c))
+#define REQ_COUNT 8
+#define MAX_REQ (REQ_COUNT-1)
+
+static struct usba_udc the_udc;
+#define true 1
+#define false 0
+static const char driver_name[] = "atmel_usba_udc";
+static const char ep0name[] = "ep0";
+
+
+static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+{
+       unsigned int transaction_len;
+
+       transaction_len = req->req.length - req->req.actual;
+       req->last_transaction = 1;
+       if (transaction_len > ep->ep.maxpacket) {
+               transaction_len = ep->ep.maxpacket;
+               req->last_transaction = 0;
+       } else if (transaction_len == ep->ep.maxpacket && req->req.zero)
+               req->last_transaction = 0;
+
+       debug("%s: submit_transaction, req %p (length %d)%s\n",
+               ep->ep.name, req, transaction_len,
+               req->last_transaction ? ", done" : "");
+
+       memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       req->req.actual += transaction_len;
+}
+
+static void submit_request(struct usba_ep *ep, struct usba_request *req)
+{
+
+       req->req.actual = 0;
+       req->submitted = 1;
+
+       debug("%s : submit_request: req %p (length %d)\n",
+                               ep->ep.name, req, req->req.length);
+       next_fifo_transaction(ep, req);
+       if (req->last_transaction) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+       } else {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+               }
+}
+
+static void submit_next_request(struct usba_ep *ep)
+{
+       struct usba_request *req;
+
+       if (list_empty(&ep->queue)) {
+               usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY);
+               return;
+       }
+       req = list_entry(ep->queue.next, struct usba_request, queue);
+       if (!req->submitted)
+               submit_request(ep, req);
+       debug("%s : submit_next_request: req %p (length %d)\n",
+                               ep->ep.name, req, req->req.length);
+}
+
+static void send_status(struct usba_udc *udc, struct usba_ep *ep)
+{
+       debug("Send USBA status\n");
+       ep->state = STATUS_STAGE_IN;
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+}
+
+static void receive_data(struct usba_ep *ep)
+{
+       struct usba_udc *udc = ep->udc;
+       struct usba_request *req;
+       unsigned long status;
+       unsigned int bytecount, nr_busy;
+       int is_complete = 0;
+
+       status = usba_ep_readl(ep, STA);
+       nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
+       debug("receive data: nr_busy=%u\n", nr_busy);
+
+       while (nr_busy > 0) {
+               if (list_empty(&ep->queue)) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       break;
+               }
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+               bytecount = USBA_BFEXT(BYTE_COUNT, status);
+
+               if (status & (1 << 31))
+                       is_complete = 1;
+               if (req->req.actual + bytecount >= req->req.length) {
+                       is_complete = 1;
+                       bytecount = req->req.length - req->req.actual;
+               }
+
+               memcpy_fromio(req->req.buf + req->req.actual,
+                               ep->fifo, bytecount);
+               req->req.actual += bytecount;
+
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+
+               if (is_complete) {
+                       debug("%s: request done\n", ep->ep.name);
+                       req->req.status = 0;
+                       list_del_init(&req->queue);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       req->req.complete(&ep->ep, &req->req);
+                       debug("request->complete done\n");
+               }
+
+               status = usba_ep_readl(ep, STA);
+               nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+               debug("nr_busy = %d\n", nr_busy);
+               if (is_complete && ep_is_control(ep)) {
+                       send_status(udc, ep);
+                       break;
+               }
+               debug("rcv : bytecount=%d actual=%d\n", req->req.actual);
+       }
+}
+
+static void
+request_complete(struct usba_ep *ep, struct usba_request *req, int status)
+{
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+
+       debug("%s: req %p complete: status %d, actual %u\n",
+               ep->ep.name, req, req->req.status, req->req.actual);
+
+       req->req.complete(&ep->ep, &req->req);
+       debug("request complete finished\n");
+}
+
+static int
+usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct usba_ep *ep;
+       struct usba_udc *udc;
+       unsigned long ept_cfg, maxpacket;
+       unsigned int nr_trans;
+
+       ep = container_of(_ep, struct  usba_ep, ep);
+       udc = ep->udc;
+
+       debug("Endpoint enable ep %d\n", ep->index);
+       maxpacket = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff;
+
+       if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index)
+                       || ep->index == 0
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || maxpacket == 0
+                       || maxpacket > ep->fifo_size) {
+               debug("ep_enable: Invalid argument");
+               return -EINVAL;
+       }
+
+       ep->is_isoc = 0;
+       ep->is_in = 0;
+
+       if (maxpacket <= 8)
+               ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
+       else
+               /* LSB is bit 1, not 0 */
+               ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
+
+       debug("%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
+                       ep->ep.name, ept_cfg, maxpacket);
+
+       if ((desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+               ep->is_in = 1;
+               ept_cfg |= USBA_EPT_DIR_IN;
+               debug("%s: is IN endpoint\n", ep->ep.name);
+       }
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               debug("%s: is CTRL endpoint\n", ep->ep.name);
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               debug("%s: is ISOC endpoint\n", ep->ep.name);
+               if (!ep->can_isoc)
+                       return -EINVAL;
+
+
+               /*
+                * Bits 11:12 specify number of _additional_
+                * transactions per microframe.
+                */
+               nr_trans = ((le16_to_cpu(desc->wMaxPacketSize) >> 11) & 3) + 1;
+               if (nr_trans > 3)
+                       return -EINVAL;
+
+               ep->is_isoc = 1;
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
+
+               /*
+                * Do triple-buffering on high-bandwidth iso endpoints.
+                */
+               if (nr_trans > 1 && ep->nr_banks == 3)
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
+               else
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
+               ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               debug("%s: is BULK endpoint\n", ep->ep.name);
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               debug("%s: is INT endpoint\n", ep->ep.name);
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       }
+
+       if (ep->desc) {
+               debug("ep%d already enabled\n", ep->index);
+               return -EBUSY;
+       }
+
+       ep->desc = desc;
+       ep->ep.maxpacket = maxpacket;
+
+       usba_ep_writel(ep, CFG, ept_cfg);
+       debug("ep%d CFG = 0x%lx\n", ep->index, ept_cfg);
+       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+
+       debug("ep%d not using DMA\n", ep->index);
+       usba_writel(udc, INT_ENB, (usba_readl(udc, INT_ENB)
+                                       | USBA_BF(EPT_INT, 1 << ep->index)));
+
+       debug("EPT_CFG%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, CFG));
+       debug("INT_ENB after init: %#08lx\n",
+                       (unsigned long)usba_readl(udc, INT_ENB));
+       debug("INT_STA after init: %#08lx\n",
+                       (unsigned long)usba_readl(udc, INT_STA));
+       debug("EPT_CTL_ENB%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, CTL_ENB));
+       debug("EPT_CTL_DIS%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, CTL_DIS));
+       debug("EPT_CTL%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, CTL));
+       debug("EPT_STA%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, STA));
+       return 0;
+}
+
+static int usba_ep_disable(struct usb_ep *_ep)
+{
+       struct usba_ep *ep;
+       struct usba_udc *udc;
+
+       ep = container_of(_ep, struct usba_ep, ep);
+       udc = ep->udc;
+
+       if (ep == &ep->udc->ep[0])
+               return -EINVAL;
+
+       debug("Endpoint disable ep %d\n", ep->index);
+
+       ep->desc = NULL;
+
+       usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE);
+       usba_writel(udc, INT_ENB,
+                       usba_readl(udc, INT_ENB)
+                       & ~USBA_BF(EPT_INT, 1 << ep->index));
+
+       return 0;
+}
+
+#define REQ_COUNT 8
+#define MAX_REQ (REQ_COUNT-1)
+static struct usba_request req_pool[REQ_COUNT];
+
+static void init_requests(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_REQ; i++)
+               req_pool[i].in_use = 0;
+}
+
+static void free_request(struct usba_request *ptr)
+{
+       if (ptr < &req_pool[0] && ptr > &req_pool[REQ_COUNT]) {
+               debug("%s: ptr 0x%p does not specify valid req\n", \
+                       __func__, ptr);
+               if (!(ptr->in_use))
+                       debug("%s: ptr not marked as \"in_use\"\n", __func__);
+
+               hang();
+       }
+       ptr->in_use = 0;
+}
+
+static struct usba_request *alloc_request(void)
+{
+       int i;
+       struct usba_request *ptr = NULL;
+
+       for (i = 0; i < MAX_REQ; i++) {
+               if (!req_pool[i].in_use) {
+                       ptr = &req_pool[i];
+                       req_pool[i].in_use = 1;
+                       DBG("alloc_req: request[%d]\n", i);
+                       break;
+               }
+       }
+       if (!ptr)
+               DBG("panic: no more free req buffers\n");
+       return ptr;
+}
+
+static struct usb_request *
+usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct usba_request *req;
+
+       req = alloc_request();
+
+       if (!req) {
+               debug("ALLOC REQUEST FAILLED : %s\n", _ep->name);
+               return NULL;
+       }
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+static void usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_request *req;
+
+       debug("FREE request for %s\n", _ep->name);
+       req = container_of(_req, struct usba_request, req);
+
+       free_request(req);
+}
+
+static int
+usba_ep_queue(struct usb_ep *_ep,
+             struct usb_request *_req,
+             gfp_t gfp_flags)
+{
+       struct usba_request *req = to_usba_req(_req);
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       int ret;
+
+       debug("%s: queue req %p, len %u\n",
+                       ep->ep.name, req, _req->length);
+
+       if (!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue)) {
+
+               debug("invalid request\n");
+               if (!_req)
+                       debug("NO REQUEST\n");
+               if (!_req->complete)
+                       debug("NO REQUEST COMPLETE\n");
+               if (!_req->buf)
+                       debug("NO REQUEST BUF\n");
+               if (!list_empty(&req->queue))
+                       debug("NO LIST EMPTY\n");
+               return -EINVAL;
+       }
+
+       if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
+               DBG("invalid ep\n");
+               return -EINVAL;
+       }
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc)
+                       return -ESHUTDOWN;
+
+       req->submitted = 0;
+       req->last_transaction = 0;
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* May have received a reset since last time we checked */
+       ret = -ESHUTDOWN;
+
+       if (ep->desc) {
+               list_add_tail(&req->queue, &ep->queue);
+
+         if ((!ep_is_control(ep) && ep->is_in) ||
+               (ep_is_control(ep) && (ep->state == DATA_STAGE_IN ||
+               ep->state == STATUS_STAGE_IN))) {
+
+               usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+               debug("WE TRANSMITTED DATA ep= %s\n", ep->ep.name);
+         } else {
+               debug("WE RECEIVED OUT DATA ep= %s\n", ep->ep.name);
+               usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+               /*FIXME may be needed, not sure yet */
+               /*usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);*/
+         }
+         ret = 0;
+       }
+       return ret;
+}
+
+static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_ep *ep = container_of(_ep, struct usba_ep, ep);
+       struct usba_request *req = container_of(_req, struct usba_request, req);
+
+       debug("ep_dequeue: %s, req %p\n",
+                       ep->ep.name, req);
+
+       if (!_ep || ep->ep.name == ep0name) {
+               DBG("invalid dequeue request\n");
+               if (!_ep)
+                       debug("NO ENDPOINT\n");
+               if (ep->ep.name == ep0name)
+                       debug("Cannot dequeue on ep0\n");
+               return -EINVAL;
+       }
+       /*
+        * Errors should stop the queue from advancing until the
+        * completion function returns.
+        */
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req)
+               return -EINVAL;
+       request_complete(ep, req, -ECONNRESET);
+
+       /* Process the next request if any */
+       submit_next_request(ep);
+
+       return 0;
+}
+
+static int usba_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct usba_ep *ep = container_of(_ep, struct usba_ep, ep);
+       int ret = 0;
+
+       debug("Endpoint halt\n");
+       if (!ep->desc) {
+               debug("Attempted to halt uninitialized ep %s\n",
+                               ep->ep.name);
+               return -ENODEV;
+       }
+       if (ep->is_isoc) {
+               debug("Attempted to halt isochronous ep %s\n",
+                               ep->ep.name);
+               return -ENOTTY;
+       }
+
+       /*
+        * We can't halt IN endpoints while there are still data to be
+        * transferred
+        */
+       if (!list_empty(&ep->queue)
+                       || ((value && ep->is_in && (usba_ep_readl(ep, STA)
+                                       & USBA_BF(BUSY_BANKS, -1L))))) {
+               ret = -EAGAIN;
+       } else {
+               if (value)
+                       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+               else
+                       usba_ep_writel(ep, CLR_STA,
+                                       USBA_FORCE_STALL | USBA_TOGGLE_CLR);
+               usba_ep_readl(ep, STA);
+       }
+
+       return ret;
+}
+
+static const struct usb_ep_ops usba_ep_ops = {
+       .enable         = usba_ep_enable,
+       .disable        = usba_ep_disable,
+       .alloc_request  = usba_ep_alloc_request,
+       .free_request   = usba_ep_free_request,
+       .queue          = usba_ep_queue,
+       .dequeue        = usba_ep_dequeue,
+       .set_halt       = usba_ep_set_halt,
+};
+
+static int usba_udc_get_frame(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+
+       return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
+}
+
+static int usba_udc_wakeup(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       u32 ctrl;
+       int ret = -EINVAL;
+       debug("UDC wakeup\n");
+
+       if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+               ctrl = usba_readl(udc, CTRL);
+               usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int
+usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       debug("UDC set selfpowered\n");
+       if (is_selfpowered)
+               udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED;
+       else
+               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+       return 0;
+}
+
+static const struct usb_gadget_ops usba_udc_ops = {
+       .get_frame              = usba_udc_get_frame,
+       .wakeup                 = usba_udc_wakeup,
+       .set_selfpowered        = usba_udc_set_selfpowered,
+};
+
+static struct usb_endpoint_descriptor usba_ep0_desc = {
+       .bLength = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType = USB_DT_ENDPOINT,
+       .bEndpointAddress = 0,
+       .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize = __constant_cpu_to_le16(64),
+       /* FIXME: I have no idea what to put here */
+       .bInterval = 1,
+};
+
+static struct usba_udc the_udc = {
+       .regs = (unsigned *) AT91SAM9G45_BASE_UDPHS,
+       .fifo = (unsigned *) AT91SAM9G45_UDPHS_FIFO,
+       .gadget = {
+               .ops    = &usba_udc_ops,
+               .ep0    = &the_udc.ep[0].ep,
+               .is_dualspeed = 1,
+               .name   = driver_name,
+       },
+
+       .ep[0] = {
+               .ep = {
+                       .name   = ep0name,
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 64,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 0,
+               .fifo_size      = 64,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[1] = {
+               .ep = {
+                       .name   = "ep1",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 1,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[2] = {
+               .ep = {
+                       .name   = "ep2",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 2,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[3] = {
+               .ep = {
+                       .name   = "ep3",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 3,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[4] = {
+               .ep = {
+                       .name   = "ep4",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 4,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[5] = {
+               .ep = {
+                       .name   = "ep5",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 5,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+       .ep[6] = {
+               .ep = {
+                       .name   = "ep6",
+                       .ops    = &usba_ep_ops,
+                       .maxpacket      = 1024,
+               },
+               .udc            = &the_udc,
+               .is_pingpong    = 0,
+               .int_mask       = 1 << 6,
+               .fifo_size      = 1024,
+               .nr_banks       = 1,
+               .can_dma        = 0,
+               .can_isoc       = 0,
+       },
+};
+
+static void reset_all_endpoints(struct usba_udc *udc)
+{
+
+       struct usba_ep *ep;
+       struct usba_request *req, *tmp_req;
+       debug("USBA : reset all endpoints\n");
+       usba_writel(udc, EPT_RST, ~0UL);
+
+       ep = container_of(udc->gadget.ep0, struct usba_ep, ep);
+       list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
+               list_del_init(&req->queue);
+               request_complete(ep, req, -ECONNRESET);
+       }
+
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               if (ep->desc)
+                       usba_ep_disable(&ep->ep);
+       }
+}
+
+static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
+{
+       struct usba_ep *ep;
+       debug("get EP by Address\n");
+       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+               return container_of(udc->gadget.ep0, struct usba_ep, ep);
+
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               u8 bEndpointAddress;
+
+               if (!ep->desc)
+                       continue;
+               bEndpointAddress = ep->desc->bEndpointAddress;
+               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+                       continue;
+               if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+                               == (wIndex & USB_ENDPOINT_NUMBER_MASK))
+                       return ep;
+       }
+       return NULL;
+}
+
+/* Called with interrupts disabled and udc->lock held */
+static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep)
+{
+       debug("Set protocol stall\n");
+       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+       ep->state = WAIT_FOR_SETUP;
+}
+
+static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
+{
+       debug("IS STALLED\n");
+       if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL)
+               return 1;
+       return 0;
+}
+
+static inline void set_address(struct usba_udc *udc, unsigned int addr)
+{
+       u32 regval;
+       debug("USBA : set address %d\n", addr);
+       regval = usba_readl(udc, CTRL);
+       regval = USBA_BFINS(DEV_ADDR, addr, regval);
+       usba_writel(udc, CTRL, regval);
+}
+
+/* Avoid overly long expressions */
+static inline char feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
+               return true;
+       return false;
+}
+
+static inline char feature_is_ep_halt(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT))
+               return true;
+       return false;
+}
+
+static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
+               struct usb_ctrlrequest *crq)
+{
+       int retval = 0;
+
+       debug("USBA : EP0 setup\n");
+       switch (crq->bRequest) {
+       case USB_REQ_GET_STATUS: {
+               u16 status;
+               debug("USBA : USB_REQ_GET_STATUS\n");
+               if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
+                       status = cpu_to_le16(udc->devstatus);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_INTERFACE)) {
+                       status =  cpu_to_le16(0);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
+                       struct usba_ep *target;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       status = 0;
+                       if (is_stalled(udc, target))
+                               status |= cpu_to_le16(1);
+               } else {
+                       debug("Delegate : USB_REQ_GET_STATUS\n");
+                       goto delegate;
+               }
+               /* Write directly to the FIFO. No queueing is done. */
+               if (crq->wLength != cpu_to_le16(sizeof(status)))
+                       goto stall;
+               ep->state = DATA_STAGE_IN;
+               debug("Writing to FIFO\n");
+               __raw_writew(status, ep->fifo);
+               usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+               break;
+       }
+
+       case USB_REQ_CLEAR_FEATURE: {
+               debug("USBA : USB_REQ_CLEAR_FEATURE\n");
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_remote_wakeup(crq))
+                               udc->devstatus
+                                       &= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+                       else
+                               /* Can't CLEAR_FEATURE TEST_MODE */
+                               goto stall;
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0)
+                                       || !feature_is_ep_halt(crq))
+                               goto stall;
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL);
+                       if (target->index != 0)
+                               usba_ep_writel(target, CLR_STA,
+                                               USBA_TOGGLE_CLR);
+               } else {
+                       goto delegate;
+               }
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_FEATURE: {
+               debug("USBA :  USB_REQ_SET_FEATURE\n");
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_remote_wakeup(crq))
+                               udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+                       else
+                               goto stall;
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0)
+                                       || !feature_is_ep_halt(crq))
+                               goto stall;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, SET_STA, USBA_FORCE_STALL);
+               } else
+                       goto delegate;
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_ADDRESS:
+               debug("USBA :  USB_REQ_SET_ADDRESS\n");
+               if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
+                       goto delegate;
+
+               set_address(udc, le16_to_cpu(crq->wValue));
+               send_status(udc, ep);
+               ep->state = STATUS_STAGE_ADDR;
+               break;
+
+       default:
+delegate:
+                       debug("deligate SETUP Type = %4x %4x %4x\n",
+                       crq->bRequest,
+                       crq->wValue,
+                       crq->wIndex);
+
+               retval = udc->driver->setup(&udc->gadget, crq);
+       }
+
+       return retval;
+
+stall:
+       debug("udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
+               "halting endpoint...\n",
+               ep->ep.name, crq->bRequestType, crq->bRequest,
+               le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
+               le16_to_cpu(crq->wLength));
+       set_protocol_stall(udc, ep);
+       return -1;
+}
+
+static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+restart:
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       debug("%s [%d]: s/%08x c/%08x\n",
+                       ep->ep.name, ep->state, epstatus, epctrl);
+
+       req = NULL;
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+       if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               debug("usba_control_irq : USBA_TX_PK_RDY\n");
+               if (req->submitted)
+                       next_fifo_transaction(ep, req);
+               else
+                 submit_request(ep, req);
+
+               if (req->last_transaction) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+               }
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_TX_COMPLETE) {
+               debug("usba_control_irq : USBA_TX_COMPLETE\n");
+               usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE);
+
+               switch (ep->state) {
+               case DATA_STAGE_IN:
+                       debug("USBA : DATA Stage in\n");
+                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = STATUS_STAGE_OUT;
+                       break;
+               case STATUS_STAGE_ADDR:
+                       debug("USBA : Status stage addr\n");
+                       /* Activate our new address */
+                       usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
+                                               | USBA_FADDR_EN));
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_IN:
+                       debug("USBA : Status stage in\n");
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, 0);
+                               submit_next_request(ep);
+                       }
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_TEST:
+                       debug("USBA : test mode not supported\n");
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               default:
+                       debug("udc: %s: TXRDY: Invalid endpoint state %d, "
+                               "halting endpoint...\n",
+                               ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               debug("USBA : USBA_RX_BK_RDY\n");
+               switch (ep->state) {
+               case STATUS_STAGE_OUT:
+                       debug("%s : USBA :STATUS_STAGE_OUT\n", ep->ep.name);
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               debug("%s :USBA:request complete\n",
+                                     ep->ep.name);
+                               request_complete(ep, req, 0);
+                       }
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+
+               case DATA_STAGE_OUT:
+                       debug("%s : DATA STAGE OUT\n", ep->ep.name);
+                       receive_data(ep);
+                       break;
+
+               default:
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       debug("udc: %s: RXRDY: Invalid endpoint state %d, "
+                               "halting endpoint...\n",
+                               ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if (epstatus & USBA_RX_SETUP) {
+               debug("USBA : USBA_RX_SETUP\n");
+               union {
+                       struct usb_ctrlrequest crq;
+                       unsigned long data[2];
+               } crq;
+               unsigned int pkt_len;
+               int ret;
+
+               if (ep->state != WAIT_FOR_SETUP) {
+                       /*
+                        * Didn't expect a SETUP packet at this
+                        * point. Clean up any pending requests (which
+                        * may be successful).
+                        */
+                       int status = -EPROTO;
+
+                       /*
+                        * RXRDY and TXCOMP are dropped when SETUP
+                        * packets arrive.  Just pretend we received
+                        * the status packet.
+                        */
+                       if (ep->state == STATUS_STAGE_OUT
+                                       || ep->state == STATUS_STAGE_IN) {
+                               debug("DROPPING DATA %s\n", ep->ep.name);
+                               usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                               status = 0;
+                       }
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, status);
+                       }
+               }
+
+               pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
+               debug("Packet length: %u\n", pkt_len);
+               if (pkt_len != sizeof(crq)) {
+                       debug("udc: Invalid packet length %u "
+                               "(expected %zu)\n", pkt_len, sizeof(crq));
+                       set_protocol_stall(udc, ep);
+                       return;
+               }
+
+               debug("Copying ctrl request from 0x%p:\n", ep->fifo);
+               memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
+
+               /* Free up one bank in the FIFO so that we can
+                * generate or receive a reply right away. */
+               usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP);
+
+               if (crq.crq.bRequestType & USB_DIR_IN) {
+                       /*
+                        * The USB 2.0 spec states that "if wLength is
+                        * zero, there is no data transfer phase."
+                        * However, testusb #14 seems to actually
+                        * expect a data phase even if wLength = 0...
+                        */
+                       ep->state = DATA_STAGE_IN;
+               } else {
+                       if (crq.crq.wLength != cpu_to_le16(0))
+                               ep->state = DATA_STAGE_OUT;
+                       else
+                               ep->state = STATUS_STAGE_IN;
+               }
+
+               ret = -1;
+               if (ep->index == 0)
+                       ret = handle_ep0_setup(udc, ep, &crq.crq);
+               else {
+                       debug("driver setup %d %d\n",
+                               crq.crq.wIndex, crq.crq.wValue);
+                       ret = udc->driver->setup(&udc->gadget, &crq.crq);
+               }
+
+               if (ret < 0) {
+                       /* Let the host know that we failed */
+                       set_protocol_stall(udc, ep);
+               }
+       }
+}
+
+static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               debug("%s: TX PK ready\n", ep->ep.name);
+
+               if (list_empty(&ep->queue)) {
+                       debug("ep_irq: queue empty\n");
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       return;
+               }
+
+               req = list_entry(ep->queue.next, struct usba_request, queue);
+
+               if (req->submitted) {
+                       debug("TX next trans %s\n", ep->ep.name);
+                       next_fifo_transaction(ep, req);
+               } else {
+                       debug("TX submit %s\n", ep->ep.name);
+                       submit_request(ep, req);
+               }
+               if (req->last_transaction) {
+                       debug("last transaction %s\n", ep->ep.name);
+                       list_del_init(&req->queue);
+                       submit_next_request(ep);
+                       request_complete(ep, req, 0);
+               }
+
+               epstatus = usba_ep_readl(ep, STA);
+               epctrl = usba_ep_readl(ep, CTL);
+       }
+       debug("%s status = %lx\n", ep->ep.name, epstatus);
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               debug("%s RX data ready\n", ep->ep.name);
+               receive_data(ep);
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+       }
+}
+
+int usb_gadget_handle_interrupts(void)
+{
+       struct usba_udc *udc = &the_udc;
+       u32 status;
+       u32 ep_status;
+
+       status = usba_readl(udc, INT_STA);
+       debug("irq, status=%#08x\n", status);
+
+       if (status & USBA_DET_SUSPEND) {
+               debug("USBA : USBA_DET_SUSPEND\n");
+               usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver && udc->driver->suspend) {
+                       udc->driver->suspend(&udc->gadget);
+               }
+       }
+
+       if (status & USBA_WAKE_UP) {
+               debug("USBA : USBA_WAKE_UP\n");
+               usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+       }
+
+       if (status & USBA_END_OF_RESUME) {
+               debug("USBA : USBA_END_OF_RESUME\n");
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESUME);
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver && udc->driver->resume) {
+                       udc->driver->resume(&udc->gadget);
+               }
+       }
+
+       ep_status = USBA_BFEXT(EPT_INT, status);
+       if (ep_status) {
+               int i;
+
+               for (i = 0; i < USBA_NR_ENDPOINTS; i++)
+                       if (ep_status & (1 << i)) {
+                               if (ep_is_control(&udc->ep[i])) {
+                                       debug("EP %d = control\n", i);
+                                       usba_control_irq(udc, &udc->ep[i]);
+                               } else {
+                                       debug("EP = %d\n", i);
+                                       usba_ep_irq(udc, &udc->ep[i]);
+                               }
+                       }
+       }
+
+       if (status & USBA_END_OF_RESET) {
+               struct usba_ep *ep0;
+               debug("USBA : USBA_END_OF_RESET\n");
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
+               reset_all_endpoints(udc);
+
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver->disconnect) {
+                       udc->gadget.speed = USB_SPEED_UNKNOWN;
+                       udc->driver->disconnect(&udc->gadget);
+               }
+
+               if (status & USBA_HIGH_SPEED) {
+                       debug("USBA : High speed\n");
+                       udc->gadget.speed = USB_SPEED_HIGH;
+               } else {
+                       debug("USBA : Full speed\n");
+                       udc->gadget.speed = USB_SPEED_FULL;
+               }
+
+               ep0 = &udc->ep[0];
+               ep0->desc = &usba_ep0_desc;
+               ep0->state = WAIT_FOR_SETUP;
+               usba_ep_writel(ep0, CFG,
+                               (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
+                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
+                               | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
+               usba_ep_writel(ep0, CTL_ENB,
+                               USBA_EPT_ENABLE | USBA_RX_SETUP);
+               usba_writel(udc, INT_ENB,
+                               (usba_readl(udc, INT_ENB)
+                               | USBA_BF(EPT_INT, 1)
+                               | USBA_DET_SUSPEND
+                               | USBA_END_OF_RESUME));
+
+               /*
+                * Unclear why we hit this irregularly, e.g. in usbtest,
+                * but it's clearly harmless...
+               */
+               if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) {
+                       ERR("ODD: EP0 configuration is invalid!\n");
+                       debug("ERROR : ep0 config invalid\n");
+               }
+               debug("USBA : USBA_END_OF_RESET - finished\n");
+       }
+       return IRQ_HANDLED;
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct usba_udc *udc = &the_udc;
+
+       if (!driver)
+               return -ENODEV;
+       if (driver != udc->driver || !driver->unbind)
+               return -EINVAL;
+
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       reset_all_endpoints(udc);
+
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+       if (udc->driver->disconnect)
+               udc->driver->disconnect(&udc->gadget);
+
+       driver->unbind(&udc->gadget);
+       udc->driver = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct usba_udc *udc = &the_udc;
+       int             retval = -1;
+
+       debug("USBA : registering driver\n");
+
+       if (udc->driver) {
+               debug("UDC already has a gadget driver\n");
+               return -EBUSY;
+       }
+
+       udc->driver = driver;
+
+       if (udc->driver)
+               retval = driver->bind(&udc->gadget);
+
+       if (retval) {
+               debug("driver->bind() returned %d\n", retval);
+               udc->driver = NULL;
+               return retval;
+       }
+
+       debug("Enabling controller\n");
+       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+       usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+
+       debug("USBA register finished\n");
+       return 0;
+}
+
+/* reinit == restore inital software state */
+static void udc_reinit(struct usba_udc *udc)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+       for (i = 0; i < USBA_NR_ENDPOINTS; i++) {
+               struct usba_ep *ep = &udc->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+               ep->desc = NULL;
+               ep->stopped = 0;
+               ep->fifo_bank = 0;
+               ep->ep.maxpacket = ep->maxpacket;
+               ep->ep_regs = (void __iomem *) udc->regs + USBA_EPT_BASE(i);
+               INIT_LIST_HEAD(&ep->queue);
+       }
+}
+
+int usba_udc_probe(struct platform_data *pdata)
+{
+       struct usba_udc *udc;
+       int  i;
+       /* needed to disable DMA */
+       at91_pmc_t *pmc = (at91_pmc_t *)AT91_PMC_BASE;
+       u32 regvalue;
+
+       udc = &the_udc;
+       udc->regs = (unsigned *) AT91SAM9G45_BASE_UDPHS;
+       udc->fifo = (unsigned *) AT91SAM9G45_UDPHS_FIFO;
+
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+       debug("USBA : Probing USB controller\n");
+       writel(readl(&pmc->pcer) | (1 << AT91SAM9G45_ID_UDPHS), &pmc->pcer);
+       writel(readl(&pmc->uckr) |
+               AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+
+       debug("USBA : Enable controller\n");
+       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+       usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+
+       init_requests();
+       udc_reinit(udc);
+
+       the_udc.gadget.ep0 = &udc->ep[0].ep;
+
+       udc->ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
+       udc->ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
+       udc->ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
+       udc->ep[0].ep.ops = &usba_ep_ops;
+       udc->ep[0].ep.name = the_udc.ep[0].ep.name;
+       udc->ep[0].ep.maxpacket =  64;
+       udc->ep[0].udc = &the_udc;
+       udc->ep[0].fifo_size = 64;
+       udc->ep[0].nr_banks = the_udc.ep[0].nr_banks;
+       udc->ep[0].index = 0;
+       udc->ep[0].is_pingpong = 0;
+       udc->ep[0].can_isoc = 0;
+       udc->ep[0].can_dma = 0;
+
+       for (i = 1; i < USBA_NR_ENDPOINTS; i++) {
+               struct usba_ep *ep = &udc->ep[i];
+
+               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+               ep->ep.ops = &usba_ep_ops;
+               ep->ep.name = the_udc.ep[i].ep.name;
+               ep->ep.maxpacket = 1024;
+               ep->udc = &the_udc;
+               ep->fifo_size = 1024;
+               ep->index = i;
+               if ((i == 1) || (i == 2)) {
+                       ep->nr_banks = 1;
+                       ep->is_pingpong = 0;
+               } else {
+                       ep->nr_banks = 1;
+                       ep->is_pingpong = 0;
+               }
+               ep->can_isoc = 0;
+               ep->can_dma = 0;
+       }
+
+       /* This code disables DMA : see g45 spec */
+       regvalue = usba_readl(udc, CTRL);
+       usba_writel(udc, CTRL, (regvalue & ~AT91C_UDPHS_EN_UDPHS));
+       usba_writel(udc, CTRL, (regvalue | AT91C_UDPHS_EN_UDPHS));
+
+       regvalue = usba_readl(udc, CTRL);
+       debug("UDPHS_CTRL after reset 0x%lx\n", regvalue);
+       for (i = 1; i <= (((AT91SAM9G45_BASE_UDPHS + UDPHS_IPFEATURES) &
+                       AT91C_UDPHS_DMA_CHANNEL_NBR) >> 4); i++) {
+               debug("UDPHS ep %d disable DMA\n", i);
+               /* DMA stop channel command */
+               __raw_writel(0x00,
+                       AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMACONTROL);
+               /* Disable endpoint */
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       0x100 + (0x20*i) + UDPHS_EPTCTLDIS);
+               __raw_writel((regvalue | 0XFFFFFFFF),
+                       AT91SAM9G45_BASE_UDPHS +
+                       0x100 + (0x20*i) + UDPHS_EPTCTLDIS);
+               /* Reset endpoint config */
+               __raw_writel(0x00,
+                       AT91SAM9G45_BASE_UDPHS +
+                       0x100 + (0x20*i) + UDPHS_EPTCFG);
+               /* Reset DMA channel (Buff count and Control field) */
+               __raw_writel(0x02,
+                       AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMACONTROL);
+               /* DMA stop channel command */
+               __raw_writel(0x00,
+                       AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMACONTROL);
+               /* Clear DMA channel status (read register to clear it) */
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMASTATUS);
+               __raw_writel(regvalue,
+                       AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMASTATUS);
+
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMACONTROL);
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       0x100 + (0x20*i) + UDPHS_EPTCTLDIS);
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       0x100 + (0x20*i) + UDPHS_EPTCFG);
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS +
+                       (UDPHS_DMA + 0x10*i) + UDPHS_DMASTATUS);
+               regvalue = readl(AT91SAM9G45_BASE_UDPHS + 0xF0);
+       }
+       debug("USBA : Probing finished\n");
+       return 0;
+}
+
+MODULE_DESCRIPTION("Atmel usba udc driver");
+MODULE_AUTHOR("Marcel Janssen");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_usba_udc");
+
diff --git a/include/usb/atmel_usba_udc.h b/include/usb/atmel_usba_udc.h
new file mode 100644
index 0000000..b165003
--- /dev/null
+++ b/include/usb/atmel_usba_udc.h
@@ -0,0 +1,398 @@
+/*
+ * Driver for the Atmel USBA high speed USB device controller
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_USB_GADGET_USBA_UDC_H__
+#define __LINUX_USB_GADGET_USBA_UDC_H__
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/list.h>
+
+#define __iomem
+
+/* USB register offsets */
+#define USBA_CTRL                              0x0000
+#define USBA_FNUM                              0x0004
+#define USBA_INT_ENB                           0x0010
+#define USBA_INT_STA                           0x0014
+#define USBA_INT_CLR                           0x0018
+#define USBA_EPT_RST                           0x001c
+#define USBA_TST                               0x00e0
+
+/* USB endpoint register offsets */
+#define USBA_EPT_CFG                           0x0000
+#define USBA_EPT_CTL_ENB                       0x0004
+#define USBA_EPT_CTL_DIS                       0x0008
+#define USBA_EPT_CTL                           0x000c
+#define USBA_EPT_SET_STA                       0x0014
+#define USBA_EPT_CLR_STA                       0x0018
+#define USBA_EPT_STA                           0x001c
+
+/* USB DMA register offsets */
+#define USBA_DMA_NXT_DSC                       0x0000
+#define USBA_DMA_ADDRESS                       0x0004
+#define USBA_DMA_CONTROL                       0x0008
+#define USBA_DMA_STATUS                                0x000c
+
+/* Bitfields in CTRL */
+#define USBA_DEV_ADDR_OFFSET                   0
+#define USBA_DEV_ADDR_SIZE                     7
+#define USBA_FADDR_EN                          (1 <<  7)
+#define USBA_EN_USBA                           (1 <<  8)
+#define USBA_DETACH                            (1 <<  9)
+#define USBA_REMOTE_WAKE_UP                    (1 << 10)
+#define USBA_PULLD_DIS                         (1 << 11)
+
+#if defined(CONFIG_AVR32)
+#define USBA_ENABLE_MASK                       USBA_EN_USBA
+#define USBA_DISABLE_MASK                      0
+#elif defined(CONFIG_ARCH_AT91)
+#define USBA_ENABLE_MASK                       (USBA_EN_USBA | USBA_PULLD_DIS)
+#define USBA_DISABLE_MASK                      USBA_DETACH
+#endif /* CONFIG_ARCH_AT91 */
+
+/* Bitfields in FNUM */
+#define USBA_MICRO_FRAME_NUM_OFFSET            0
+#define USBA_MICRO_FRAME_NUM_SIZE              3
+#define USBA_FRAME_NUMBER_OFFSET               3
+#define USBA_FRAME_NUMBER_SIZE                 11
+#define USBA_FRAME_NUM_ERROR                   (1 << 31)
+
+/* Bitfields in INT_ENB/INT_STA/INT_CLR */
+#define USBA_HIGH_SPEED                                (1 <<  0)
+#define USBA_DET_SUSPEND                       (1 <<  1)
+#define USBA_MICRO_SOF                         (1 <<  2)
+#define USBA_SOF                               (1 <<  3)
+#define USBA_END_OF_RESET                      (1 <<  4)
+#define USBA_WAKE_UP                           (1 <<  5)
+#define USBA_END_OF_RESUME                     (1 <<  6)
+#define USBA_UPSTREAM_RESUME                   (1 <<  7)
+#define USBA_EPT_INT_OFFSET                    8
+#define USBA_EPT_INT_SIZE                      16
+#define USBA_DMA_INT_OFFSET                    24
+#define USBA_DMA_INT_SIZE                      8
+
+/* Bitfields in EPT_RST */
+#define USBA_RST_OFFSET                                0
+#define USBA_RST_SIZE                          16
+
+/* Bitfields in USBA_TST */
+#define USBA_SPEED_CFG_OFFSET                  0
+#define USBA_SPEED_CFG_SIZE                    2
+#define USBA_TST_J_MODE                                (1 <<  2)
+#define USBA_TST_K_MODE                                (1 <<  3)
+#define USBA_TST_PKT_MODE                      (1 <<  4)
+#define USBA_OPMODE2                           (1 <<  5)
+
+/* Bitfields in EPT_CFG */
+#define USBA_EPT_SIZE_OFFSET                   0
+#define USBA_EPT_SIZE_SIZE                     3
+#define USBA_EPT_DIR_IN                                (1 <<  3)
+#define USBA_EPT_TYPE_OFFSET                   4
+#define USBA_EPT_TYPE_SIZE                     2
+#define USBA_BK_NUMBER_OFFSET                  6
+#define USBA_BK_NUMBER_SIZE                    2
+#define USBA_NB_TRANS_OFFSET                   8
+#define USBA_NB_TRANS_SIZE                     2
+#define USBA_EPT_MAPPED                                (1 << 31)
+
+/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */
+#define USBA_EPT_ENABLE                                (1 <<  0)
+#define USBA_AUTO_VALID                                (1 <<  1)
+#define USBA_INTDIS_DMA                                (1 <<  3)
+#define USBA_NYET_DIS                          (1 <<  4)
+#define USBA_DATAX_RX                          (1 <<  6)
+#define USBA_MDATA_RX                          (1 <<  7)
+/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */
+#define USBA_BUSY_BANK_IE                      (1 << 18)
+
+/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */
+#define USBA_FORCE_STALL                       (1 <<  5)
+#define USBA_TOGGLE_CLR                                (1 <<  6)
+#define USBA_TOGGLE_SEQ_OFFSET                 6
+#define USBA_TOGGLE_SEQ_SIZE                   2
+#define USBA_ERR_OVFLW                         (1 <<  8)
+#define USBA_RX_BK_RDY                         (1 <<  9)
+#define USBA_KILL_BANK                         (1 <<  9)
+#define USBA_TX_COMPLETE                       (1 << 10)
+#define USBA_TX_PK_RDY                         (1 << 11)
+#define USBA_ISO_ERR_TRANS                     (1 << 11)
+#define USBA_RX_SETUP                          (1 << 12)
+#define USBA_ISO_ERR_FLOW                      (1 << 12)
+#define USBA_STALL_SENT                                (1 << 13)
+#define USBA_ISO_ERR_CRC                       (1 << 13)
+#define USBA_ISO_ERR_NBTRANS                   (1 << 13)
+#define USBA_NAK_IN                            (1 << 14)
+#define USBA_ISO_ERR_FLUSH                     (1 << 14)
+#define USBA_NAK_OUT                           (1 << 15)
+#define USBA_CURRENT_BANK_OFFSET               16
+#define USBA_CURRENT_BANK_SIZE                 2
+#define USBA_BUSY_BANKS_OFFSET                 18
+#define USBA_BUSY_BANKS_SIZE                   2
+#define USBA_BYTE_COUNT_OFFSET                 20
+#define USBA_BYTE_COUNT_SIZE                   11
+#define USBA_SHORT_PACKET                      (1 << 31)
+
+/* Bitfields in DMA_CONTROL */
+#define USBA_DMA_CH_EN                         (1 <<  0)
+#define USBA_DMA_LINK                          (1 <<  1)
+#define USBA_DMA_END_TR_EN                     (1 <<  2)
+#define USBA_DMA_END_BUF_EN                    (1 <<  3)
+#define USBA_DMA_END_TR_IE                     (1 <<  4)
+#define USBA_DMA_END_BUF_IE                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_IE                  (1 <<  6)
+#define USBA_DMA_BURST_LOCK                    (1 <<  7)
+#define USBA_DMA_BUF_LEN_OFFSET                        16
+#define USBA_DMA_BUF_LEN_SIZE                  16
+
+/* Bitfields in DMA_STATUS */
+#define USBA_DMA_CH_ACTIVE                     (1 <<  1)
+#define USBA_DMA_END_TR_ST                     (1 <<  4)
+#define USBA_DMA_END_BUF_ST                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_ST                  (1 <<  6)
+
+/* Constants for SPEED_CFG */
+#define USBA_SPEED_CFG_NORMAL                  0
+#define USBA_SPEED_CFG_FORCE_HIGH              2
+#define USBA_SPEED_CFG_FORCE_FULL              3
+
+/* Constants for EPT_SIZE */
+#define USBA_EPT_SIZE_8                                0
+#define USBA_EPT_SIZE_16                       1
+#define USBA_EPT_SIZE_32                       2
+#define USBA_EPT_SIZE_64                       3
+#define USBA_EPT_SIZE_128                      4
+#define USBA_EPT_SIZE_256                      5
+#define USBA_EPT_SIZE_512                      6
+#define USBA_EPT_SIZE_1024                     7
+
+/* Constants for EPT_TYPE */
+#define USBA_EPT_TYPE_CONTROL                  0
+#define USBA_EPT_TYPE_ISO                      1
+#define USBA_EPT_TYPE_BULK                     2
+#define USBA_EPT_TYPE_INT                      3
+
+/* Constants for BK_NUMBER */
+#define USBA_BK_NUMBER_ZERO                    0
+#define USBA_BK_NUMBER_ONE                     1
+#define USBA_BK_NUMBER_DOUBLE                  2
+#define USBA_BK_NUMBER_TRIPLE                  3
+
+/* Bit manipulation macros */
+#define USBA_BF(name, value)                                   \
+       (((value) & ((1 << USBA_##name##_SIZE) - 1))            \
+        << USBA_##name##_OFFSET)
+#define USBA_BFEXT(name, value)                                        \
+       (((value) >> USBA_##name##_OFFSET)                      \
+        & ((1 << USBA_##name##_SIZE) - 1))
+#define USBA_BFINS(name, value, old)                           \
+       (((old) & ~(((1 << USBA_##name##_SIZE) - 1)             \
+                   << USBA_##name##_OFFSET))                   \
+        | USBA_BF(name, value))
+
+/* Register access macros */
+#define usba_readl(udc, reg)                                   \
+       __raw_readl((udc)->regs + USBA_##reg)
+#define usba_writel(udc, reg, value)                           \
+       __raw_writel((value), (udc)->regs + USBA_##reg)
+#define usba_ep_readl(ep, reg)                                 \
+       __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
+#define usba_ep_writel(ep, reg, value)                         \
+       __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
+#define usba_dma_readl(ep, reg)                                        \
+       __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
+#define usba_dma_writel(ep, reg, value)                                \
+       __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
+
+/* Calculate base address for a given endpoint or DMA controller */
+#define USBA_EPT_BASE(x)       (0x100 + (x) * 0x20)
+#define USBA_DMA_BASE(x)       (0x300 + (x) * 0x10)
+#define USBA_FIFO_BASE(x)      ((x) << 16)
+
+/* Synth parameters */
+#define USBA_NR_ENDPOINTS      7
+
+#define EP0_FIFO_SIZE          64
+#define EP0_EPT_SIZE           USBA_EPT_SIZE_64
+#define EP0_NR_BANKS           1
+
+/*
+ * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
+ * provide this information?
+ */
+#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+#define FIFO_IOMEM_ID  0
+#define CTRL_IOMEM_ID  1
+
+#define DBG_ERR                0x0001  /* report all error returns */
+#define DBG_HW         0x0002  /* debug hardware initialization */
+#define DBG_GADGET     0x0004  /* calls to/from gadget driver */
+#define DBG_INT                0x0008  /* interrupts */
+#define DBG_BUS                0x0010  /* report changes in bus state */
+#define DBG_QUEUE      0x0020  /* debug request queue processing */
+#define DBG_FIFO       0x0040  /* debug FIFO contents */
+#define DBG_DMA                0x0080  /* debug DMA handling */
+#define DBG_REQ                0x0100  /* print out queued request length */
+#define DBG_ALL                0xffff
+#define DBG_NONE       0x0000
+
+#define DEBUG_LEVEL    (DBG_ERR)
+
+enum usba_ctrl_state {
+       WAIT_FOR_SETUP,
+       DATA_STAGE_IN,
+       DATA_STAGE_OUT,
+       STATUS_STAGE_IN,
+       STATUS_STAGE_OUT,
+       STATUS_STAGE_ADDR,
+       STATUS_STAGE_TEST,
+};
+
+struct usba_ep {
+       int                             state;
+       struct usb_ep                   ep;
+       struct list_head                queue;
+       struct usba_udc                 *udc;
+       void __iomem                    *fifo;
+       void __iomem                    *dma_regs;
+       void __iomem                    *ep_regs;
+
+       unsigned                        maxpacket:16;
+       u8                              int_mask;
+       unsigned                        is_pingpong:1;
+       u8                              index;
+       u16                             fifo_size;
+       u8                              nr_banks;
+       unsigned                        stopped:1;
+       unsigned int                    can_dma:1;
+       unsigned int                    can_isoc:1;
+       unsigned                        is_in:1;
+       unsigned                        is_isoc:1;
+       unsigned                        fifo_bank:1;
+
+       const struct usb_endpoint_descriptor    *desc;
+};
+
+struct usba_request {
+       struct usb_request              req;
+       struct list_head                queue;
+       unsigned int                    last_transaction:1;
+       unsigned int                    submitted:1;
+       unsigned                        in_use;
+};
+
+/* USB Device */
+struct usba_udc_data {
+       u8      vbus_pin;               /* high == host powering us */
+       u8      pullup_pin;             /* high == D+ pulled up */
+};
+
+struct platform_data {
+       struct usba_udc_data    board;
+       unsigned                udc_clk;
+};
+
+/*
+ * driver is non-SMP, and just blocks IRQs whenever it needs
+ * access protection for chip registers or driver state
+ */
+
+struct usba_udc {
+       void __iomem *regs;
+       void __iomem *fifo;
+       struct usb_gadget               gadget;
+       struct usba_ep                  ep[USBA_NR_ENDPOINTS];
+       struct usb_gadget_driver        *driver;
+       struct usba_udc_data            board;
+       unsigned                        vbus:1;
+       int irq;
+       int vbus_pin;
+       struct clk *pclk;
+       struct clk *hclk;
+       u16 devstatus;
+       int vbus_prev;
+};
+
+static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct usba_ep, ep);
+}
+
+static inline struct usba_request *to_usba_req(struct usb_request *req)
+{
+       return container_of(req, struct usba_request, req);
+}
+
+static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct usba_udc, gadget);
+}
+
+int usba_udc_probe(struct platform_data *pdata);
+
+#define ep_is_control(ep)      ((ep)->index == 0)
+#define ep_is_idle(ep)         ((ep)->state == EP_STATE_IDLE)
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define DBG (stuff...)         printf("udc: " stuff)
+#else
+#define DBG (stuff...)         do {} while (0)
+#endif
+
+#ifdef VERBOSE
+#define VDBG(x...)     printf(x)
+#else
+#define VDBG(stuff...) do {} while (0)
+#endif
+
+#ifdef PACKET_TRACE
+#    define PACKET             VDBG
+#else
+#    define PACKET(stuff...)   do {} while (0)
+#endif
+
+#define ERR(stuff...)          printf("ERR udc: " stuff)
+#define WARN(stuff...)         printf("WARNING udc: " stuff)
+#define INFO(stuff...)         printf("INFO udc: " stuff)
+
+/* following defines come form At91Bootstrap.
+ * They're needed for disabling DMA for the USB device controller
+ */
+#define UDPHS_CTRL                     (0)
+#define AT91C_UDPHS_EN_UDPHS           (0x1 <<  8)
+#define UDPHS_IPFEATURES               (248)
+#define AT91C_UDPHS_DMA_CHANNEL_NBR    (0x7 <<  4)
+#define UDPHS_DMACONTROL               (8)
+#define UDPHS_EPT                      (256)
+#define AT91C_BASE_UDPHS_EPT_0         (0xFFF78100)
+#define UDPHS_EPTCTLDIS                        (8)
+#define UDPHS_EPTCFG                   (0)
+#define UDPHS_EPTCTL                   (12)
+#define UDPHS_DMA                      (768)
+#define AT91C_BASE_UDPHS_DMA_1         (0xFFF78310)
+#define AT91C_BASE_UDPHS_DMA_1         (0xFFF78310)
+#define AT91C_BASE_UDPHS_DMA_2         (0xFFF78320)
+#define AT91C_BASE_UDPHS_DMA_3         (0xFFF78330)
+#define AT91C_BASE_UDPHS_DMA_4         (0xFFF78340)
+#define AT91C_BASE_UDPHS_DMA_5         (0xFFF78350)
+#define AT91C_BASE_UDPHS_DMA_6         (0xFFF78360)
+#define UDPHS_DMASTATUS                        (12)
+#define AT91C_BASE_UDPHS_EPTFIFO       (0x00600000)
+#define AT91C_UDPHS_EPTFIFO_READEPT3   (0x00630000)
+#define AT91C_UDPHS_EPTFIFO_READEPT5   (0x00650000)
+#define AT91C_UDPHS_EPTFIFO_READEPT1   (0x00610000)
+#define AT91C_UDPHS_EPTFIFO_READEPT0   (0x00600000)
+#define AT91C_UDPHS_EPTFIFO_READEPT6   (0x00660000)
+#define AT91C_UDPHS_EPTFIFO_READEPT2   (0x00620000)
+#define AT91C_UDPHS_EPTFIFO_READEPT4   (0x00640000)
+
+#endif /* __LINUX_USB_GADGET_USBA_UDC_H */
-- 
1.7.3.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to