#include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include <mach/hardware.h>
-
 #ifdef CONFIG_ARCH_LUBBOCK
 #include <mach/lubbock.h>
 #endif
 
-#ifdef CONFIG_ARCH_IXP4XX
-#define __UDC_REG(x) (*((volatile u32 *)(IXP4XX_USB_BASE_VIRT + (x))))
-#endif
-
-#ifdef CONFIG_ARCH_PXA
-#define __UDC_REG(x) __REG(0x40600000 + (x))
-#endif
-
-#define UDCCR          __UDC_REG(0x0000)  /* UDC Control Register */
-#define UDC_RES1       __UDC_REG(0x0004)  /* UDC Undocumented - Reserved1 */
-#define UDC_RES2       __UDC_REG(0x0008)  /* UDC Undocumented - Reserved2 */
-#define UDC_RES3       __UDC_REG(0x000C)  /* UDC Undocumented - Reserved3 */
-#define UDCCS0         __UDC_REG(0x0010)  /* UDC Endpoint 0 Control/Status Register */
-#define UDCCS1         __UDC_REG(0x0014)  /* UDC Endpoint 1 (IN) Control/Status Register */
-#define UDCCS2         __UDC_REG(0x0018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
-#define UDCCS3         __UDC_REG(0x001C)  /* UDC Endpoint 3 (IN) Control/Status Register */
-#define UDCCS4         __UDC_REG(0x0020)  /* UDC Endpoint 4 (OUT) Control/Status Register */
-#define UDCCS5         __UDC_REG(0x0024)  /* UDC Endpoint 5 (Interrupt) Control/Status Register */
-#define UDCCS6         __UDC_REG(0x0028)  /* UDC Endpoint 6 (IN) Control/Status Register */
-#define UDCCS7         __UDC_REG(0x002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
-#define UDCCS8         __UDC_REG(0x0030)  /* UDC Endpoint 8 (IN) Control/Status Register */
-#define UDCCS9         __UDC_REG(0x0034)  /* UDC Endpoint 9 (OUT) Control/Status Register */
-#define UDCCS10                __UDC_REG(0x0038)  /* UDC Endpoint 10 (Interrupt) Control/Status Register */
-#define UDCCS11                __UDC_REG(0x003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
-#define UDCCS12                __UDC_REG(0x0040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
-#define UDCCS13                __UDC_REG(0x0044)  /* UDC Endpoint 13 (IN) Control/Status Register */
-#define UDCCS14                __UDC_REG(0x0048)  /* UDC Endpoint 14 (OUT) Control/Status Register */
-#define UDCCS15                __UDC_REG(0x004C)  /* UDC Endpoint 15 (Interrupt) Control/Status Register */
-#define UFNRH          __UDC_REG(0x0060)  /* UDC Frame Number Register High */
-#define UFNRL          __UDC_REG(0x0064)  /* UDC Frame Number Register Low */
-#define UBCR2          __UDC_REG(0x0068)  /* UDC Byte Count Reg 2 */
-#define UBCR4          __UDC_REG(0x006c)  /* UDC Byte Count Reg 4 */
-#define UBCR7          __UDC_REG(0x0070)  /* UDC Byte Count Reg 7 */
-#define UBCR9          __UDC_REG(0x0074)  /* UDC Byte Count Reg 9 */
-#define UBCR12         __UDC_REG(0x0078)  /* UDC Byte Count Reg 12 */
-#define UBCR14         __UDC_REG(0x007c)  /* UDC Byte Count Reg 14 */
-#define UDDR0          __UDC_REG(0x0080)  /* UDC Endpoint 0 Data Register */
-#define UDDR1          __UDC_REG(0x0100)  /* UDC Endpoint 1 Data Register */
-#define UDDR2          __UDC_REG(0x0180)  /* UDC Endpoint 2 Data Register */
-#define UDDR3          __UDC_REG(0x0200)  /* UDC Endpoint 3 Data Register */
-#define UDDR4          __UDC_REG(0x0400)  /* UDC Endpoint 4 Data Register */
-#define UDDR5          __UDC_REG(0x00A0)  /* UDC Endpoint 5 Data Register */
-#define UDDR6          __UDC_REG(0x0600)  /* UDC Endpoint 6 Data Register */
-#define UDDR7          __UDC_REG(0x0680)  /* UDC Endpoint 7 Data Register */
-#define UDDR8          __UDC_REG(0x0700)  /* UDC Endpoint 8 Data Register */
-#define UDDR9          __UDC_REG(0x0900)  /* UDC Endpoint 9 Data Register */
-#define UDDR10         __UDC_REG(0x00C0)  /* UDC Endpoint 10 Data Register */
-#define UDDR11         __UDC_REG(0x0B00)  /* UDC Endpoint 11 Data Register */
-#define UDDR12         __UDC_REG(0x0B80)  /* UDC Endpoint 12 Data Register */
-#define UDDR13         __UDC_REG(0x0C00)  /* UDC Endpoint 13 Data Register */
-#define UDDR14         __UDC_REG(0x0E00)  /* UDC Endpoint 14 Data Register */
-#define UDDR15         __UDC_REG(0x00E0)  /* UDC Endpoint 15 Data Register */
-
-#define UICR0          __UDC_REG(0x0050)  /* UDC Interrupt Control Register 0 */
-#define UICR1          __UDC_REG(0x0054)  /* UDC Interrupt Control Register 1 */
-
-#define USIR0          __UDC_REG(0x0058)  /* UDC Status Interrupt Register 0 */
-#define USIR1          __UDC_REG(0x005C)  /* UDC Status Interrupt Register 1 */
+static void __iomem *pxa25x_udc_reg_base;
+#define __UDC_REG(x) (*((volatile u32 *)(pxa25x_udc_reg_base + (x))))
+
+#define UDCCR   0x0000 /* UDC Control Register */
+#define UDC_RES1 0x0004 /* UDC Undocumented - Reserved1 */
+#define UDC_RES2 0x0008 /* UDC Undocumented - Reserved2 */
+#define UDC_RES3 0x000C /* UDC Undocumented - Reserved3 */
+#define UDCCS0  0x0010 /* UDC Endpoint 0 Control/Status Register */
+#define UDCCS1  0x0014 /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS2  0x0018 /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS3  0x001C /* UDC Endpoint 3 (IN) Control/Status Register */
+#define UDCCS4  0x0020 /* UDC Endpoint 4 (OUT) Control/Status Register */
+#define UDCCS5  0x0024 /* UDC Endpoint 5 (Interrupt) Control/Status Register */
+#define UDCCS6  0x0028 /* UDC Endpoint 6 (IN) Control/Status Register */
+#define UDCCS7  0x002C /* UDC Endpoint 7 (OUT) Control/Status Register */
+#define UDCCS8  0x0030 /* UDC Endpoint 8 (IN) Control/Status Register */
+#define UDCCS9  0x0034 /* UDC Endpoint 9 (OUT) Control/Status Register */
+#define UDCCS10         0x0038 /* UDC Endpoint 10 (Interrupt) Control/Status Register */
+#define UDCCS11         0x003C /* UDC Endpoint 11 (IN) Control/Status Register */
+#define UDCCS12         0x0040 /* UDC Endpoint 12 (OUT) Control/Status Register */
+#define UDCCS13         0x0044 /* UDC Endpoint 13 (IN) Control/Status Register */
+#define UDCCS14         0x0048 /* UDC Endpoint 14 (OUT) Control/Status Register */
+#define UDCCS15         0x004C /* UDC Endpoint 15 (Interrupt) Control/Status Register */
+#define UFNRH   0x0060 /* UDC Frame Number Register High */
+#define UFNRL   0x0064 /* UDC Frame Number Register Low */
+#define UBCR2   0x0068 /* UDC Byte Count Reg 2 */
+#define UBCR4   0x006c /* UDC Byte Count Reg 4 */
+#define UBCR7   0x0070 /* UDC Byte Count Reg 7 */
+#define UBCR9   0x0074 /* UDC Byte Count Reg 9 */
+#define UBCR12  0x0078 /* UDC Byte Count Reg 12 */
+#define UBCR14  0x007c /* UDC Byte Count Reg 14 */
+#define UDDR0   0x0080 /* UDC Endpoint 0 Data Register */
+#define UDDR1   0x0100 /* UDC Endpoint 1 Data Register */
+#define UDDR2   0x0180 /* UDC Endpoint 2 Data Register */
+#define UDDR3   0x0200 /* UDC Endpoint 3 Data Register */
+#define UDDR4   0x0400 /* UDC Endpoint 4 Data Register */
+#define UDDR5   0x00A0 /* UDC Endpoint 5 Data Register */
+#define UDDR6   0x0600 /* UDC Endpoint 6 Data Register */
+#define UDDR7   0x0680 /* UDC Endpoint 7 Data Register */
+#define UDDR8   0x0700 /* UDC Endpoint 8 Data Register */
+#define UDDR9   0x0900 /* UDC Endpoint 9 Data Register */
+#define UDDR10  0x00C0 /* UDC Endpoint 10 Data Register */
+#define UDDR11  0x0B00 /* UDC Endpoint 11 Data Register */
+#define UDDR12  0x0B80 /* UDC Endpoint 12 Data Register */
+#define UDDR13  0x0C00 /* UDC Endpoint 13 Data Register */
+#define UDDR14  0x0E00 /* UDC Endpoint 14 Data Register */
+#define UDDR15  0x00E0 /* UDC Endpoint 15 Data Register */
+
+#define UICR0   0x0050 /* UDC Interrupt Control Register 0 */
+#define UICR1   0x0054 /* UDC Interrupt Control Register 1 */
+
+#define USIR0   0x0058 /* UDC Status Interrupt Register 0 */
+#define USIR1   0x005C /* UDC Status Interrupt Register 1 */
 
 #define UDCCR_UDE      (1 << 0)        /* UDC enable */
 #define UDCCR_UDA      (1 << 1)        /* UDC active */
                mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
 
