--- /dev/null
+/*
+ * Handles the Intel 27x USB Device Controller (UDC)
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+
+#include <asm/byteorder.h>
+#include <asm/hardware.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include <asm/arch/udc.h>
+
+#include "pxa27x_udc.h"
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x
+ * series processors.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces.  The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol. The
+ * biggest issues are:  that the endpoints have to be set up before the
+ * controller can be enabled (minor, and not uncommon); and each endpoint
+ * can only have one configuration, interface and alternative interface
+ * number (major, and very unusual). Once set up, these cannot be changed
+ * without a controller reset.
+ *
+ * The workaround is to setup all combinations necessary for the gadgets which
+ * will work with this driver. This is done in pxa_udc structure, statically.
+ * See pxa_udc, udc_usb_ep versus pxa_ep, and matching function find_pxa_ep.
+ * (You could modify this if needed.  Some drivers have a "fifo_mode" module
+ * parameter to facilitate such changes.)
+ *
+ * The combinations have been tested with these gadgets :
+ *  - zero gadget
+ *  - file storage gadget
+ *  - ether gadget
+ *
+ * The driver doesn't use DMA, only IO access and IRQ callbacks. No use is
+ * made of UDC's double buffering either. USB "On-The-Go" is not implemented.
+ *
+ * All the requests are handled the same way :
+ *  - the drivers tries to handle the request directly to the IO
+ *  - if the IO fifo is not big enough, the remaining is send/received in
+ *    interrupt handling.
+ */
+
+#define        DRIVER_VERSION  "2008-04-18"
+#define        DRIVER_DESC     "PXA 27x USB Device Controller driver"
+
+static const char driver_name[] = "pxa27x_udc";
+static struct pxa_udc *the_controller;
+
+static void handle_ep(struct pxa_ep *ep);
+
+/*
+ * Debug filesystem
+ */
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+
+static int state_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       int pos = 0, ret;
+       u32 tmp;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       /* basic device status */
+       pos += seq_printf(s, DRIVER_DESC "\n"
+                        "%s version: %s\nGadget driver: %s\n",
+                        driver_name, DRIVER_VERSION,
+                        udc->driver ? udc->driver->driver.name : "(none)");
+
+       tmp = udc_readl(udc, UDCCR);
+       pos += seq_printf(s,
+                        "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), "
+                        "con=%d,inter=%d,altinter=%d\n", tmp,
+                        (tmp & UDCCR_OEN) ? " oen":"",
+                        (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
+                        (tmp & UDCCR_AHNP) ? " rem" : "",
+                        (tmp & UDCCR_BHNP) ? " rstir" : "",
+                        (tmp & UDCCR_DWRE) ? " dwre" : "",
+                        (tmp & UDCCR_SMAC) ? " smac" : "",
+                        (tmp & UDCCR_EMCE) ? " emce" : "",
+                        (tmp & UDCCR_UDR) ? " udr" : "",
+                        (tmp & UDCCR_UDA) ? " uda" : "",
+                        (tmp & UDCCR_UDE) ? " ude" : "",
+                        (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
+                        (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
+                        (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
+       /* registers for device and ep0 */
+       pos += seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
+                       udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
+       pos += seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
+                       udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
+       pos += seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
+       pos += seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, "
+                       "reconfig=%lu\n",
+                       udc->stats.irqs_reset, udc->stats.irqs_suspend,
+                       udc->stats.irqs_resume, udc->stats.irqs_reconfig);
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int queues_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       struct pxa_ep *ep;
+       struct pxa27x_request *req;
+       int pos = 0, i, maxpkt, ret;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       /* dump endpoint queues */
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               maxpkt = ep->fifo_size;
+               pos += seq_printf(s,  "%-12s max_pkt=%d %s\n",
+                               EPNAME(ep), maxpkt, "pio");
+
+               if (list_empty(&ep->queue)) {
+                       pos += seq_printf(s, "\t(nothing queued)\n");
+                       continue;
+               }
+
+               list_for_each_entry(req, &ep->queue, queue) {
+                       pos += seq_printf(s,  "\treq %p len %d/%d buf %p\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf);
+               }
+       }
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int eps_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       struct pxa_ep *ep;
+       int pos = 0, i, ret;
+       u32 tmp;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       ep = &udc->pxa_ep[0];
+       tmp = udc_ep_readl(ep, UDCCSR);
+       pos += seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n", tmp,
+                        (tmp & UDCCSR0_SA) ? " sa" : "",
+                        (tmp & UDCCSR0_RNE) ? " rne" : "",
+                        (tmp & UDCCSR0_FST) ? " fst" : "",
+                        (tmp & UDCCSR0_SST) ? " sst" : "",
+                        (tmp & UDCCSR0_DME) ? " dme" : "",
+                        (tmp & UDCCSR0_IPR) ? " ipr" : "",
+                        (tmp & UDCCSR0_OPC) ? " opc" : "");
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               tmp = i? udc_ep_readl(ep, UDCCR) : udc_readl(udc, UDCCR);
+               pos += seq_printf(s, "%-12s: "
+                               "IN %lu(%lu reqs), OUT %lu(%lu reqs), "
+                               "irqs=%lu, udccr=0x%08x, udccsr=0x%03x, "
+                               "udcbcr=%d\n",
+                               EPNAME(ep),
+                               ep->stats.in_bytes, ep->stats.in_ops,
+                               ep->stats.out_bytes, ep->stats.out_ops,
+                               ep->stats.irqs,
+                               tmp, udc_ep_readl(ep, UDCCSR),
+                               udc_ep_readl(ep, UDCBCR));
+       }
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int eps_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, eps_dbg_show, inode->i_private);
+}
+
+static int queues_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, queues_dbg_show, inode->i_private);
+}
+
+static int state_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, state_dbg_show, inode->i_private);
+}
+
+static const struct file_operations state_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = state_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static const struct file_operations queues_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = queues_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static const struct file_operations eps_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = eps_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static void pxa_init_debugfs(struct pxa_udc *udc)
+{
+       struct dentry *root, *state, *queues, *eps;
+
+       root = debugfs_create_dir(udc->gadget.name, NULL);
+       if (IS_ERR(root) || !root)
+               goto err_root;
+
+       state = debugfs_create_file("udcstate", 0400, root, udc,
+                       &state_dbg_fops);
+       if (!state)
+               goto err_state;
+       queues = debugfs_create_file("queues", 0400, root, udc,
+                       &queues_dbg_fops);
+       if (!queues)
+               goto err_queues;
+       eps = debugfs_create_file("epstate", 0400, root, udc,
+                       &eps_dbg_fops);
+       if (!queues)
+               goto err_eps;
+
+       udc->debugfs_root = root;
+       udc->debugfs_state = state;
+       udc->debugfs_queues = queues;
+       udc->debugfs_eps = eps;
+       return;
+err_eps:
+       debugfs_remove(eps);
+err_queues:
+       debugfs_remove(queues);
+err_state:
+       debugfs_remove(root);
+err_root:
+       dev_err(udc->dev, "debugfs is not available\n");
+}
+
+static void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+       debugfs_remove(udc->debugfs_eps);
+       debugfs_remove(udc->debugfs_queues);
+       debugfs_remove(udc->debugfs_state);
+       debugfs_remove(udc->debugfs_root);
+       udc->debugfs_eps = NULL;
+       udc->debugfs_queues = NULL;
+       udc->debugfs_state = NULL;
+       udc->debugfs_root = NULL;
+}
+
+#else
+static inline void pxa_init_debugfs(struct pxa_udc *udc)
+{
+}
+
+static inline void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+}
+#endif
+
+/**
+ * is_match_usb_pxa - check if usb_ep and pxa_ep match
+ * @udc_usb_ep: usb endpoint
+ * @ep: pxa endpoint
+ * @config: configuration required in pxa_ep
+ * @interface: interface required in pxa_ep
+ * @altsetting: altsetting required in pxa_ep
+ *
+ * Returns 1 if all criteria match between pxa and usb endpoint, 0 otherwise
+ */
+static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep,
+               int config, int interface, int altsetting)
+{
+       if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr)
+               return 0;
+       if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in)
+               return 0;
+       if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type)
+               return 0;
+       if ((ep->config != config) || (ep->interface != interface)
+                       || (ep->alternate != altsetting))
+               return 0;
+       return 1;
+}
+
+/**
+ * find_pxa_ep - find pxa_ep structure matching udc_usb_ep
+ * @udc: pxa udc
+ * @udc_usb_ep: udc_usb_ep structure
+ *
+ * Match udc_usb_ep and all pxa_ep available, to see if one matches.
+ * This is necessary because of the strong pxa hardware restriction requiring
+ * that once pxa endpoints are initialized, their configuration is freezed, and
+ * no change can be made to their address, direction, or in which configuration,
+ * interface or altsetting they are active ... which differs from more usual
+ * models which have endpoints be roughly just addressable fifos, and leave
+ * configuration events up to gadget drivers (like all control messages).
+ *
+ * Note that there is still a blurred point here :
+ *   - we rely on UDCCR register "active interface" and "active altsetting".
+ *     This is a nonsense in regard of USB spec, where multiple interfaces are
+ *     active at the same time.
+ *   - if we knew for sure that the pxa can handle multiple interface at the
+ *     same time, assuming Intel's Developer Guide is wrong, this function
+ *     should be reviewed, and a cache of couples (iface, altsetting) should
+ *     be kept in the pxa_udc structure. In this case this function would match
+ *     against the cache of couples instead of the "last altsetting" set up.
+ *
+ * Returns the matched pxa_ep structure or NULL if none found
+ */
+static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc,
+               struct udc_usb_ep *udc_usb_ep)
+{
+       int i;
+       struct pxa_ep *ep;
+       int cfg = udc->config;
+       int iface = udc->last_interface;
+       int alt = udc->last_alternate;
+
+       if (udc_usb_ep == &udc->udc_usb_ep[0])
+               return &udc->pxa_ep[0];
+
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt))
+                       return ep;
+       }
+       return NULL;
+}
+
+/**
+ * update_pxa_ep_matches - update pxa_ep cached values in all udc_usb_ep
+ * @udc: pxa udc
+ *
+ * Context: in_interrupt()
+ *
+ * Updates all pxa_ep fields in udc_usb_ep structures, if this field was
+ * previously set up (and is not NULL). The update is necessary is a
+ * configuration change or altsetting change was issued by the USB host.
+ */
+static void update_pxa_ep_matches(struct pxa_udc *udc)
+{
+       int i;
+       struct udc_usb_ep *udc_usb_ep;
+
+       for (i = 1; i < NR_USB_ENDPOINTS; i++) {
+               udc_usb_ep = &udc->udc_usb_ep[i];
+               if (udc_usb_ep->pxa_ep)
+                       udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
+       }
+}
+
+/**
+ * pio_irq_enable - Enables irq generation for one endpoint
+ * @ep: udc endpoint
+ */
+static void pio_irq_enable(struct pxa_ep *ep)
+{
+       struct pxa_udc *udc = ep->dev;
+       int index = EPIDX(ep);
+       u32 udcicr0 = udc_readl(udc, UDCICR0);
+       u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+       if (index < 16)
+               udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2)));
+       else
+               udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2)));
+}
+
+/**
+ * pio_irq_disable - Disables irq generation for one endpoint
+ * @ep: udc endpoint
+ * @index: endpoint number
+ */
+static void pio_irq_disable(struct pxa_ep *ep)
+{
+       struct pxa_udc *udc = ep->dev;
+       int index = EPIDX(ep);
+       u32 udcicr0 = udc_readl(udc, UDCICR0);
+       u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+       if (index < 16)
+               udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2)));
+       else
+               udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2)));
+}
+
+/**
+ * udc_set_mask_UDCCR - set bits in UDCCR
+ * @udc: udc device
+ * @mask: bits to set in UDCCR
+ *
+ * Sets bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       udc_writel(udc, UDCCR,
+                       (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * udc_clear_mask_UDCCR - clears bits in UDCCR
+ * @udc: udc device
+ * @mask: bit to clear in UDCCR
+ *
+ * Clears bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       udc_writel(udc, UDCCR,
+                       (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * ep_count_bytes_remain - get how many bytes in udc endpoint
+ * @ep: udc endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos (-EOPNOTSUPP)
+ */
+static int ep_count_bytes_remain(struct pxa_ep *ep)
+{
+       if (ep->dir_in)
+               return -EOPNOTSUPP;
+       return udc_ep_readl(ep, UDCBCR) & 0x3ff;
+}
+
+/**
+ * ep_is_empty - checks if ep has byte ready for reading
+ * @ep: udc endpoint
+ *
+ * If endpoint is the control endpoint, checks if there are bytes in the
+ * control endpoint fifo. If endpoint is a data endpoint, checks if bytes
+ * are ready for reading on OUT endpoint.
+ *
+ * Returns 0 if ep not empty, 1 if ep empty, -EOPNOTSUPP if IN endpoint
+ */
+static int ep_is_empty(struct pxa_ep *ep)
+{
+       int ret;
+
+       if (!is_ep0(ep) && ep->dir_in)
+               return -EOPNOTSUPP;
+       if (is_ep0(ep))
+               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE);
+       else
+               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE);
+       return ret;
+}
+
+/**
+ * ep_is_full - checks if ep has place to write bytes
+ * @ep: udc endpoint
+ *
+ * If endpoint is not the control endpoint and is an IN endpoint, checks if
+ * there is place to write bytes into the endpoint.
+ *
+ * Returns 0 if ep not full, 1 if ep full, -EOPNOTSUPP if OUT endpoint
+ */
+static int ep_is_full(struct pxa_ep *ep)
+{
+       if (is_ep0(ep))
+               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR);
+       if (!ep->dir_in)
+               return -EOPNOTSUPP;
+       return (!(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF));
+}
+
+/**
+ * epout_has_pkt - checks if OUT endpoint fifo has a packet available
+ * @ep: pxa endpoint
+ *
+ * Returns 1 if a complete packet is available, 0 if not, -EOPNOTSUPP for IN ep.
+ */
+static int epout_has_pkt(struct pxa_ep *ep)
+{
+       if (!is_ep0(ep) && ep->dir_in)
+               return -EOPNOTSUPP;
+       if (is_ep0(ep))
+               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC);
+       return (udc_ep_readl(ep, UDCCSR) & UDCCSR_PC);
+}
+
+/**
+ * set_ep0state - Set ep0 automata state
+ * @dev: udc device
+ * @state: state
+ */
+static void set_ep0state(struct pxa_udc *udc, int state)
+{
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+       char *old_stname = EP0_STNAME(udc);
+
+       udc->ep0state = state;
+       ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname,
+               EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR),
+               udc_ep_readl(ep, UDCBCR));
+}
+
+/**
+ * ep0_idle - Put control endpoint into idle state
+ * @dev: udc device
+ */
+static void ep0_idle(struct pxa_udc *dev)
+{
+       set_ep0state(dev, WAIT_FOR_SETUP);
+}
+
+/**
+ * inc_ep_stats_reqs - Update ep stats counts
+ * @ep: physical endpoint
+ * @req: usb request
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ *
+ */
+static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in)
+{
+       if (is_in)
+               ep->stats.in_ops++;
+       else
+               ep->stats.out_ops++;
+}
+
+/**
+ * inc_ep_stats_bytes - Update ep stats counts
+ * @ep: physical endpoint
+ * @count: bytes transfered on endpoint
+ * @req: usb request
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ */
+static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
+{
+       if (is_in)
+               ep->stats.in_bytes += count;
+       else
+               ep->stats.out_bytes += count;
+}
+
+/**
+ * pxa_ep_setup - Sets up an usb physical endpoint
+ * @ep: pxa27x physical endpoint
+ *
+ * Find the physical pxa27x ep, and setup its UDCCR
+ */
+static __init void pxa_ep_setup(struct pxa_ep *ep)
+{
+       u32 new_udccr;
+
+       new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN)
+               | ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
+               | ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN)
+               | ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN)
+               | ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET)
+               | ((ep->dir_in) ? UDCCONR_ED : 0)
+               | ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS)
+               | UDCCONR_EE;
+
+       udc_ep_writel(ep, UDCCR, new_udccr);
+}
+
+/**
+ * pxa_eps_setup - Sets up all usb physical endpoints
+ * @dev: udc device
+ *
+ * Setup all pxa physical endpoints, except ep0
+ */
+static __init void pxa_eps_setup(struct pxa_udc *dev)
+{
+       unsigned int i;
+
+       dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
+
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++)
+               pxa_ep_setup(&dev->pxa_ep[i]);
+}
+
+/**
+ * pxa_ep_alloc_request - Allocate usb request
+ * @_ep: usb endpoint
+ * @gfp_flags:
+ *
+ * For the pxa27x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+  */
+static struct usb_request *
+pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct pxa27x_request *req;
+
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req || !_ep)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       req->in_use = 0;
+       req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+       return &req->req;
+}
+
+/**
+ * pxa_ep_free_request - Free usb request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Wrapper around kfree to free _req
+ */
+static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa27x_request *req;
+
+       req = container_of(_req, struct pxa27x_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+/**
+ * ep_add_request - add a request to the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Queues the request in the endpoint's queue, and enables the interrupts
+ * on the endpoint.
+ */
+static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       if (unlikely(!req))
+               return;
+       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+               req->req.length, udc_ep_readl(ep, UDCCSR));
+
+       req->in_use = 1;
+       list_add_tail(&req->queue, &ep->queue);
+       pio_irq_enable(ep);
+}
+
+/**
+ * ep_del_request - removes a request from the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Unqueue the request from the endpoint's queue. If there are no more requests
+ * on the endpoint, and if it's not the control endpoint, interrupts are
+ * disabled on the endpoint.
+ */
+static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       if (unlikely(!req))
+               return;
+       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+               req->req.length, udc_ep_readl(ep, UDCCSR));
+
+       list_del_init(&req->queue);
+       req->in_use = 0;
+       if (!is_ep0(ep) && list_empty(&ep->queue))
+               pio_irq_disable(ep);
+}
+
+/**
+ * req_done - Complete an usb request
+ * @ep: pxa physical endpoint
+ * @req: pxa request
+ * @status: usb request status sent to gadget API
+ *
+ * Context: ep->lock held
+ *
+ * Retire a pxa27x usb request. Endpoint must be locked.
+ */
+static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status)
+{
+       ep_del_request(ep, req);
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (status && status != -ESHUTDOWN)
+               ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
+                       &req->req, status,
+                       req->req.actual, req->req.length);
+
+       req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
+}
+
+/**
+ * ep_end_out_req - Ends control endpoint in request
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends endpoint in request (completes usb request).
+ */
+static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       inc_ep_stats_reqs(ep, !USB_DIR_IN);
+       req_done(ep, req, 0);
+}
+
+/**
+ * ep0_end_out_req - Ends control endpoint in request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends control endpoint in request (completes usb request), and puts
+ * control endpoint into idle state
+ */
+static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       set_ep0state(ep->dev, OUT_STATUS_STAGE);
+       ep_end_out_req(ep, req);
+       ep0_idle(ep->dev);
+}
+
+/**
+ * ep_end_in_req - Ends endpoint out request
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends endpoint out request (completes usb request).
+ */
+static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       inc_ep_stats_reqs(ep, USB_DIR_IN);
+       req_done(ep, req, 0);
+}
+
+/**
+ * ep0_end_in_req - Ends control endpoint out request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ *
+ * Context: ep->lock held
+ *
+ * Ends control endpoint out request (completes usb request), and puts
+ * control endpoint into status state
+ */
+static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       struct pxa_udc *udc = ep->dev;
+
+       set_ep0state(udc, IN_STATUS_STAGE);
+       ep_end_in_req(ep, req);
+}
+
+/**
+ * nuke - Dequeue all requests
+ * @ep: pxa endpoint
+ * @status: usb request status
+ *
+ * Context: ep->lock held
+ *
+ * Dequeues all requests on an endpoint. As a side effect, interrupts will be
+ * disabled on that endpoint (because no more requests).
+ */
+static void nuke(struct pxa_ep *ep, int status)
+{
+       struct pxa27x_request *req;
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+               req_done(ep, req, status);
+       }
+}
+
+/**
+ * read_packet - transfer 1 packet from an OUT endpoint into request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Takes bytes from OUT endpoint and transfers them info the usb request.
+ * If there is less space in request than bytes received in OUT endpoint,
+ * bytes are left in the OUT endpoint.
+ *
+ * Returns how many bytes were actually transfered
+ */
+static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       u32 *buf;
+       int bytes_ep, bufferspace, count, i;
+
+       bytes_ep = ep_count_bytes_remain(ep);
+       bufferspace = req->req.length - req->req.actual;
+
+       buf = (u32 *)(req->req.buf + req->req.actual);
+       prefetchw(buf);
+
+       if (likely(!ep_is_empty(ep)))
+               count = min(bytes_ep, bufferspace);
+       else /* zlp */
+               count = 0;
+
+       for (i = count; i > 0; i -= 4)
+               *buf++ = udc_ep_readl(ep, UDCDR);
+       req->req.actual += count;
+
+       udc_ep_writel(ep, UDCCSR, UDCCSR_PC);
+
+       return count;
+}
+
+/**
+ * write_packet - transfer 1 packet from request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ * @max: max bytes that fit into endpoint
+ *
+ * Takes bytes from usb request, and transfers them into the physical
+ * endpoint. If there are no bytes to transfer, doesn't write anything
+ * to physical endpoint.
+ *
+ * Returns how many bytes were actually transfered.
+ */
+static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req,
+                       unsigned int max)
+{
+       int length, count, remain, i;
+       u32 *buf;
+       u8 *buf_8;
+
+       buf = (u32 *)(req->req.buf + req->req.actual);
+       prefetch(buf);
+
+       length = min(req->req.length - req->req.actual, max);
+       req->req.actual += length;
+
+       remain = length & 0x3;
+       count = length & ~(0x3);
+       for (i = count; i > 0 ; i -= 4)
+               udc_ep_writel(ep, UDCDR, *buf++);
+
+       buf_8 = (u8 *)buf;
+       for (i = remain; i > 0; i--)
+               udc_ep_writeb(ep, UDCDR, *buf_8++);
+
+       ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain,
+               udc_ep_readl(ep, UDCCSR));
+
+       return length;
+}
+
+/**
+ * read_fifo - Transfer packets from OUT endpoint into usb request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Unload as many packets as possible from the fifo we use for usb OUT
+ * transfers and put them into the request. Caller should have made sure
+ * there's at least one packet ready.
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if the request completed, 0 otherwise
+ */
+static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       int count, is_short, completed = 0;
+
+       while (epout_has_pkt(ep)) {
+               count = read_packet(ep, req);
+               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+               is_short = (count < ep->fifo_size);
+               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+                       &req->req, req->req.actual, req->req.length);
+
+               /* completion */
+               if (is_short || req->req.actual == req->req.length) {
+                       completed = 1;
+                       break;
+               }
+               /* finished that packet.  the next one may be waiting... */
+       }
+       return completed;
+}
+
+/**
+ * write_fifo - transfer packets from usb request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: pxa usb request
+ *
+ * Write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if request fully transfered, 0 if partial transfer
+ */
+static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       unsigned max;
+       int count, is_short, is_last = 0, completed = 0, totcount = 0;
+       u32 udccsr;
+
+       max = ep->fifo_size;
+       do {
+               is_short = 0;
+
+               udccsr = udc_ep_readl(ep, UDCCSR);
+               if (udccsr & UDCCSR_PC) {
+                       ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
+                               udccsr);
+                       udc_ep_writel(ep, UDCCSR, UDCCSR_PC);
+               }
+               if (udccsr & UDCCSR_TRN) {
+                       ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
+                               udccsr);
+                       udc_ep_writel(ep, UDCCSR, UDCCSR_TRN);
+               }
+
+               count = write_packet(ep, req, max);
+               inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+               totcount += count;
+
+               /* last packet is usually short (or a zlp) */
+               if (unlikely(count < max)) {
+                       is_last = 1;
+                       is_short = 1;
+               } else {
+                       if (likely(req->req.length > req->req.actual)
+                                       || req->req.zero)
+                               is_last = 0;
+                       else
+                               is_last = 1;
+                       /* interrupt/iso maxpacket may not fill the fifo */
+                       is_short = unlikely(max < ep->fifo_size);
+               }
+
+               if (is_short)
+                       udc_ep_writel(ep, UDCCSR, UDCCSR_SP);
+
+               /* requests complete when all IN data is in the FIFO */
+               if (is_last) {
+                       completed = 1;
+                       break;
+               }
+       } while (!ep_is_full(ep));
+
+       ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n",
+                       totcount, is_last ? "/L" : "", is_short ? "/S" : "",
+                       req->req.length - req->req.actual, &req->req);
+
+       return completed;
+}
+
+/**
+ * read_ep0_fifo - Transfer packets from control endpoint into usb request
+ * @ep: control endpoint
+ * @req: pxa usb request
+ *
+ * Special ep0 version of the above read_fifo. Reads as many bytes from control
+ * endpoint as can be read, and stores them into usb request (limited by request
+ * maximum length).
+ *
+ * Returns 0 if usb request only partially filled, 1 if fully filled
+ */
+static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       int count, is_short, completed = 0;
+
+       while (epout_has_pkt(ep)) {
+               count = read_packet(ep, req);
+               udc_ep_writel(ep, UDCCSR, UDCCSR0_OPC);
+               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+               is_short = (count < ep->fifo_size);
+               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+                       &req->req, req->req.actual, req->req.length);
+
+               if (is_short || req->req.actual >= req->req.length) {
+                       completed = 1;
+                       break;
+               }
+       }
+
+       return completed;
+}
+
+/**
+ * write_ep0_fifo - Send a request to control endpoint (ep0 in)
+ * @ep: control endpoint
+ * @req: request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Sends a request (or a part of the request) to the control endpoint (ep0 in).
+ * If the request doesn't fit, the remaining part will be sent from irq.
+ * The request is considered fully written only if either :
+ *   - last write transfered all remaining bytes, but fifo was not fully filled
+ *   - last write was a 0 length write
+ *
+ * Returns 1 if request fully written, 0 if request only partially sent
+ */
+static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       unsigned        count;
+       int             is_last, is_short;
+
+       count = write_packet(ep, req, EP0_FIFO_SIZE);
+       inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+
+       is_short = (count < EP0_FIFO_SIZE);
+       is_last = ((count == 0) || (count < EP0_FIFO_SIZE));
+
+       /* Sends either a short packet or a 0 length packet */
+       if (unlikely(is_short))
+               udc_ep_writel(ep, UDCCSR, UDCCSR0_IPR);
+
+       ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n",
+               count, is_short ? "/S" : "", is_last ? "/L" : "",
+               req->req.length - req->req.actual,
+               &req->req, udc_ep_readl(ep, UDCCSR));
+
+       return is_last;
+}
+
+/**
+ * pxa_ep_queue - Queue a request into an IN endpoint
+ * @_ep: usb endpoint
+ * @_req: usb request
+ * @gfp_flags: flags
+ *
+ * Context: normally called when !in_interrupt, but callable when in_interrupt()
+ * in the special case of ep0 setup :
+ *   (irq->handle_ep0_ctrl_req->gadget_setup->pxa_ep_queue)
+ *
+ * Returns 0 if succedeed, error otherwise
+ */
+static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa_ep           *ep;
+       struct pxa27x_request   *req;
+       struct pxa_udc          *dev;
+       unsigned long           flags;
+       int                     rc = 0;
+       int                     is_first_req;
+       unsigned                length;
+
+       req = container_of(_req, struct pxa27x_request, req);
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+       if (unlikely(!_req || !_req->complete || !_req->buf))
+               return -EINVAL;
+
+       if (unlikely(!_ep))
+               return -EINVAL;
+
+       dev = udc_usb_ep->dev;
+       ep = udc_usb_ep->pxa_ep;
+       if (unlikely(!ep))
+               return -EINVAL;
+
+       dev = ep->dev;
+       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               ep_dbg(ep, "bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       /* iso is always one packet per request, that's the only way
+        * we can report per-packet status.  that also helps with dma.
+        */
+       if (unlikely(EPXFERTYPE_is_ISO(ep)
+                       && req->req.length > ep->fifo_size))
+               return -EMSGSIZE;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       is_first_req = list_empty(&ep->queue);
+       ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
+                       _req, is_first_req ? "yes" : "no",
+                       _req->length, _req->buf);
+
+       if (!ep->enabled) {
+               _req->status = -ESHUTDOWN;
+               rc = -ESHUTDOWN;
+               goto out;
+       }
+
+       if (req->in_use) {
+               ep_err(ep, "refusing to queue req %p (already queued)\n", req);
+               goto out;
+       }
+
+       length = _req->length;
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       ep_add_request(ep, req);
+
+       if (is_ep0(ep)) {
+               switch (dev->ep0state) {
+               case WAIT_ACK_SET_CONF_INTERF:
+                       if (length == 0) {
+                               ep_end_in_req(ep, req);
+                       } else {
+                               ep_err(ep, "got a request of %d bytes while"
+                                       "in state WATI_ACK_SET_CONF_INTERF\n",
+                                       length);
+                               ep_del_request(ep, req);
+                               rc = -EL2HLT;
+                       }
+                       ep0_idle(ep->dev);
+                       break;
+               case IN_DATA_STAGE:
+                       if (!ep_is_full(ep))
+                               if (write_ep0_fifo(ep, req))
+                                       ep0_end_in_req(ep, req);
+                       break;
+               case OUT_DATA_STAGE:
+                       if ((length == 0) || !epout_has_pkt(ep))
+                               if (read_ep0_fifo(ep, req))
+                                       ep0_end_out_req(ep, req);
+                       break;
+               default:
+                       ep_err(ep, "odd state %s to send me a request\n",
+                               EP0_STNAME(ep->dev));
+                       ep_del_request(ep, req);
+                       rc = -EL2HLT;
+                       break;
+               }
+       } else {
+               handle_ep(ep);
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       return rc;
+}
+
+/**
+ * pxa_ep_dequeue - Dequeue one request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Return 0 if no error, -EINVAL or -ECONNRESET otherwise
+ */
+static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa27x_request   *req;
+       unsigned long           flags;
+       int                     rc;
+
+       if (!_ep)
+               return -EINVAL;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+
+       rc = -EINVAL;
+       if (&req->req != _req)
+               goto out;
+
+       rc = 0;
+       req_done(ep, req, -ECONNRESET);
+out:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       return rc;
+}
+
+/**
+ * pxa_ep_set_halt - Halts operations on one endpoint
+ * @_ep: usb endpoint
+ * @value:
+ *
+ * Returns 0 if no error, -EINVAL, -EROFS, -EAGAIN otherwise
+ */
+static int pxa_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       unsigned long flags;
+       int rc;
+
+
+       if (!_ep)
+               return -EINVAL;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return -EINVAL;
+
+       if (value == 0) {
+               /*
+                * This path (reset toggle+halt) is needed to implement
+                * SET_INTERFACE on normal hardware.  but it can't be
+                * done from software on the PXA UDC, and the hardware
+                * forgets to do it as part of SET_INTERFACE automagic.
+                */
+               ep_dbg(ep, "only host can clear halt\n");
+               return -EROFS;
+       }
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       rc = -EAGAIN;
+       if (ep->dir_in  && (ep_is_full(ep) || !list_empty(&ep->queue)))
+               goto out;
+
+       /* FST, FEF bits are the same for control and non control endpoints */
+       rc = 0;
+       udc_ep_writel(ep, UDCCSR, UDCCSR_FST | UDCCSR_FEF);
+       if (is_ep0(ep))
+               set_ep0state(ep->dev, STALL);
+
+out:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       return rc;
+}
+
+/**
+ * pxa_ep_fifo_status - Get how many bytes in physical endpoint
+ * @_ep: usb endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos.
+ */
+static int pxa_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+
+       if (!_ep)
+               return -ENODEV;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return -ENODEV;
+
+       if (ep->dir_in)
+               return -EOPNOTSUPP;
+       if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep))
+               return 0;
+       else
+               return ep_count_bytes_remain(ep) + 1;
+}
+
+/**
+ * pxa_ep_fifo_flush - Flushes one endpoint
+ * @_ep: usb endpoint
+ *
+ * Discards all data in one endpoint(IN or OUT), except control endpoint.
+ */
+static void pxa_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       unsigned long           flags;
+
+       if (!_ep)
+               return;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       if (unlikely(!list_empty(&ep->queue)))
+               ep_dbg(ep, "called while queue list not empty\n");
+       ep_dbg(ep, "called\n");
+
+       /* for OUT, just read and discard the FIFO contents. */
+       if (!ep->dir_in) {
+               while (!ep_is_empty(ep))
+                       udc_ep_readl(ep, UDCDR);
+       } else {
+               /* most IN status is the same, but ISO can't stall */
+               udc_ep_writel(ep, UDCCSR,
+                               UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
+                               | (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
+       }
+
+       spin_unlock_irqrestore(&ep->lock, flags);
+
+       return;
+}
+
+/**
+ * pxa_ep_enable - Enables usb endpoint
+ * @_ep: usb endpoint
+ * @desc: usb endpoint descriptor
+ *
+ * Nothing much to do here, as ep configuration is done once and for all
+ * before udc is enabled. After udc enable, no physical endpoint configuration
+ * can be changed.
+ * Function makes sanity checks and flushes the endpoint.
+ */
+static int pxa_ep_enable(struct usb_ep *_ep,
+       const struct usb_endpoint_descriptor *desc)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa_udc          *udc;
+
+       if (!_ep || !desc)
+               return -EINVAL;
+
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       if (udc_usb_ep->pxa_ep) {
+               ep = udc_usb_ep->pxa_ep;
+               ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
+                       _ep->name);
+       } else {
+               ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
+       }
+
+       if (!ep || is_ep0(ep)) {
+               dev_err(udc_usb_ep->dev->dev,
+                       "unable to match pxa_ep for ep %s\n",
+                       _ep->name);
+               return -EINVAL;
+       }
+
+       if ((desc->bDescriptorType != USB_DT_ENDPOINT)
+                       || (ep->type != usb_endpoint_type(desc))) {
+               ep_err(ep, "type mismatch\n");
+               return -EINVAL;
+       }
+
+       if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) {
+               ep_err(ep, "bad maxpacket\n");
+               return -ERANGE;
+       }
+
+       udc_usb_ep->pxa_ep = ep;
+       udc = ep->dev;
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               ep_err(ep, "bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       ep->enabled = 1;
+
+       /* flush fifo (mostly for OUT buffers) */
+       pxa_ep_fifo_flush(_ep);
+
+       ep_dbg(ep, "enabled\n");
+       return 0;
+}
+
+/**
+ * pxa_ep_disable - Disable usb endpoint
+ * @_ep: usb endpoint
+ *
+ * Same as for pxa_ep_enable, no physical endpoint configuration can be
+ * changed.
+ * Function flushes the endpoint and related requests.
+ */
+static int pxa_ep_disable(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       unsigned long           flags;
+
+       if (!_ep)
+               return -EINVAL;
+
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       ep->enabled = 0;
+       nuke(ep, -ESHUTDOWN);
+       spin_unlock_irqrestore(&ep->lock, flags);
+
+       pxa_ep_fifo_flush(_ep);
+       udc_usb_ep->pxa_ep = NULL;
+
+       ep_dbg(ep, "disabled\n");
+       return 0;
+}
+
+static struct usb_ep_ops pxa_ep_ops = {
+       .enable         = pxa_ep_enable,
+       .disable        = pxa_ep_disable,
+
+       .alloc_request  = pxa_ep_alloc_request,
+       .free_request   = pxa_ep_free_request,
+
+       .queue          = pxa_ep_queue,
+       .dequeue        = pxa_ep_dequeue,
+
+       .set_halt       = pxa_ep_set_halt,
+       .fifo_status    = pxa_ep_fifo_status,
+       .fifo_flush     = pxa_ep_fifo_flush,
+};
+
+
+/**
+ * pxa_udc_get_frame - Returns usb frame number
+ * @_gadget: usb gadget
+ */
+static int pxa_udc_get_frame(struct usb_gadget *_gadget)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       return (udc_readl(udc, UDCFNR) & 0x7ff);
+}
+
+/**
+ * pxa_udc_wakeup - Force udc device out of suspend
+ * @_gadget: usb gadget
+ *
+ * Returns 0 if succesfull, error code otherwise
+ */
+static int pxa_udc_wakeup(struct usb_gadget *_gadget)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       /* host may not have enabled remote wakeup */
+       if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0)
+               return -EHOSTUNREACH;
+       udc_set_mask_UDCCR(udc, UDCCR_UDR);
+       return 0;
+}
+
+static const struct usb_gadget_ops pxa_udc_ops = {
+       .get_frame      = pxa_udc_get_frame,
+       .wakeup         = pxa_udc_wakeup,
+       /* current versions must always be self-powered */
+};
+
+/**
+ * udc_disable - disable udc device controller
+ * @udc: udc device
+ *
+ * Disables the udc device : disables clocks, udc interrupts, control endpoint
+ * interrupts.
+ */
+static void udc_disable(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCICR0, 0);
+       udc_writel(udc, UDCICR1, 0);
+
+       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+       clk_disable(udc->clk);
+
+       ep0_idle(udc);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+/**
+ * udc_init_data - Initialize udc device data structures
+ * @dev: udc device
+ *
+ * Initializes gadget endpoint list, endpoints locks. No action is taken
+ * on the hardware.
+ */
+static __init void udc_init_data(struct pxa_udc *dev)
+{
+       int i;
+       struct pxa_ep *ep;
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+       dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+       ep0_idle(dev);
+       strcpy(dev->dev->bus_id, "");
+
+       /* PXA endpoints init */
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &dev->pxa_ep[i];
+
+               ep->enabled = is_ep0(ep);
+               INIT_LIST_HEAD(&ep->queue);
+               spin_lock_init(&ep->lock);
+       }
+
+       /* USB endpoints init */
+       for (i = 0; i < NR_USB_ENDPOINTS; i++)
+               if (i != 0)
+                       list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
+                                       &dev->gadget.ep_list);
+}
+
+/**
+ * udc_enable - Enables the udc device
+ * @dev: udc device
+ *
+ * Enables the udc device : enables clocks, udc interrupts, control endpoint
+ * interrupts, sets usb as UDC client and setups endpoints.
+ */
+static void udc_enable(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCICR0, 0);
+       udc_writel(udc, UDCICR1, 0);
+       udc_writel(udc, UP2OCR, UP2OCR_HXOE);
+       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+
+       clk_enable(udc->clk);
+
+       ep0_idle(udc);
+       udc->gadget.speed = USB_SPEED_FULL;
+       memset(&udc->stats, 0, sizeof(udc->stats));
+
+       udc_set_mask_UDCCR(udc, UDCCR_UDE);
+       udelay(2);
+       if (udc_readl(udc, UDCCR) & UDCCR_EMCE)
+               dev_err(udc->dev, "Configuration errors, udc disabled\n");
+
+       /*
+        * Caller must be able to sleep in order to cope with startup transients
+        */
+       msleep(100);
+
+       /* enable suspend/resume and reset irqs */
+       udc_writel(udc, UDCICR1,
+                       UDCICR1_IECC | UDCICR1_IERU
+                       | UDCICR1_IESU | UDCICR1_IERS);
+
+       /* enable ep0 irqs */
+       pio_irq_enable(&udc->pxa_ep[0]);
+
+       dev_info(udc->dev, "UDC connecting\n");
+       if (udc->mach->udc_command)
+               udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+/**
+ * usb_gadget_register_driver - Register gadget driver
+ * @driver: gadget driver
+ *
+ * When a driver is successfully registered, it will receive control requests
+ * including set_configuration(), which enables non-control requests.  Then
+ * usb traffic follows until a disconnect is reported.  Then a host may connect
+ * again, or the driver might get unbound.
+ *
+ * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct pxa_udc *udc = the_controller;
+       int retval;
+
+       if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
+                       || !driver->disconnect || !driver->setup)
+               return -EINVAL;
+       if (!udc)
+               return -ENODEV;
+       if (udc->driver)
+               return -EBUSY;
+
+       /* first hook up the driver ... */
+       udc->driver = driver;
+       udc->gadget.dev.driver = &driver->driver;
+
+       retval = device_add(&udc->gadget.dev);
+       if (retval) {
+               dev_err(udc->dev, "device_add error %d\n", retval);
+               goto add_fail;
+       }
+       retval = driver->bind(&udc->gadget);
+       if (retval) {
+               dev_err(udc->dev, "bind to driver %s --> error %d\n",
+                       driver->driver.name, retval);
+               goto bind_fail;
+       }
+       dev_dbg(udc->dev, "registered gadget driver '%s'\n",
+               driver->driver.name);
+
+       udc_enable(udc);
+       return 0;
+
+bind_fail:
+       device_del(&udc->gadget.dev);
+add_fail:
+       udc->driver = NULL;
+       udc->gadget.dev.driver = NULL;
+       return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+
+/**
+ * stop_activity - Stops udc endpoints
+ * @udc: udc device
+ * @driver: gadget driver
+ *
+ * Disables all udc endpoints (even control endpoint), report disconnect to
+ * the gadget user.
+ */
+static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
+{
+       int i;
+
+       /* don't disconnect drivers more than once */
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       for (i = 0; i < NR_USB_ENDPOINTS; i++)
+               pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
+
+       if (driver)
+               driver->disconnect(&udc->gadget);
+}
+
+/**
+ * usb_gadget_unregister_driver - Unregister the gadget driver
+ * @driver: gadget driver
+ *
+ * Returns 0 if no error, -ENODEV, -EINVAL otherwise
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct pxa_udc *udc = the_controller;
+
+       if (!udc)
+               return -ENODEV;
+       if (!driver || driver != udc->driver || !driver->unbind)
+               return -EINVAL;
+
+       stop_activity(udc, driver);
+       udc_disable(udc);
+
+       driver->unbind(&udc->gadget);
+       udc->driver = NULL;
+
+       device_del(&udc->gadget.dev);
+
+       dev_info(udc->dev, "unregistered gadget driver '%s'\n",
+                driver->driver.name);
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/**
+ * handle_ep0_ctrl_req - handle control endpoint control request
+ * @udc: udc device
+ * @req: control request
+ */
+static void handle_ep0_ctrl_req(struct pxa_udc *udc,
+                               struct pxa27x_request *req)
+{
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+       union {
+               struct usb_ctrlrequest  r;
+               u32                     word[2];
+       } u;
+       int i;
+       int have_extrabytes = 0;
+
+       nuke(ep, -EPROTO);
+
+       /* read SETUP packet */
+       for (i = 0; i < 2; i++) {
+               if (unlikely(ep_is_empty(ep)))
+                       goto stall;
+               u.word[i] = udc_ep_readl(ep, UDCDR);
+       }
+
+       have_extrabytes = !ep_is_empty(ep);
+       while (!ep_is_empty(ep)) {
+               i = udc_ep_readl(ep, UDCDR);
+               ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
+       }
+
+       le16_to_cpus(&u.r.wValue);
+       le16_to_cpus(&u.r.wIndex);
+       le16_to_cpus(&u.r.wLength);
+
+       ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+               u.r.bRequestType, u.r.bRequest,
+               u.r.wValue, u.r.wIndex, u.r.wLength);
+       if (unlikely(have_extrabytes))
+               goto stall;
+
+       if (u.r.bRequestType & USB_DIR_IN)
+               set_ep0state(udc, IN_DATA_STAGE);
+       else
+               set_ep0state(udc, OUT_DATA_STAGE);
+
+       /* Tell UDC to enter Data Stage */
+       udc_ep_writel(ep, UDCCSR, UDCCSR0_SA | UDCCSR0_OPC);
+
+       i = udc->driver->setup(&udc->gadget, &u.r);
+       if (i < 0)
+               goto stall;
+out:
+       return;
+stall:
+       ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
+               udc_ep_readl(ep, UDCCSR), i);
+       udc_ep_writel(ep, UDCCSR, UDCCSR0_FST | UDCCSR0_FTF);
+       set_ep0state(udc, STALL);
+       goto out;
+}
+
+/**
+ * handle_ep0 - Handle control endpoint data transfers
+ * @udc: udc device
+ * @fifo_irq: 1 if triggered by fifo service type irq
+ * @opc_irq: 1 if triggered by output packet complete type irq
+ *
+ * Context : when in_interrupt() or with ep->lock held
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ * Handles states of ep0 automata.
+ *
+ * PXA27x hardware handles several standard usb control requests without
+ * driver notification.  The requests fully handled by hardware are :
+ *  SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE,
+ *  GET_STATUS
+ * The requests handled by hardware, but with irq notification are :
+ *  SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE
+ * The remaining standard requests really handled by handle_ep0 are :
+ *  GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests.
+ * Requests standardized outside of USB 2.0 chapter 9 are handled more
+ * uniformly, by gadget drivers.
+ *
+ * The control endpoint state machine is _not_ USB spec compliant, it's even
+ * hardly compliant with Intel PXA270 developers guide.
+ * The key points which inferred this state machine are :
+ *   - on every setup token, bit UDCCSR0_SA is raised and held until cleared by
+ *     software.
+ *   - on every OUT packet received, UDCCSR0_OPC is raised and held until
+ *     cleared by software.
+ *   - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it
+ *     before reading ep0.
+ *   - irq can be called on a "packet complete" event (opc_irq=1), while
+ *     UDCCSR0_OPC is not yet raised (delta can be as big as 100ms
+ *     from experimentation).
+ *   - as UDCCSR0_SA can be activated while in irq handling, and clearing
+ *     UDCCSR0_OPC would flush the setup data, we almost never clear UDCCSR0_OPC
+ *     => we never actually read the "status stage" packet of an IN data stage
+ *     => this is not documented in Intel documentation
+ *   - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA
+ *     STAGE. The driver add STATUS STAGE to send last zero length packet in
+ *     OUT_STATUS_STAGE.
+ *   - special attention was needed for IN_STATUS_STAGE. If a packet complete
+ *     event is detected, we terminate the status stage without ackowledging the
+ *     packet (not to risk to loose a potential SETUP packet)
+ */
+static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
+{
+       u32                     udccsr0;
+       struct pxa_ep           *ep = &udc->pxa_ep[0];
+       struct pxa27x_request   *req = NULL;
+       int                     completed = 0;
+
+       udccsr0 = udc_ep_readl(ep, UDCCSR);
+       ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
+               EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
+               (fifo_irq << 1 | opc_irq));
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
+       if (udccsr0 & UDCCSR0_SST) {
+               ep_dbg(ep, "clearing stall status\n");
+               nuke(ep, -EPIPE);
+               udc_ep_writel(ep, UDCCSR, UDCCSR0_SST);
+               ep0_idle(udc);
+       }
+
+       if (udccsr0 & UDCCSR0_SA) {
+               nuke(ep, 0);
+               set_ep0state(udc, SETUP_STAGE);
+       }
+
+       switch (udc->ep0state) {
+       case WAIT_FOR_SETUP:
+               /*
+                * Hardware bug : beware, we cannot clear OPC, since we would
+                * miss a potential OPC irq for a setup packet.
+                * So, we only do ... nothing, and hope for a next irq with
+                * UDCCSR0_SA set.
+                */
+               break;
+       case SETUP_STAGE:
+               udccsr0 &= UDCCSR0_CTRL_REQ_MASK;
+               if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
+                       handle_ep0_ctrl_req(udc, req);
+               break;
+       case IN_DATA_STAGE:                     /* GET_DESCRIPTOR */
+               if (epout_has_pkt(ep))
+                       udc_ep_writel(ep, UDCCSR, UDCCSR0_OPC);
+               if (req && !ep_is_full(ep))
+                       completed = write_ep0_fifo(ep, req);
+               if (completed)
+                       ep0_end_in_req(ep, req);
+               break;
+       case OUT_DATA_STAGE:                    /* SET_DESCRIPTOR */
+               if (epout_has_pkt(ep) && req)
+                       completed = read_ep0_fifo(ep, req);
+               if (completed)
+                       ep0_end_out_req(ep, req);
+               break;
+       case STALL:
+               udc_ep_writel(ep, UDCCSR, UDCCSR0_FST);
+               break;
+       case IN_STATUS_STAGE:
+               /*
+                * Hardware bug : beware, we cannot clear OPC, since we would
+                * miss a potential PC irq for a setup packet.
+                * So, we only put the ep0 into WAIT_FOR_SETUP state.
+                */
+               if (opc_irq)
+                       ep0_idle(udc);
+               break;
+       case OUT_STATUS_STAGE:
+       case WAIT_ACK_SET_CONF_INTERF:
+               ep_warn(ep, "should never get in %s state here!!!\n",
+                               EP0_STNAME(ep->dev));
+               ep0_idle(udc);
+               break;
+       }
+}
+
+/**
+ * handle_ep - Handle endpoint data tranfers
+ * @ep: pxa physical endpoint
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ *
+ * Is always called when in_interrupt() or with ep->lock held.
+ */
+static void handle_ep(struct pxa_ep *ep)
+{
+       struct pxa27x_request   *req;
+       int completed;
+       u32 udccsr;
+       int is_in = ep->dir_in;
+       int loop = 0;
+
+       do {
+               completed = 0;
+               udccsr = udc_ep_readl(ep, UDCCSR);
+               if (likely(!list_empty(&ep->queue)))
+                       req = list_entry(ep->queue.next,
+                                       struct pxa27x_request, queue);
+               else
+                       req = NULL;
+
+               ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n",
+                               req, udccsr, loop++);
+
+               if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN)))
+                       udc_ep_writel(ep, UDCCSR,
+                                       udccsr & (UDCCSR_SST | UDCCSR_TRN));
+               if (!req)
+                       break;
+
+               if (unlikely(is_in)) {
+                       if (likely(!ep_is_full(ep)))
+                               completed = write_fifo(ep, req);
+                       if (completed)
+                               ep_end_in_req(ep, req);
+               } else {
+                       if (likely(epout_has_pkt(ep)))
+                               completed = read_fifo(ep, req);
+                       if (completed)
+                               ep_end_out_req(ep, req);
+               }
+       } while (completed);
+}
+
+/**
+ * pxa27x_change_configuration - Handle SET_CONF usb request notification
+ * @udc: udc device
+ * @config: usb configuration
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
+{
+       struct usb_ctrlrequest req ;
+
+       dev_dbg(udc->dev, "config=%d\n", config);
+
+       udc->config = config;
+       udc->last_interface = 0;
+       udc->last_alternate = 0;
+
+       req.bRequestType = 0;
+       req.bRequest = USB_REQ_SET_CONFIGURATION;
+       req.wValue = config;
+       req.wIndex = 0;
+       req.wLength = 0;
+
+       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+       udc->driver->setup(&udc->gadget, &req);
+}
+
+/**
+ * pxa27x_change_interface - Handle SET_INTERF usb request notification
+ * @udc: udc device
+ * @iface: interface number
+ * @alt: alternate setting number
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
+{
+       struct usb_ctrlrequest  req;
+
+       dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
+
+       udc->last_interface = iface;
+       udc->last_alternate = alt;
+
+       req.bRequestType = USB_RECIP_INTERFACE;
+       req.bRequest = USB_REQ_SET_INTERFACE;
+       req.wValue = alt;
+       req.wIndex = iface;
+       req.wLength = 0;
+
+       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+       udc->driver->setup(&udc->gadget, &req);
+}
+
+/*
+ * irq_handle_data - Handle data transfer
+ * @irq: irq IRQ number
+ * @udc: dev pxa_udc device structure
+ *
+ * Called from irq handler, transferts data to or from endpoint to queue
+ */
+static void irq_handle_data(int irq, struct pxa_udc *udc)
+{
+       int i;
+       struct pxa_ep *ep;
+       u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
+       u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
+
+       if (udcisr0 & UDCISR_INT_MASK) {
+               udc->pxa_ep[0].stats.irqs++;
+               udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK));
+               handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR),
+                               !!(udcisr0 & UDCICR_PKTCOMPL));
+       }
+
+       udcisr0 >>= 2;
+       for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) {
+               if (!(udcisr0 & UDCISR_INT_MASK))
+                       continue;
+
+               udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
+               ep = &udc->pxa_ep[i];
+               ep->stats.irqs++;
+               handle_ep(ep);
+       }
+
+       for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
+               udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK));
+               if (!(udcisr1 & UDCISR_INT_MASK))
+                       continue;
+
+               ep = &udc->pxa_ep[i];
+               ep->stats.irqs++;
+               handle_ep(ep);
+       }
+
+}
+
+/**
+ * irq_udc_suspend - Handle IRQ "UDC Suspend"
+ * @udc: udc device
+ */
+static void irq_udc_suspend(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCISR1, UDCISR1_IRSU);
+       udc->stats.irqs_suspend++;
+
+       if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                       && udc->driver && udc->driver->suspend)
+               udc->driver->suspend(&udc->gadget);
+       ep0_idle(udc);
+}
+
+/**
+  * irq_udc_resume - Handle IRQ "UDC Resume"
+  * @udc: udc device
+  */
+static void irq_udc_resume(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCISR1, UDCISR1_IRRU);
+       udc->stats.irqs_resume++;
+
+       if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                       && udc->driver && udc->driver->resume)
+               udc->driver->resume(&udc->gadget);
+}
+
+/**
+ * irq_udc_reconfig - Handle IRQ "UDC Change Configuration"
+ * @udc: udc device
+ */
+static void irq_udc_reconfig(struct pxa_udc *udc)
+{
+       unsigned config, interface, alternate, config_change;
+       u32 udccr = udc_readl(udc, UDCCR);
+
+       udc_writel(udc, UDCISR1, UDCISR1_IRCC);
+       udc->stats.irqs_reconfig++;
+
+       config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S;
+       config_change = (config != udc->config);
+       pxa27x_change_configuration(udc, config);
+
+       interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S;
+       alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S;
+       pxa27x_change_interface(udc, interface, alternate);
+
+       if (config_change)
+               update_pxa_ep_matches(udc);
+       udc_set_mask_UDCCR(udc, UDCCR_SMAC);
+}
+
+/**
+ * irq_udc_reset - Handle IRQ "UDC Reset"
+ * @udc: udc device
+ */
+static void irq_udc_reset(struct pxa_udc *udc)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+
+       dev_info(udc->dev, "USB reset\n");
+       udc_writel(udc, UDCISR1, UDCISR1_IRRS);
+       udc->stats.irqs_reset++;
+
+       if ((udccr & UDCCR_UDA) == 0) {
+               dev_dbg(udc->dev, "USB reset start\n");
+               stop_activity(udc, udc->driver);
+       }
+       udc->gadget.speed = USB_SPEED_FULL;
+       memset(&udc->stats, 0, sizeof udc->stats);
+
+       nuke(ep, -EPROTO);
+       udc_ep_writel(ep, UDCCSR, UDCCSR0_FTF | UDCCSR0_OPC);
+       ep0_idle(udc);
+}
+
+/**
+ * pxa_udc_irq - Main irq handler
+ * @irq: irq number
+ * @_dev: udc device
+ *
+ * Handles all udc interrupts
+ */
+static irqreturn_t pxa_udc_irq(int irq, void *_dev)
+{
+       struct pxa_udc *udc = _dev;
+       u32 udcisr0 = udc_readl(udc, UDCISR0);
+       u32 udcisr1 = udc_readl(udc, UDCISR1);
+       u32 udccr = udc_readl(udc, UDCCR);
+       u32 udcisr1_spec;
+
+       dev_vdbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
+                "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
+
+       udcisr1_spec = udcisr1 & 0xf8000000;
+       if (unlikely(udcisr1_spec & UDCISR1_IRSU))
+               irq_udc_suspend(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRRU))
+               irq_udc_resume(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRCC))
+               irq_udc_reconfig(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRRS))
+               irq_udc_reset(udc);
+
+       if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
+               irq_handle_data(irq, udc);
+
+       return IRQ_HANDLED;
+}
+
+static struct pxa_udc memory = {
+       .gadget = {
+               .ops            = &pxa_udc_ops,
+               .ep0            = &memory.udc_usb_ep[0].usb_ep,
+               .name           = driver_name,
+               .dev = {
+                       .bus_id         = "gadget",
+               },
+       },
+
+       .udc_usb_ep = {
+               USB_EP_CTRL,
+               USB_EP_OUT_BULK(1),
+               USB_EP_IN_BULK(2),
+               USB_EP_IN_ISO(3),
+               USB_EP_OUT_ISO(4),
+               USB_EP_IN_INT(5),
+       },
+
+       .pxa_ep = {
+               PXA_EP_CTRL,
+               /* Endpoints for gadget zero */
+               PXA_EP_OUT_BULK(1, 1, 3, 0, 0),
+               PXA_EP_IN_BULK(2,  2, 3, 0, 0),
+               /* Endpoints for ether gadget, file storage gadget */
+               PXA_EP_OUT_BULK(3, 1, 1, 0, 0),
+               PXA_EP_IN_BULK(4,  2, 1, 0, 0),
+               PXA_EP_IN_ISO(5,   3, 1, 0, 0),
+               PXA_EP_OUT_ISO(6,  4, 1, 0, 0),
+               PXA_EP_IN_INT(7,   5, 1, 0, 0),
+               /* Endpoints for RNDIS, serial */
+               PXA_EP_OUT_BULK(8, 1, 2, 0, 0),
+               PXA_EP_IN_BULK(9,  2, 2, 0, 0),
+               PXA_EP_IN_INT(10,  5, 2, 0, 0),
+               /*
+                * All the following endpoints are only for completion.  They
+                * won't never work, as multiple interfaces are really broken on
+                * the pxa.
+               */
+               PXA_EP_OUT_BULK(11, 1, 2, 1, 0),
+               PXA_EP_IN_BULK(12,  2, 2, 1, 0),
+               /* Endpoint for CDC Ether */
+               PXA_EP_OUT_BULK(13, 1, 1, 1, 1),
+               PXA_EP_IN_BULK(14,  2, 1, 1, 1),
+       }
+};
+
+/**
+ * pxa_udc_probe - probes the udc device
+ * @_dev: platform device
+ *
+ * Perform basic init : allocates udc clock, creates sysfs files, requests
+ * irq.
+ */
+static int __init pxa_udc_probe(struct platform_device *pdev)
+{
+       struct resource *regs;
+       struct pxa_udc *udc = &memory;
+       int retval;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs)
+               return -ENXIO;
+       udc->irq = platform_get_irq(pdev, 0);
+       if (udc->irq < 0)
+               return udc->irq;
+
+       udc->dev = &pdev->dev;
+       udc->mach = pdev->dev.platform_data;
+
+       udc->clk = clk_get(&pdev->dev, "UDCCLK");
+       if (IS_ERR(udc->clk)) {
+               retval = PTR_ERR(udc->clk);
+               goto err_clk;
+       }
+
+       retval = -ENOMEM;
+       udc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+       if (!udc->regs) {
+               dev_err(&pdev->dev, "Unable to map UDC I/O memory\n");
+               goto err_map;
+       }
+
+       device_initialize(&udc->gadget.dev);
+       udc->gadget.dev.parent = &pdev->dev;
+       udc->gadget.dev.dma_mask = NULL;
+
+       the_controller = udc;
+       platform_set_drvdata(pdev, udc);
+       udc_init_data(udc);
+       pxa_eps_setup(udc);
+
+       /* irq setup after old hardware state is cleaned up */
+       retval = request_irq(udc->irq, pxa_udc_irq,
+                       IRQF_SHARED, driver_name, udc);
+       if (retval != 0) {
+               dev_err(udc->dev, "%s: can't get irq %i, err %d\n",
+                       driver_name, IRQ_USB, retval);
+               goto err_irq;
+       }
+
+       pxa_init_debugfs(udc);
+       return 0;
+err_irq:
+       iounmap(udc->regs);
+err_map:
+       clk_put(udc->clk);
+       udc->clk = NULL;
+err_clk:
+       return retval;
+}
+
+/**
+ * pxa_udc_remove - removes the udc device driver
+ * @_dev: platform device
+ */
+static int __exit pxa_udc_remove(struct platform_device *_dev)
+{
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+
+       usb_gadget_unregister_driver(udc->driver);
+       free_irq(udc->irq, udc);
+       pxa_cleanup_debugfs(udc);
+
+       platform_set_drvdata(_dev, NULL);
+       the_controller = NULL;
+       clk_put(udc->clk);
+
+       return 0;
+}
+
+static void pxa_udc_shutdown(struct platform_device *_dev)
+{
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+
+       udc_disable(udc);
+}
+
+#ifdef CONFIG_PM
+/**
+ * pxa_udc_suspend - Suspend udc device
+ * @_dev: platform device
+ * @state: suspend state
+ *
+ * Suspends udc : saves configuration registers (UDCCR*), then disables the udc
+ * device.
+ */
+static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
+{
+       int i;
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+       struct pxa_ep *ep;
+
+       ep = &udc->pxa_ep[0];
+       udc->udccsr0 = udc_ep_readl(ep, UDCCSR);
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               ep->udccsr_value = udc_ep_readl(ep, UDCCSR);
+               ep->udccr_value  = udc_ep_readl(ep, UDCCR);
+               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+                               ep->udccsr_value, ep->udccr_value);
+       }
+
+       udc_disable(udc);
+
+       return 0;
+}
+
+/**
+ * pxa_udc_resume - Resume udc device
+ * @_dev: platform device
+ *
+ * Resumes udc : restores configuration registers (UDCCR*), then enables the udc
+ * device.
+ */
+static int pxa_udc_resume(struct platform_device *_dev)
+{
+       int i;
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+       struct pxa_ep *ep;
+
+       ep = &udc->pxa_ep[0];
+       udc_ep_writel(ep, UDCCSR, udc->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME));
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               udc_ep_writel(ep, UDCCSR, ep->udccsr_value);
+               udc_ep_writel(ep, UDCCR,  ep->udccr_value);
+               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+                               ep->udccsr_value, ep->udccr_value);
+       }
+
+       udc_enable(udc);
+       /*
+        * We do not handle OTG yet.
+        *
+        * OTGPH bit is set when sleep mode is entered.
+        * it indicates that OTG pad is retaining its state.
+        * Upon exit from sleep mode and before clearing OTGPH,
+        * Software must configure the USB OTG pad, UDC, and UHC
+        * to the state they were in before entering sleep mode.
+        *
+        * Should be : PSSR |= PSSR_OTGPH;
+        */
+
+       return 0;
+}
+#endif
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:pxa2xx-udc");
+
+static struct platform_driver udc_driver = {
+       .driver         = {
+               .name   = "pxa2xx-udc",
+               .owner  = THIS_MODULE,
+       },
+       .remove         = __exit_p(pxa_udc_remove),
+       .shutdown       = pxa_udc_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = pxa_udc_suspend,
+       .resume         = pxa_udc_resume
+#endif
+};
+
+static int __init udc_init(void)
+{
+       printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+       return platform_driver_probe(&udc_driver, pxa_udc_probe);
+}
+module_init(udc_init);
+
+
+static void __exit udc_exit(void)
+{
+       platform_driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
 
--- /dev/null
+/*
+ * linux/drivers/usb/gadget/pxa27x_udc.h
+ * Intel PXA27x on-chip full speed USB device controller
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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 __LINUX_USB_GADGET_PXA27X_H
+#define __LINUX_USB_GADGET_PXA27X_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+/*
+ * Register definitions
+ */
+/* Offsets */
+#define UDCCR          0x0000          /* UDC Control Register */
+#define UDCICR0                0x0004          /* UDC Interrupt Control Register0 */
+#define UDCICR1                0x0008          /* UDC Interrupt Control Register1 */
+#define UDCISR0                0x000C          /* UDC Interrupt Status Register 0 */
+#define UDCISR1                0x0010          /* UDC Interrupt Status Register 1 */
+#define UDCFNR         0x0014          /* UDC Frame Number Register */
+#define UDCOTGICR      0x0018          /* UDC On-The-Go interrupt control */
+#define UP2OCR         0x0020          /* USB Port 2 Output Control register */
+#define UP3OCR         0x0024          /* USB Port 3 Output Control register */
+#define UDCCSRn(x)     (0x0100 + ((x)<<2)) /* UDC Control/Status register */
+#define UDCBCRn(x)     (0x0200 + ((x)<<2)) /* UDC Byte Count Register */
+#define UDCDRn(x)      (0x0300 + ((x)<<2)) /* UDC Data Register  */
+#define UDCCRn(x)      (0x0400 + ((x)<<2)) /* UDC Control Register */
+
+#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 UDCCR_SMAC     (1 << 4)        /* Switch Endpoint Memory to Active
+                                          Configuration */
+#define UDCCR_EMCE     (1 << 3)        /* Endpoint Memory Configuration
+                                          Error */
+#define UDCCR_UDR      (1 << 2)        /* UDC Resume */
+#define UDCCR_UDA      (1 << 1)        /* UDC Active */
+#define UDCCR_UDE      (1 << 0)        /* UDC Enable */
+
+#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 UDCICR_FIFOERR (1 << 1)        /* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL        (1 << 0)        /* Packet Complete interrupt for EP */
+#define UDCICR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC   (1 << 31)       /* IntReq - Configuration Change */
+#define UDCISR1_IRSOF  (1 << 30)       /* IntReq - Start of Frame */
+#define UDCISR1_IRRU   (1 << 29)       /* IntReq - Resume */
+#define UDCISR1_IRSU   (1 << 28)       /* IntReq - Suspend */
+#define UDCISR1_IRRS   (1 << 27)       /* IntReq - Reset */
+#define UDCISR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#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 */
+
+/* Host Port 2 field bits */
+#define UP2OCR_CPVEN   (1 << 0)        /* Charge Pump Vbus Enable */
+#define UP2OCR_CPVPE   (1 << 1)        /* Charge Pump Vbus Pulse Enable */
+                                       /* Transceiver enablers */
+#define UP2OCR_DPPDE   (1 << 2)        /*   D+ Pull Down Enable */
+#define UP2OCR_DMPDE   (1 << 3)        /*   D- Pull Down Enable */
+#define UP2OCR_DPPUE   (1 << 4)        /*   D+ Pull Up Enable */
+#define UP2OCR_DMPUE   (1 << 5)        /*   D- Pull Up Enable */
+#define UP2OCR_DPPUBE  (1 << 6)        /*   D+ Pull Up Bypass Enable */
+#define UP2OCR_DMPUBE  (1 << 7)        /*   D- Pull Up Bypass Enable */
+#define UP2OCR_EXSP    (1 << 8)        /* External Transceiver Speed Control */
+#define UP2OCR_EXSUS   (1 << 9)        /* External Transceiver Speed Enable */
+#define UP2OCR_IDON    (1 << 10)       /* OTG ID Read Enable */
+#define UP2OCR_HXS     (1 << 16)       /* Transceiver Output Select */
+#define UP2OCR_HXOE    (1 << 17)       /* Transceiver Output Enable */
+#define UP2OCR_SEOS    (1 << 24)       /* Single-Ended Output Select */
+
+#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 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 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 UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
+#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST)
+#define UDC_FNR_MASK   (0x7ff)
+#define UDC_BCR_MASK   (0x3ff)
+
+/*
+ * UDCCR = UDC Endpoint Configuration Registers
+ * UDCCSR = UDC Control/Status Register for this EP
+ * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
+ * UDCDR = UDC Endpoint Data Register (the fifo)
+ */
+#define ofs_UDCCR(ep)  (UDCCRn(ep->idx))
+#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx))
+#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx))
+#define ofs_UDCDR(ep)  (UDCDRn(ep->idx))
+
+/* Register access macros */
+#define udc_ep_readl(ep, reg)  \
+       __raw_readl((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writel(ep, reg, value)  \
+       __raw_writel((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_ep_readb(ep, reg)  \
+       __raw_readb((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writeb(ep, reg, value)  \
+       __raw_writeb((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_readl(dev, reg)    \
+       __raw_readl((dev)->regs + (reg))
+#define udc_writel(udc, reg, value)    \
+       __raw_writel((value), (udc)->regs + (reg))
+
+#define UDCCSR_MASK            (UDCCSR_FST | UDCCSR_DME)
+#define UDCCISR0_EP_MASK       ~0
+#define UDCCISR1_EP_MASK       0xffff
+#define UDCCSR0_CTRL_REQ_MASK  (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
+
+#define EPIDX(ep)      (ep->idx)
+#define EPADDR(ep)     (ep->addr)
+#define EPXFERTYPE(ep) (ep->type)
+#define EPNAME(ep)     (ep->name)
+#define is_ep0(ep)     (!ep->idx)
+#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
+
+/*
+ * Endpoint definitions
+ *
+ * Once enabled, pxa endpoint configuration is freezed, and cannot change
+ * unless a reset happens or the udc is disabled.
+ * Therefore, we must define all pxa potential endpoint definitions needed for
+ * all gadget and set them up before the udc is enabled.
+ *
+ * As the architecture chosen is fully static, meaning the pxa endpoint
+ * configurations are set up once and for all, we must provide a way to match
+ * one usb endpoint (usb_ep) to several pxa endpoints. The reason is that gadget
+ * layer autoconf doesn't choose the usb_ep endpoint on (config, interface, alt)
+ * criteria, while the pxa architecture requires that.
+ *
+ * The solution is to define several pxa endpoints matching one usb_ep. Ex:
+ *   - "ep1-in" matches pxa endpoint EPA (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=0)
+ *   - "ep1-in" matches pxa endpoint EPB (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=1)
+ *   - "ep1-in" matches pxa endpoint EPC (which is an IN ep at addr 1, when
+ *     the udc talks on (config=2, interface=0, alt=0)
+ *
+ * We'll define the pxa endpoint by its index (EPA => idx=1, EPB => idx=2, ...)
+ */
+
+/*
+ * Endpoint definition helpers
+ */
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+  .desc = {    .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
+               .bmAttributes = type, \
+               .wMaxPacketSize = maxpkt, }, \
+  .dev = &memory \
+}
+#define USB_EP_BULK(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
+#define USB_EP_ISO(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
+#define USB_EP_INT(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
+#define USB_EP_IN_BULK(n)      USB_EP_BULK(n, "ep" #n "in-bulk", 1)
+#define USB_EP_OUT_BULK(n)     USB_EP_BULK(n, "ep" #n "out-bulk", 0)
+#define USB_EP_IN_ISO(n)       USB_EP_ISO(n,  "ep" #n "in-iso", 1)
+#define USB_EP_OUT_ISO(n)      USB_EP_ISO(n,  "ep" #n "out-iso", 0)
+#define USB_EP_IN_INT(n)       USB_EP_INT(n,  "ep" #n "in-int", 1)
+#define USB_EP_CTRL            USB_EP_DEF(0,  "ep0", 0, 0, EP0_FIFO_SIZE)
+
+#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
+{ \
+       .dev = &memory, \
+       .name = "ep" #_idx, \
+       .idx = _idx, .enabled = 0, \
+       .dir_in = dir, .addr = _addr, \
+       .config = _config, .interface = iface, .alternate = altset, \
+       .type = _type, .fifo_size = maxpkt, \
+}
+#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_IN_BULK(i, adr, c, f, a)                PXA_EP_BULK(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_BULK(i, adr, c, f, a)       PXA_EP_BULK(i, adr, 0, c, f, a)
+#define PXA_EP_IN_ISO(i, adr, c, f, a)         PXA_EP_ISO(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_ISO(i, adr, c, f, a)                PXA_EP_ISO(i, adr, 0, c, f, a)
+#define PXA_EP_IN_INT(i, adr, c, f, a)         PXA_EP_INT(i, adr, 1, c, f, a)
+#define PXA_EP_CTRL    PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
+
+struct pxa27x_udc;
+
+struct stats {
+       unsigned long in_ops;
+       unsigned long out_ops;
+       unsigned long in_bytes;
+       unsigned long out_bytes;
+       unsigned long irqs;
+};
+
+/**
+ * struct udc_usb_ep - container of each usb_ep structure
+ * @usb_ep: usb endpoint
+ * @desc: usb descriptor, especially type and address
+ * @dev: udc managing this endpoint
+ * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
+ */
+struct udc_usb_ep {
+       struct usb_ep usb_ep;
+       struct usb_endpoint_descriptor desc;
+       struct pxa_udc *dev;
+       struct pxa_ep *pxa_ep;
+};
+
+/**
+ * struct pxa_ep - pxa endpoint
+ * @dev: udc device
+ * @queue: requests queue
+ * @lock: lock to pxa_ep data (queues and stats)
+ * @enabled: true when endpoint enabled (not stopped by gadget layer)
+ * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
+ * @name: endpoint name (for trace/debug purpose)
+ * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
+ * @addr: usb endpoint number
+ * @config: configuration in which this endpoint is active
+ * @interface: interface in which this endpoint is active
+ * @alternate: altsetting in which this endpoitn is active
+ * @fifo_size: max packet size in the endpoint fifo
+ * @type: endpoint type (bulk, iso, int, ...)
+ * @udccsr_value: save register of UDCCSR0 for suspend/resume
+ * @udccr_value: save register of UDCCR for suspend/resume
+ * @stats: endpoint statistics
+ *
+ * The *PROBLEM* is that pxa's endpoint configuration scheme is both misdesigned
+ * (cares about config/interface/altsetting, thus placing needless limits on
+ * device capability) and full of implementation bugs forcing it to be set up
+ * for use more or less like a pxa255.
+ *
+ * As we define the pxa_ep statically, we must guess all needed pxa_ep for all
+ * gadget which may work with this udc driver.
+ */
+struct pxa_ep {
+       struct pxa_udc          *dev;
+
+       struct list_head        queue;
+       spinlock_t              lock;           /* Protects this structure */
+                                               /* (queues, stats) */
+       unsigned                enabled:1;
+
+       unsigned                idx:5;
+       char                    *name;
+
+       /*
+        * Specific pxa endpoint data, needed for hardware initialization
+        */
+       unsigned                dir_in:1;
+       unsigned                addr:3;
+       unsigned                config:2;
+       unsigned                interface:3;
+       unsigned                alternate:3;
+       unsigned                fifo_size;
+       unsigned                type;
+
+#ifdef CONFIG_PM
+       u32                     udccsr_value;
+       u32                     udccr_value;
+#endif
+       struct stats            stats;
+};
+
+/**
+ * struct pxa27x_request - container of each usb_request structure
+ * @req: usb request
+ * @udc_usb_ep: usb endpoint the request was submitted on
+ * @in_use: sanity check if request already queued on an pxa_ep
+ * @queue: linked list of requests, linked on pxa_ep->queue
+ */
+struct pxa27x_request {
+       struct usb_request                      req;
+       struct udc_usb_ep                       *udc_usb_ep;
+       unsigned                                in_use:1;
+       struct list_head                        queue;
+};
+
+enum ep0_state {
+       WAIT_FOR_SETUP,
+       SETUP_STAGE,
+       IN_DATA_STAGE,
+       OUT_DATA_STAGE,
+       IN_STATUS_STAGE,
+       OUT_STATUS_STAGE,
+       STALL,
+       WAIT_ACK_SET_CONF_INTERF
+};
+
+static char *ep0_state_name[] = {
+       "WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
+       "IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
+       "WAIT_ACK_SET_CONF_INTERF"
+};
+#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
+
+#define EP0_FIFO_SIZE  16U
+#define BULK_FIFO_SIZE 64U
+#define ISO_FIFO_SIZE  256U
+#define INT_FIFO_SIZE  16U
+
+struct udc_stats {
+       unsigned long   irqs_reset;
+       unsigned long   irqs_suspend;
+       unsigned long   irqs_resume;
+       unsigned long   irqs_reconfig;
+};
+
+#define NR_USB_ENDPOINTS (1 + 5)       /* ep0 + ep1in-bulk + .. + ep3in-iso */
+#define NR_PXA_ENDPOINTS (1 + 14)      /* ep0 + epA + epB + .. + epX */
+
+/**
+ * struct pxa_udc - udc structure
+ * @regs: mapped IO space
+ * @irq: udc irq
+ * @clk: udc clock
+ * @usb_gadget: udc gadget structure
+ * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
+ * @dev: device
+ * @mach: machine info, used to activate specific GPIO
+ * @ep0state: control endpoint state machine state
+ * @stats: statistics on udc usage
+ * @udc_usb_ep: array of usb endpoints offered by the gadget
+ * @pxa_ep: array of pxa available endpoints
+ * @config: UDC active configuration
+ * @last_interface: UDC interface of the last SET_INTERFACE host request
+ * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
+ * @udccsr0: save of udccsr0 in case of suspend
+ * @debugfs_root: root entry of debug filesystem
+ * @debugfs_state: debugfs entry for "udcstate"
+ * @debugfs_queues: debugfs entry for "queues"
+ * @debugfs_eps: debugfs entry for "epstate"
+ */
+struct pxa_udc {
+       void __iomem                            *regs;
+       int                                     irq;
+       struct clk                              *clk;
+
+       struct usb_gadget                       gadget;
+       struct usb_gadget_driver                *driver;
+       struct device                           *dev;
+       struct pxa2xx_udc_mach_info             *mach;
+
+       enum ep0_state                          ep0state;
+       struct udc_stats                        stats;
+
+       struct udc_usb_ep                       udc_usb_ep[NR_USB_ENDPOINTS];
+       struct pxa_ep                           pxa_ep[NR_PXA_ENDPOINTS];
+
+       unsigned                                config:2;
+       unsigned                                last_interface:3;
+       unsigned                                last_alternate:3;
+
+#ifdef CONFIG_PM
+       unsigned                                udccsr0;
+#endif
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       struct dentry                           *debugfs_root;
+       struct dentry                           *debugfs_state;
+       struct dentry                           *debugfs_queues;
+       struct dentry                           *debugfs_eps;
+#endif
+};
+
+static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct pxa_udc, gadget);
+}
+
+/*
+ * Debugging/message support
+ */
+#define ep_dbg(ep, fmt, arg...) \
+       dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_vdbg(ep, fmt, arg...) \
+       dev_vdbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_err(ep, fmt, arg...) \
+       dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_info(ep, fmt, arg...) \
+       dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_warn(ep, fmt, arg...) \
+       dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
+
+#endif /* __LINUX_USB_GADGET_PXA27X_H */