-static void pio_irq_enable(int bEndpointAddress)
+static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 uicr)
+{
+       __UDC_REG(reg) = uicr;
+}
+
+static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg)
 {
-        bEndpointAddress &= 0xf;
+       return __UDC_REG(reg);
+}
+
+static void pio_irq_enable(struct pxa25x_ep *ep)
+{
+       u32 bEndpointAddress = ep->bEndpointAddress & 0xf;
+
         if (bEndpointAddress < 8)
-                UICR0 &= ~(1 << bEndpointAddress);
+               udc_set_reg(ep->dev, UICR0, udc_get_reg(ep->dev, UICR0) &
+                                               ~(1 << bEndpointAddress));
         else {
                 bEndpointAddress -= 8;
-                UICR1 &= ~(1 << bEndpointAddress);
+               udc_set_reg(ep->dev, UICR1, udc_get_reg(ep->dev, UICR1) &
+                                               ~(1 << bEndpointAddress));
        }
 }
 
-static void pio_irq_disable(int bEndpointAddress)
+static void pio_irq_disable(struct pxa25x_ep *ep)
 {
-        bEndpointAddress &= 0xf;
+       u32 bEndpointAddress = ep->bEndpointAddress & 0xf;
+
         if (bEndpointAddress < 8)
-                UICR0 |= 1 << bEndpointAddress;
+                udc_set_reg(ep->dev, UICR0, udc_get_reg(ep->dev, UICR0) |
+                                               (1 << bEndpointAddress));
         else {
                 bEndpointAddress -= 8;
-                UICR1 |= 1 << bEndpointAddress;
+                udc_set_reg(ep->dev, UICR1, udc_get_reg(ep->dev, UICR1) |
+                                               (1 << bEndpointAddress));
         }
 }
 
  */
 #define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
 
-static inline void udc_set_mask_UDCCR(int mask)
+static inline void udc_set_mask_UDCCR(struct pxa25x_udc *dev, int mask)
 {
-       UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+       u32 udccr = __UDC_REG(UDCCR);
+
+       __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
 }
 
-static inline void udc_clear_mask_UDCCR(int mask)
+static inline void udc_clear_mask_UDCCR(struct pxa25x_udc *dev, int mask)
 {
-       UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+       u32 udccr = __UDC_REG(UDCCR);
+
+       __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
 }
 
-static inline void udc_ack_int_UDCCR(int mask)
+static inline void udc_ack_int_UDCCR(struct pxa25x_udc *dev, int mask)
 {
        /* udccr contains the bits we dont want to change */
-       __u32 udccr = UDCCR & UDCCR_MASK_BITS;
+       u32 udccr = __UDC_REG(UDCCR) & UDCCR_MASK_BITS;
 
-       UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
+       __UDC_REG(UDCCR) = udccr | (mask & ~UDCCR_MASK_BITS);
+}
+
+static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *ep)
+{
+       return __UDC_REG(ep->regoff_udccs);
+}
+
+static inline void udc_ep_set_UDCCS(struct pxa25x_ep *ep, u32 data)
+{
+       __UDC_REG(ep->regoff_udccs) = data;
+}
+
+static inline u32 udc_ep0_get_UDCCS(struct pxa25x_udc *dev)
+{
+       return __UDC_REG(UDCCS0);
+}
+
+static inline void udc_ep0_set_UDCCS(struct pxa25x_udc *dev, u32 data)
+{
+       __UDC_REG(UDCCS0) = data;
+}
+
+static inline u32 udc_ep_get_UDDR(struct pxa25x_ep *ep)
+{
+       return __UDC_REG(ep->regoff_uddr);
+}
+
+static inline void udc_ep_set_UDDR(struct pxa25x_ep *ep, u32 data)
+{
+       __UDC_REG(ep->regoff_uddr) = data;
+}
+
+static inline u32 udc_ep_get_UBCR(struct pxa25x_ep *ep)
+{
+       return __UDC_REG(ep->regoff_ubcr);
 }
 
 /*
 }
 
 static int
-write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max)
+write_packet(struct pxa25x_ep *ep, struct pxa25x_request *req, unsigned max)
 {
        u8              *buf;
        unsigned        length, count;
 
        count = length;
        while (likely(count--))
-               *uddr = *buf++;
+               udc_ep_set_UDDR(ep, *buf++);
 
        return length;
 }
                unsigned        count;
                int             is_last, is_short;
 
-               count = write_packet(ep->reg_uddr, req, max);
+               count = write_packet(ep, req, max);
 
                /* last packet is usually short (or a zlp) */
                if (unlikely (count != max))
                 * double buffering might work.  TSP, TPC, and TFS
                 * bit values are the same for all normal IN endpoints.
                 */
-               *ep->reg_udccs = UDCCS_BI_TPC;
+               udc_ep_set_UDCCS(ep, UDCCS_BI_TPC);
                if (is_short)
-                       *ep->reg_udccs = UDCCS_BI_TSP;
+                       udc_ep_set_UDCCS(ep, UDCCS_BI_TSP);
 
                /* requests complete when all IN data is in the FIFO */
                if (is_last) {
                        done (ep, req, 0);
                        if (list_empty(&ep->queue))
-                               pio_irq_disable (ep->bEndpointAddress);
+                               pio_irq_disable(ep);
                        return 1;
                }
 
                // double buffering is off in the default fifo mode, which
                // prevents TFS from being set here.
 
-       } while (*ep->reg_udccs & UDCCS_BI_TFS);
+       } while (udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS);
        return 0;
 }
 
 static inline
 void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
 {
-       UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
-       USIR0 = USIR0_IR0;
+       udc_ep0_set_UDCCS(dev, flags|UDCCS0_SA|UDCCS0_OPR);
+       udc_set_reg(dev, USIR0, USIR0_IR0);
        dev->req_pending = 0;
        DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
-               __func__, tag, UDCCS0, flags);
+               __func__, tag, udc_ep0_get_UDCCS(dev), flags);
 }
 
 static int
 write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
 {
+       struct pxa25x_udc *dev = ep->dev;
        unsigned        count;
        int             is_short;
 
-       count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
+       count = write_packet(&dev->ep[0], req, EP0_FIFO_SIZE);
        ep->dev->stats.write.bytes += count;
 
        /* last packet "must be" short (or a zlp) */
                if (ep->dev->req_pending)
                        ep0start(ep->dev, UDCCS0_IPR, "short IN");
                else
-                       UDCCS0 = UDCCS0_IPR;
+                       udc_ep0_set_UDCCS(dev, UDCCS0_IPR);
 
                count = req->req.length;
                done (ep, req, 0);
                if (count >= EP0_FIFO_SIZE) {
                        count = 100;
                        do {
-                               if ((UDCCS0 & UDCCS0_OPR) != 0) {
+                               if ((udc_ep0_get_UDCCS(dev) & UDCCS0_OPR) != 0) {
                                        /* clear OPR, generate ack */
-                                       UDCCS0 = UDCCS0_OPR;
+                                       udc_ep0_set_UDCCS(dev, UDCCS0_OPR);
                                        break;
                                }
                                count--;
                 * UDCCS_{BO,IO}_RPC are all the same bit value.
                 * UDCCS_{BO,IO}_RNE are all the same bit value.
                 */
-               udccs = *ep->reg_udccs;
+               udccs = udc_ep_get_UDCCS(ep);
                if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
                        break;
                buf = req->req.buf + req->req.actual;
 
                /* read all bytes from this packet */
                if (likely (udccs & UDCCS_BO_RNE)) {
-                       count = 1 + (0x0ff & *ep->reg_ubcr);
+                       count = 1 + (0x0ff & udc_ep_get_UBCR(ep));
                        req->req.actual += min (count, bufferspace);
                } else /* zlp */
                        count = 0;
                        is_short ? "/S" : "",
                        req, req->req.actual, req->req.length);
                while (likely (count-- != 0)) {
-                       u8      byte = (u8) *ep->reg_uddr;
+                       u8      byte = (u8) udc_ep_get_UDDR(ep);
 
                        if (unlikely (bufferspace == 0)) {
                                /* this happens when the driver's buffer
                                bufferspace--;
                        }
                }
-               *ep->reg_udccs =  UDCCS_BO_RPC;
+               udc_ep_set_UDCCS(ep, UDCCS_BO_RPC);
                /* RPC/RSP/RNE could now reflect the other packet buffer */
 
                /* iso is one request per packet */
                if (is_short || req->req.actual == req->req.length) {
                        done (ep, req, 0);
                        if (list_empty(&ep->queue))
-                               pio_irq_disable (ep->bEndpointAddress);
+                               pio_irq_disable(ep);
                        return 1;
                }
 
        buf = req->req.buf + req->req.actual;
        bufferspace = req->req.length - req->req.actual;
 
-       while (UDCCS0 & UDCCS0_RNE) {
+       while (udc_ep_get_UDCCS(ep) & UDCCS0_RNE) {
                byte = (u8) UDDR0;
 
                if (unlikely (bufferspace == 0)) {
                }
        }
 
-       UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
+       udc_ep_set_UDCCS(ep, UDCCS0_OPR | UDCCS0_IPR);
 
        /* completion */
        if (req->req.actual >= req->req.length)
                                        DBG(DBG_VERBOSE, "ep0 config ack%s\n",
                                                dev->has_cfr ?  "" : " raced");
                                        if (dev->has_cfr)
-                                               UDCCFR = UDCCFR_AREN|UDCCFR_ACM
-                                                       |UDCCFR_MB1;
+                                               udc_set_reg(dev, UDCCFR, UDCCFR_AREN |
+                                                           UDCCFR_ACM | UDCCFR_MB1);
                                        done(ep, req, 0);
                                        dev->ep0state = EP0_END_XFER;
                                        local_irq_restore (flags);
                                }
                                if (dev->req_pending)
                                        ep0start(dev, UDCCS0_IPR, "OUT");
-                               if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
+                               if (length == 0 || ((udc_ep0_get_UDCCS(dev) & UDCCS0_RNE) != 0
                                                && read_ep0_fifo(ep, req))) {
                                        ep0_idle(dev);
                                        done(ep, req, 0);
                        }
                /* can the FIFO can satisfy the request immediately? */
                } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
-                       if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
+                       if ((udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS) != 0
                                        && write_fifo(ep, req))
                                req = NULL;
-               } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
+               } else if ((udc_ep_get_UDCCS(ep) & UDCCS_BO_RFS) != 0
                                && read_fifo(ep, req)) {
                        req = NULL;
                }
 
                if (likely(req && ep->ep.desc))
-                       pio_irq_enable(ep->bEndpointAddress);
+                       pio_irq_enable(ep);
        }
 
        /* pio or dma irq handler advances the queue. */
                done(ep, req, status);
        }
        if (ep->ep.desc)
-               pio_irq_disable (ep->bEndpointAddress);
+               pio_irq_disable(ep);
 }
 
 
        local_irq_save(flags);
 
        if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-                       && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
+                       && ((udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS) == 0
                           || !list_empty(&ep->queue))) {
                local_irq_restore(flags);
                return -EAGAIN;
        }
 
        /* FST bit is the same for control, bulk in, bulk out, interrupt in */
-       *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
+       udc_ep_set_UDCCS(ep, UDCCS_BI_FST|UDCCS_BI_FTF);
 
        /* ep0 needs special care */
        if (!ep->ep.desc) {
        } else {
                unsigned i;
                for (i = 0; i < 1000; i += 20) {
-                       if (*ep->reg_udccs & UDCCS_BI_SST)
+                       if (udc_ep_get_UDCCS(ep) & UDCCS_BI_SST)
                                break;
                        udelay(20);
                }
        if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
                return -EOPNOTSUPP;
        if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
-                       || (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
+                       || (udc_ep_get_UDCCS(ep) & UDCCS_BO_RFS) == 0)
                return 0;
        else
-               return (*ep->reg_ubcr & 0xfff) + 1;
+               return (udc_ep_get_UBCR(ep) & 0xfff) + 1;
 }
 
 static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
 
        /* for OUT, just read and discard the FIFO contents. */
        if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
-               while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
-                       (void) *ep->reg_uddr;
+               while (((udc_ep_get_UDCCS(ep)) & UDCCS_BO_RNE) != 0)
+                       (void)udc_ep_get_UDDR(ep);
                return;
        }
 
        /* most IN status is the same, but ISO can't stall */
-       *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
+       udc_ep_set_UDCCS(ep, UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
                | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                       ? 0 : UDCCS_BI_SST);
+                       ? 0 : UDCCS_BI_SST));
 }
 
 
 
 static int pxa25x_udc_get_frame(struct usb_gadget *_gadget)
 {
-       return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
+       struct pxa25x_udc       *dev;
+
+       dev = container_of(_gadget, struct pxa25x_udc, gadget);
+       return ((udc_get_reg(dev, UFNRH) & 0x07) << 8) |
+               (udc_get_reg(dev, UFNRL) & 0xff);
 }
 
 static int pxa25x_udc_wakeup(struct usb_gadget *_gadget)
 {
+       struct pxa25x_udc       *udc;
+
+       udc = container_of(_gadget, struct pxa25x_udc, gadget);
+
        /* host may not have enabled remote wakeup */
-       if ((UDCCS0 & UDCCS0_DRWF) == 0)
+       if ((udc_ep0_get_UDCCS(udc) & UDCCS0_DRWF) == 0)
                return -EHOSTUNREACH;
-       udc_set_mask_UDCCR(UDCCR_RSM);
+       udc_set_mask_UDCCR(udc, UDCCR_RSM);
        return 0;
 }
 
        /* registers for device and ep0 */
        seq_printf(m,
                "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-               UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
+               udc_get_reg(dev, UICR1), udc_get_reg(dev, UICR0),
+               udc_get_reg(dev, USIR1), udc_get_reg(dev, USIR0),
+               udc_get_reg(dev, UFNRH), udc_get_reg(dev, UFNRL));
 
-       tmp = UDCCR;
+       tmp = udc_get_reg(dev, UDCCR);
        seq_printf(m,
                "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
                (tmp & UDCCR_REM) ? " rem" : "",
                (tmp & UDCCR_UDA) ? " uda" : "",
                (tmp & UDCCR_UDE) ? " ude" : "");
 
-       tmp = UDCCS0;
+       tmp = udc_ep0_get_UDCCS(dev);
        seq_printf(m,
                "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
                (tmp & UDCCS0_SA) ? " sa" : "",
                (tmp & UDCCS0_OPR) ? " opr" : "");
 
        if (dev->has_cfr) {
-               tmp = UDCCFR;
+               tmp = udc_get_reg(dev, UDCCFR);
                seq_printf(m,
                        "udccfr %02X =%s%s\n", tmp,
                        (tmp & UDCCFR_AREN) ? " aren" : "",
                        desc = ep->ep.desc;
                        if (!desc)
                                continue;
-                       tmp = *dev->ep [i].reg_udccs;
+                       tmp = udc_ep_get_UDCCS(&dev->ep[i]);
                        seq_printf(m,
                                "%s max %d %s udccs %02x irqs %lu\n",
                                ep->ep.name, usb_endpoint_maxp(desc),
 static void udc_disable(struct pxa25x_udc *dev)
 {
        /* block all irqs */
-       udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
-       UICR0 = UICR1 = 0xff;
-       UFNRH = UFNRH_SIM;
+       udc_set_mask_UDCCR(dev, UDCCR_SRM|UDCCR_REM);
+       udc_set_reg(dev, UICR0, 0xff);
+       udc_set_reg(dev, UICR1, 0xff);
+       udc_set_reg(dev, UFNRH, UFNRH_SIM);
 
        /* if hardware supports it, disconnect from usb */
        pullup_off();
 
-       udc_clear_mask_UDCCR(UDCCR_UDE);
+       udc_clear_mask_UDCCR(dev, UDCCR_UDE);
 
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
  */
 static void udc_enable (struct pxa25x_udc *dev)
 {
-       udc_clear_mask_UDCCR(UDCCR_UDE);
+       udc_clear_mask_UDCCR(dev, UDCCR_UDE);
 
        /* try to clear these bits before we enable the udc */
-       udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
+       udc_ack_int_UDCCR(dev, UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
 
        ep0_idle(dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
         * - if RESET is already in progress, ack interrupt
         * - unmask reset interrupt
         */
-       udc_set_mask_UDCCR(UDCCR_UDE);
-       if (!(UDCCR & UDCCR_UDA))
-               udc_ack_int_UDCCR(UDCCR_RSTIR);
+       udc_set_mask_UDCCR(dev, UDCCR_UDE);
+       if (!(udc_get_reg(dev, UDCCR) & UDCCR_UDA))
+               udc_ack_int_UDCCR(dev, UDCCR_RSTIR);
 
        if (dev->has_cfr /* UDC_RES2 is defined */) {
                /* pxa255 (a0+) can avoid a set_config race that could
                 * prevent gadget drivers from configuring correctly
                 */
-               UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
+               udc_set_reg(dev, UDCCFR, UDCCFR_ACM | UDCCFR_MB1);
        } else {
                /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
                 * which could result in missing packets and interrupts.
                 * double buffers or not; ACM/AREN bits fit into the holes.
                 * zero bits (like USIR0_IRx) disable double buffering.
                 */
-               UDC_RES1 = 0x00;
-               UDC_RES2 = 0x00;
+               udc_set_reg(dev, UDC_RES1, 0x00);
+               udc_set_reg(dev, UDC_RES2, 0x00);
        }
 
        /* enable suspend/resume and reset irqs */
-       udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
+       udc_clear_mask_UDCCR(dev, UDCCR_SRM | UDCCR_REM);
 
        /* enable ep0 irqs */
-       UICR0 &= ~UICR0_IM0;
+       udc_set_reg(dev, UICR0, udc_get_reg(dev, UICR0) & ~UICR0_IM0);
 
        /* if hardware supports it, pullup D+ and wait for reset */
        pullup_on();
 
        local_irq_disable();
        if (dev->ep0state == EP0_STALL
-                       && (UDCCS0 & UDCCS0_FST) == 0
-                       && (UDCCS0 & UDCCS0_SST) == 0) {
-               UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
+                       && (udc_ep0_get_UDCCS(dev) & UDCCS0_FST) == 0
+                       && (udc_ep0_get_UDCCS(dev) & UDCCS0_SST) == 0) {
+               udc_ep0_set_UDCCS(dev, UDCCS0_FST|UDCCS0_FTF);
                DBG(DBG_VERBOSE, "ep0 re-stall\n");
                start_watchdog(dev);
        }
 
 static void handle_ep0 (struct pxa25x_udc *dev)
 {
-       u32                     udccs0 = UDCCS0;
+       u32                     udccs0 = udc_ep0_get_UDCCS(dev);
        struct pxa25x_ep        *ep = &dev->ep [0];
        struct pxa25x_request   *req;
        union {
        /* clear stall status */
        if (udccs0 & UDCCS0_SST) {
                nuke(ep, -EPIPE);
-               UDCCS0 = UDCCS0_SST;
+               udc_ep0_set_UDCCS(dev, UDCCS0_SST);
                del_timer(&dev->timer);
                ep0_idle(dev);
        }
        switch (dev->ep0state) {
        case EP0_IDLE:
                /* late-breaking status? */
-               udccs0 = UDCCS0;
+               udccs0 = udc_ep0_get_UDCCS(dev);
 
                /* start control request? */
                if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
 
                        /* read SETUP packet */
                        for (i = 0; i < 8; i++) {
-                               if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
+                               if (unlikely(!(udc_ep0_get_UDCCS(dev) & UDCCS0_RNE))) {
 bad_setup:
                                        DMSG("SETUP %d!\n", i);
                                        goto stall;
                                }
                                u.raw [i] = (u8) UDDR0;
                        }
-                       if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
+                       if (unlikely((udc_ep0_get_UDCCS(dev) & UDCCS0_RNE) != 0))
                                goto bad_setup;
 
 got_setup:
                                         */
                                }
                                DBG(DBG_VERBOSE, "protocol STALL, "
-                                       "%02x err %d\n", UDCCS0, i);
+                                       "%02x err %d\n", udc_ep0_get_UDCCS(dev), i);
 stall:
                                /* the watchdog timer helps deal with cases
                                 * where udc seems to clear FST wrongly, and
                         * - IPR cleared
                         * - OPR got set, without SA (likely status stage)
                         */
-                       UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
+                       udc_ep0_set_UDCCS(dev, udccs0 & (UDCCS0_SA|UDCCS0_OPR));
                }
                break;
        case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
                if (udccs0 & UDCCS0_OPR) {
-                       UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
+                       udc_ep0_set_UDCCS(dev, UDCCS0_OPR|UDCCS0_FTF);
                        DBG(DBG_VERBOSE, "ep0in premature status\n");
                        if (req)
                                done(ep, req, 0);
                 * also appears after some config change events.
                 */
                if (udccs0 & UDCCS0_OPR)
-                       UDCCS0 = UDCCS0_OPR;
+                       udc_ep0_set_UDCCS(dev, UDCCS0_OPR);
                ep0_idle(dev);
                break;
        case EP0_STALL:
-               UDCCS0 = UDCCS0_FST;
+               udc_ep0_set_UDCCS(dev, UDCCS0_FST);
                break;
        }
-       USIR0 = USIR0_IR0;
+       udc_set_reg(dev, USIR0, USIR0_IR0);
 }
 
 static void handle_ep(struct pxa25x_ep *ep)
 
                // TODO check FST handling
 
-               udccs = *ep->reg_udccs;
+               udccs = udc_ep_get_UDCCS(ep);
                if (unlikely(is_in)) {  /* irq from TPC, SST, or (ISO) TUR */
                        tmp = UDCCS_BI_TUR;
                        if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
                                tmp |= UDCCS_BI_SST;
                        tmp &= udccs;
                        if (likely (tmp))
-                               *ep->reg_udccs = tmp;
+                               udc_ep_set_UDCCS(ep, tmp);
                        if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
                                completed = write_fifo(ep, req);
 
                                tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
                        tmp &= udccs;
                        if (likely(tmp))
-                               *ep->reg_udccs = tmp;
+                               udc_ep_set_UDCCS(ep, tmp);
 
                        /* fifos can hold packets, ready for reading... */
                        if (likely(req)) {
                                completed = read_fifo(ep, req);
                        } else
-                               pio_irq_disable (ep->bEndpointAddress);
+                               pio_irq_disable(ep);
                }
                ep->pio_irqs++;
        } while (completed);
 
        dev->stats.irqs++;
        do {
-               u32             udccr = UDCCR;
+               u32             udccr = udc_get_reg(dev, UDCCR);
 
                handled = 0;
 
                /* SUSpend Interrupt Request */
                if (unlikely(udccr & UDCCR_SUSIR)) {
-                       udc_ack_int_UDCCR(UDCCR_SUSIR);
+                       udc_ack_int_UDCCR(dev, UDCCR_SUSIR);
                        handled = 1;
                        DBG(DBG_VERBOSE, "USB suspend\n");
 
 
                /* RESume Interrupt Request */
                if (unlikely(udccr & UDCCR_RESIR)) {
-                       udc_ack_int_UDCCR(UDCCR_RESIR);
+                       udc_ack_int_UDCCR(dev, UDCCR_RESIR);
                        handled = 1;
                        DBG(DBG_VERBOSE, "USB resume\n");
 
 
                /* ReSeT Interrupt Request - USB reset */
                if (unlikely(udccr & UDCCR_RSTIR)) {
-                       udc_ack_int_UDCCR(UDCCR_RSTIR);
+                       udc_ack_int_UDCCR(dev, UDCCR_RSTIR);
                        handled = 1;
 
-                       if ((UDCCR & UDCCR_UDA) == 0) {
+                       if ((udc_get_reg(dev, UDCCR) & UDCCR_UDA) == 0) {
                                DBG(DBG_VERBOSE, "USB reset start\n");
 
                                /* reset driver and endpoints,
                        }
 
                } else {
-                       u32     usir0 = USIR0 & ~UICR0;
-                       u32     usir1 = USIR1 & ~UICR1;
+                       u32     usir0 = udc_get_reg(dev, USIR0) &
+                                       ~udc_get_reg(dev, UICR0);
+                       u32     usir1 = udc_get_reg(dev, USIR1) &
+                                       ~udc_get_reg(dev, UICR1);
                        int     i;
 
                        if (unlikely (!usir0 && !usir1))
 
                                if (i && (usir0 & tmp)) {
                                        handle_ep(&dev->ep[i]);
-                                       USIR0 |= tmp;
+                                       udc_set_reg(dev, USIR0,
+                                               udc_get_reg(dev, USIR0) | tmp);
                                        handled = 1;
                                }
 #ifndef        CONFIG_USB_PXA25X_SMALL
                                if (usir1 & tmp) {
                                        handle_ep(&dev->ep[i+8]);
-                                       USIR1 |= tmp;
+                                       udc_set_reg(dev, USIR1,
+                                               udc_get_reg(dev, USIR1) | tmp);
                                        handled = 1;
                                }
 #endif
                                                USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
-               .reg_udccs      = &UDCCS0,
-               .reg_uddr       = &UDDR0,
+               .regoff_udccs   = UDCCS0,
+               .regoff_uddr    = UDDR0,
        },
 
        /* first group of endpoints */
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 1,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS1,
-               .reg_uddr       = &UDDR1,
+               .regoff_udccs   = UDCCS1,
+               .regoff_uddr    = UDDR1,
        },
        .ep[2] = {
                .ep = {
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 2,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS2,
-               .reg_ubcr       = &UBCR2,
-               .reg_uddr       = &UDDR2,
+               .regoff_udccs   = UDCCS2,
+               .regoff_ubcr    = UBCR2,
+               .regoff_uddr    = UDDR2,
        },
 #ifndef CONFIG_USB_PXA25X_SMALL
        .ep[3] = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 3,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS3,
-               .reg_uddr       = &UDDR3,
+               .regoff_udccs   = UDCCS3,
+               .regoff_uddr    = UDDR3,
        },
        .ep[4] = {
                .ep = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 4,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS4,
-               .reg_ubcr       = &UBCR4,
-               .reg_uddr       = &UDDR4,
+               .regoff_udccs   = UDCCS4,
+               .regoff_ubcr    = UBCR4,
+               .regoff_uddr    = UDDR4,
        },
        .ep[5] = {
                .ep = {
                .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 5,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS5,
-               .reg_uddr       = &UDDR5,
+               .regoff_udccs   = UDCCS5,
+               .regoff_uddr    = UDDR5,
        },
 
        /* second group of endpoints */
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 6,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS6,
-               .reg_uddr       = &UDDR6,
+               .regoff_udccs   = UDCCS6,
+               .regoff_uddr    = UDDR6,
        },
        .ep[7] = {
                .ep = {
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 7,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS7,
-               .reg_ubcr       = &UBCR7,
-               .reg_uddr       = &UDDR7,
+               .regoff_udccs   = UDCCS7,
+               .regoff_ubcr    = UBCR7,
+               .regoff_uddr    = UDDR7,
        },
        .ep[8] = {
                .ep = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 8,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS8,
-               .reg_uddr       = &UDDR8,
+               .regoff_udccs   = UDCCS8,
+               .regoff_uddr    = UDDR8,
        },
        .ep[9] = {
                .ep = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 9,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS9,
-               .reg_ubcr       = &UBCR9,
-               .reg_uddr       = &UDDR9,
+               .regoff_udccs   = UDCCS9,
+               .regoff_ubcr    = UBCR9,
+               .regoff_uddr    = UDDR9,
        },
        .ep[10] = {
                .ep = {
                .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 10,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS10,
-               .reg_uddr       = &UDDR10,
+               .regoff_udccs   = UDCCS10,
+               .regoff_uddr    = UDDR10,
        },
 
        /* third group of endpoints */
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 11,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS11,
-               .reg_uddr       = &UDDR11,
+               .regoff_udccs   = UDCCS11,
+               .regoff_uddr    = UDDR11,
        },
        .ep[12] = {
                .ep = {
                .fifo_size      = BULK_FIFO_SIZE,
                .bEndpointAddress = 12,
                .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS12,
-               .reg_ubcr       = &UBCR12,
-               .reg_uddr       = &UDDR12,
+               .regoff_udccs   = UDCCS12,
+               .regoff_ubcr    = UBCR12,
+               .regoff_uddr    = UDDR12,
        },
        .ep[13] = {
                .ep = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 13,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS13,
-               .reg_uddr       = &UDDR13,
+               .regoff_udccs   = UDCCS13,
+               .regoff_uddr    = UDDR13,
        },
        .ep[14] = {
                .ep = {
                .fifo_size      = ISO_FIFO_SIZE,
                .bEndpointAddress = 14,
                .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS14,
-               .reg_ubcr       = &UBCR14,
-               .reg_uddr       = &UDDR14,
+               .regoff_udccs   = UDCCS14,
+               .regoff_ubcr    = UBCR14,
+               .regoff_uddr    = UDDR14,
        },
        .ep[15] = {
                .ep = {
                .fifo_size      = INT_FIFO_SIZE,
                .bEndpointAddress = USB_DIR_IN | 15,
                .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS15,
-               .reg_uddr       = &UDDR15,
+               .regoff_udccs   = UDCCS15,
+               .regoff_uddr    = UDDR15,
        },
 #endif /* !CONFIG_USB_PXA25X_SMALL */
 };
        struct pxa25x_udc *dev = &memory;
        int retval, irq;
        u32 chiprev;
+       struct resource *res;
 
        pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
 
        if (irq < 0)
                return -ENODEV;
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pxa25x_udc_reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pxa25x_udc_reg_base))
+               return PTR_ERR(pxa25x_udc_reg_base);
+
        dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk))
                return PTR_ERR(dev->clk);