config USB_ISP1760
        tristate "NXP ISP 1760/1761 support"
        depends on USB || USB_GADGET
+       select REGMAP_MMIO
        help
          Say Y or M here if your system as an ISP1760 USB host controller
          or an ISP1761 USB dual-role controller.
 
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 
 
 static void isp1760_init_core(struct isp1760_device *isp)
 {
-       u32 otgctrl;
-       u32 hwmode;
+       struct isp1760_hcd *hcd = &isp->hcd;
+       struct isp1760_udc *udc = &isp->udc;
 
        /* Low-level chip reset */
        if (isp->rst_gpio) {
         * Reset the host controller, including the CPU interface
         * configuration.
         */
-       isp1760_write32(isp->regs, HC_RESET_REG, SW_RESET_RESET_ALL);
+       isp1760_field_set(hcd->fields, SW_RESET_RESET_ALL);
        msleep(100);
 
        /* Setup HW Mode Control: This assumes a level active-low interrupt */
-       hwmode = HW_DATA_BUS_32BIT;
-
        if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16)
-               hwmode &= ~HW_DATA_BUS_32BIT;
+               isp1760_field_clear(hcd->fields, HW_DATA_BUS_WIDTH);
        if (isp->devflags & ISP1760_FLAG_ANALOG_OC)
-               hwmode |= HW_ANA_DIGI_OC;
+               isp1760_field_set(hcd->fields, HW_ANA_DIGI_OC);
        if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH)
-               hwmode |= HW_DACK_POL_HIGH;
+               isp1760_field_set(hcd->fields, HW_DACK_POL_HIGH);
        if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
-               hwmode |= HW_DREQ_POL_HIGH;
+               isp1760_field_set(hcd->fields, HW_DREQ_POL_HIGH);
        if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH)
-               hwmode |= HW_INTR_HIGH_ACT;
+               isp1760_field_set(hcd->fields, HW_INTR_HIGH_ACT);
        if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
-               hwmode |= HW_INTR_EDGE_TRIG;
+               isp1760_field_set(hcd->fields, HW_INTR_EDGE_TRIG);
 
        /*
         * The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
         * spurious interrupts during HCD registration.
         */
        if (isp->devflags & ISP1760_FLAG_ISP1761) {
-               isp1760_write32(isp->regs, DC_MODE, 0);
-               hwmode |= HW_COMN_IRQ;
+               isp1760_reg_write(udc->regs, ISP176x_DC_MODE, 0);
+               isp1760_field_set(hcd->fields, HW_COMN_IRQ);
        }
 
-       /*
-        * We have to set this first in case we're in 16-bit mode.
-        * Write it twice to ensure correct upper bits if switching
-        * to 16-bit mode.
-        */
-       isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode);
-       isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode);
-
        /*
         * PORT 1 Control register of the ISP1760 is the OTG control register
         * on ISP1761.
         * when OTG is requested.
         */
        if ((isp->devflags & ISP1760_FLAG_ISP1761) &&
-           (isp->devflags & ISP1760_FLAG_OTG_EN))
-               otgctrl = ((HW_DM_PULLDOWN | HW_DP_PULLDOWN) << 16)
-                       | HW_OTG_DISABLE;
-       else
-               otgctrl = (HW_SW_SEL_HC_DC << 16)
-                       | (HW_VBUS_DRV | HW_SEL_CP_EXT);
-
-       isp1760_write32(isp->regs, HC_PORT1_CTRL, otgctrl);
+           (isp->devflags & ISP1760_FLAG_OTG_EN)) {
+               isp1760_field_set(hcd->fields, HW_DM_PULLDOWN);
+               isp1760_field_set(hcd->fields, HW_DP_PULLDOWN);
+               isp1760_field_set(hcd->fields, HW_OTG_DISABLE);
+       } else {
+               isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC);
+               isp1760_field_set(hcd->fields, HW_VBUS_DRV);
+               isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
+       }
 
        dev_info(isp->dev, "bus width: %u, oc: %s\n",
                 isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
 
 void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
 {
-       isp1760_write32(isp->regs, HW_OTG_CTRL_SET,
-                       enable ? HW_DP_PULLUP : HW_DP_PULLUP << 16);
+       struct isp1760_udc *udc = &isp->udc;
+
+       if (enable)
+               isp1760_field_set(udc->fields, HW_DP_PULLUP);
+       else
+               isp1760_field_set(udc->fields, HW_DP_PULLUP_CLEAR);
 }
 
+static const struct regmap_range isp176x_hc_volatile_ranges[] = {
+       regmap_reg_range(ISP176x_HC_USBCMD, ISP176x_HC_ATL_PTD_LASTPTD),
+       regmap_reg_range(ISP176x_HC_BUFFER_STATUS, ISP176x_HC_MEMORY),
+       regmap_reg_range(ISP176x_HC_INTERRUPT, ISP176x_HC_ATL_IRQ_MASK_AND),
+};
+
+static const struct regmap_access_table isp176x_hc_volatile_table = {
+       .yes_ranges     = isp176x_hc_volatile_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(isp176x_hc_volatile_ranges),
+};
+
+static struct regmap_config isp1760_hc_regmap_conf = {
+       .name = "isp1760-hc",
+       .reg_bits = 16,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .fast_io = true,
+       .max_register = ISP176x_HC_MEMORY,
+       .volatile_table = &isp176x_hc_volatile_table,
+};
+
+static const struct reg_field isp1760_hc_reg_fields[] = {
+       [HCS_PPC]               = REG_FIELD(ISP176x_HC_HCSPARAMS, 4, 4),
+       [HCS_N_PORTS]           = REG_FIELD(ISP176x_HC_HCSPARAMS, 0, 3),
+       [HCC_ISOC_CACHE]        = REG_FIELD(ISP176x_HC_HCCPARAMS, 7, 7),
+       [HCC_ISOC_THRES]        = REG_FIELD(ISP176x_HC_HCCPARAMS, 4, 6),
+       [CMD_LRESET]            = REG_FIELD(ISP176x_HC_USBCMD, 7, 7),
+       [CMD_RESET]             = REG_FIELD(ISP176x_HC_USBCMD, 1, 1),
+       [CMD_RUN]               = REG_FIELD(ISP176x_HC_USBCMD, 0, 0),
+       [STS_PCD]               = REG_FIELD(ISP176x_HC_USBSTS, 2, 2),
+       [HC_FRINDEX]            = REG_FIELD(ISP176x_HC_FRINDEX, 0, 13),
+       [FLAG_CF]               = REG_FIELD(ISP176x_HC_CONFIGFLAG, 0, 0),
+       [PORT_OWNER]            = REG_FIELD(ISP176x_HC_PORTSC1, 13, 13),
+       [PORT_POWER]            = REG_FIELD(ISP176x_HC_PORTSC1, 12, 12),
+       [PORT_LSTATUS]          = REG_FIELD(ISP176x_HC_PORTSC1, 10, 11),
+       [PORT_RESET]            = REG_FIELD(ISP176x_HC_PORTSC1, 8, 8),
+       [PORT_SUSPEND]          = REG_FIELD(ISP176x_HC_PORTSC1, 7, 7),
+       [PORT_RESUME]           = REG_FIELD(ISP176x_HC_PORTSC1, 6, 6),
+       [PORT_PE]               = REG_FIELD(ISP176x_HC_PORTSC1, 2, 2),
+       [PORT_CSC]              = REG_FIELD(ISP176x_HC_PORTSC1, 1, 1),
+       [PORT_CONNECT]          = REG_FIELD(ISP176x_HC_PORTSC1, 0, 0),
+       [ALL_ATX_RESET]         = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 31, 31),
+       [HW_ANA_DIGI_OC]        = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 15, 15),
+       [HW_COMN_IRQ]           = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 10, 10),
+       [HW_DATA_BUS_WIDTH]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 8, 8),
+       [HW_DACK_POL_HIGH]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 6, 6),
+       [HW_DREQ_POL_HIGH]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 5, 5),
+       [HW_INTR_HIGH_ACT]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 2, 2),
+       [HW_INTR_EDGE_TRIG]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 1, 1),
+       [HW_GLOBAL_INTR_EN]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 0, 0),
+       [SW_RESET_RESET_ALL]    = REG_FIELD(ISP176x_HC_RESET, 0, 0),
+       [INT_BUF_FILL]          = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 1, 1),
+       [ATL_BUF_FILL]          = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 0, 0),
+       [MEM_BANK_SEL]          = REG_FIELD(ISP176x_HC_MEMORY, 16, 17),
+       [MEM_START_ADDR]        = REG_FIELD(ISP176x_HC_MEMORY, 0, 15),
+       [HC_INT_ENABLE]         = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 8),
+};
+
+static const struct regmap_range isp176x_dc_volatile_ranges[] = {
+       regmap_reg_range(ISP176x_DC_EPMAXPKTSZ, ISP176x_DC_EPTYPE),
+       regmap_reg_range(ISP176x_DC_BUFLEN, ISP176x_DC_EPINDEX),
+       regmap_reg_range(ISP1761_DC_OTG_CTRL_SET, ISP1761_DC_OTG_CTRL_CLEAR),
+};
+
+static const struct regmap_access_table isp176x_dc_volatile_table = {
+       .yes_ranges     = isp176x_dc_volatile_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(isp176x_dc_volatile_ranges),
+};
+
+static struct regmap_config isp1761_dc_regmap_conf = {
+       .name = "isp1761-dc",
+       .reg_bits = 16,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .fast_io = true,
+       .max_register = ISP1761_DC_OTG_CTRL_CLEAR,
+       .volatile_table = &isp176x_dc_volatile_table,
+};
+
+static const struct reg_field isp1761_dc_reg_fields[] = {
+       [DC_DEVEN]              = REG_FIELD(ISP176x_DC_ADDRESS, 7, 7),
+       [DC_DEVADDR]            = REG_FIELD(ISP176x_DC_ADDRESS, 0, 6),
+       [DC_VBUSSTAT]           = REG_FIELD(ISP176x_DC_MODE, 8, 8),
+       [DC_SFRESET]            = REG_FIELD(ISP176x_DC_MODE, 4, 4),
+       [DC_GLINTENA]           = REG_FIELD(ISP176x_DC_MODE, 3, 3),
+       [DC_CDBGMOD_ACK]        = REG_FIELD(ISP176x_DC_INTCONF, 6, 6),
+       [DC_DDBGMODIN_ACK]      = REG_FIELD(ISP176x_DC_INTCONF, 4, 4),
+       [DC_DDBGMODOUT_ACK]     = REG_FIELD(ISP176x_DC_INTCONF, 2, 2),
+       [DC_INTPOL]             = REG_FIELD(ISP176x_DC_INTCONF, 0, 0),
+       [DC_IEPRXTX_7]          = REG_FIELD(ISP176x_DC_INTENABLE, 25, 25),
+       [DC_IEPRXTX_6]          = REG_FIELD(ISP176x_DC_INTENABLE, 23, 23),
+       [DC_IEPRXTX_5]          = REG_FIELD(ISP176x_DC_INTENABLE, 21, 21),
+       [DC_IEPRXTX_4]          = REG_FIELD(ISP176x_DC_INTENABLE, 19, 19),
+       [DC_IEPRXTX_3]          = REG_FIELD(ISP176x_DC_INTENABLE, 17, 17),
+       [DC_IEPRXTX_2]          = REG_FIELD(ISP176x_DC_INTENABLE, 15, 15),
+       [DC_IEPRXTX_1]          = REG_FIELD(ISP176x_DC_INTENABLE, 13, 13),
+       [DC_IEPRXTX_0]          = REG_FIELD(ISP176x_DC_INTENABLE, 11, 11),
+       [DC_IEP0SETUP]          = REG_FIELD(ISP176x_DC_INTENABLE, 8, 8),
+       [DC_IEVBUS]             = REG_FIELD(ISP176x_DC_INTENABLE, 7, 7),
+       [DC_IEHS_STA]           = REG_FIELD(ISP176x_DC_INTENABLE, 5, 5),
+       [DC_IERESM]             = REG_FIELD(ISP176x_DC_INTENABLE, 4, 4),
+       [DC_IESUSP]             = REG_FIELD(ISP176x_DC_INTENABLE, 3, 3),
+       [DC_IEBRST]             = REG_FIELD(ISP176x_DC_INTENABLE, 0, 0),
+       [DC_EP0SETUP]           = REG_FIELD(ISP176x_DC_EPINDEX, 5, 5),
+       [DC_ENDPIDX]            = REG_FIELD(ISP176x_DC_EPINDEX, 1, 4),
+       [DC_EPDIR]              = REG_FIELD(ISP176x_DC_EPINDEX, 0, 0),
+       [DC_CLBUF]              = REG_FIELD(ISP176x_DC_CTRLFUNC, 4, 4),
+       [DC_VENDP]              = REG_FIELD(ISP176x_DC_CTRLFUNC, 3, 3),
+       [DC_DSEN]               = REG_FIELD(ISP176x_DC_CTRLFUNC, 2, 2),
+       [DC_STATUS]             = REG_FIELD(ISP176x_DC_CTRLFUNC, 1, 1),
+       [DC_STALL]              = REG_FIELD(ISP176x_DC_CTRLFUNC, 0, 0),
+       [DC_BUFLEN]             = REG_FIELD(ISP176x_DC_BUFLEN, 0, 15),
+       [DC_FFOSZ]              = REG_FIELD(ISP176x_DC_EPMAXPKTSZ, 0, 10),
+       [DC_EPENABLE]           = REG_FIELD(ISP176x_DC_EPTYPE, 3, 3),
+       [DC_ENDPTYP]            = REG_FIELD(ISP176x_DC_EPTYPE, 0, 1),
+       [DC_UFRAMENUM]          = REG_FIELD(ISP176x_DC_FRAMENUM, 11, 13),
+       [DC_FRAMENUM]           = REG_FIELD(ISP176x_DC_FRAMENUM, 0, 10),
+       [HW_OTG_DISABLE]        = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 10, 10),
+       [HW_SW_SEL_HC_DC]       = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 7, 7),
+       [HW_VBUS_DRV]           = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 4, 4),
+       [HW_SEL_CP_EXT]         = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 3, 3),
+       [HW_DM_PULLDOWN]        = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 2, 2),
+       [HW_DP_PULLDOWN]        = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 1, 1),
+       [HW_DP_PULLUP]          = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 0, 0),
+       [HW_OTG_DISABLE_CLEAR]  = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 10, 10),
+       [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 7, 7),
+       [HW_VBUS_DRV_CLEAR]     = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 4, 4),
+       [HW_SEL_CP_EXT_CLEAR]   = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 3, 3),
+       [HW_DM_PULLDOWN_CLEAR]  = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 2, 2),
+       [HW_DP_PULLDOWN_CLEAR]  = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 1, 1),
+       [HW_DP_PULLUP_CLEAR]    = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 0, 0),
+};
+
 int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
                     struct device *dev, unsigned int devflags)
 {
        struct isp1760_device *isp;
+       struct isp1760_hcd *hcd;
+       struct isp1760_udc *udc;
        bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761);
+       struct regmap_field *f;
+       void __iomem *base;
        int ret;
+       int i;
 
        /*
         * If neither the HCD not the UDC is enabled return an error, as no
 
        isp->dev = dev;
        isp->devflags = devflags;
+       hcd = &isp->hcd;
+       udc = &isp->udc;
+
+       if (devflags & ISP1760_FLAG_BUS_WIDTH_16) {
+               isp1760_hc_regmap_conf.val_bits = 16;
+               isp1761_dc_regmap_conf.val_bits = 16;
+       }
 
        isp->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH);
        if (IS_ERR(isp->rst_gpio))
                return PTR_ERR(isp->rst_gpio);
 
-       isp->regs = devm_ioremap_resource(dev, mem);
-       if (IS_ERR(isp->regs))
-               return PTR_ERR(isp->regs);
+       hcd->base = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(hcd->base))
+               return PTR_ERR(hcd->base);
+
+       hcd->regs = devm_regmap_init_mmio(dev, base, &isp1760_hc_regmap_conf);
+       if (IS_ERR(hcd->regs))
+               return PTR_ERR(hcd->regs);
+
+       for (i = 0; i < HC_FIELD_MAX; i++) {
+               f = devm_regmap_field_alloc(dev, hcd->regs,
+                                           isp1760_hc_reg_fields[i]);
+               if (IS_ERR(f))
+                       return PTR_ERR(f);
+
+               hcd->fields[i] = f;
+       }
+
+       udc->regs = devm_regmap_init_mmio(dev, base, &isp1761_dc_regmap_conf);
+       if (IS_ERR(udc->regs))
+               return PTR_ERR(udc->regs);
+
+       for (i = 0; i < DC_FIELD_MAX; i++) {
+               f = devm_regmap_field_alloc(dev, udc->regs,
+                                           isp1761_dc_reg_fields[i]);
+               if (IS_ERR(f))
+                       return PTR_ERR(f);
+
+               udc->fields[i] = f;
+       }
 
        isp1760_init_core(isp);
 
        if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) && !usb_disabled()) {
-               ret = isp1760_hcd_register(&isp->hcd, isp->regs, mem, irq,
+               ret = isp1760_hcd_register(hcd, mem, irq,
                                           irqflags | IRQF_SHARED, dev);
                if (ret < 0)
                        return ret;
        if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && !udc_disabled) {
                ret = isp1760_udc_register(isp, irq, irqflags);
                if (ret < 0) {
-                       isp1760_hcd_unregister(&isp->hcd);
+                       isp1760_hcd_unregister(hcd);
                        return ret;
                }
        }
 
 #define _ISP1760_CORE_H_
 
 #include <linux/ioport.h>
+#include <linux/regmap.h>
 
 #include "isp1760-hcd.h"
 #include "isp1760-udc.h"
 struct isp1760_device {
        struct device *dev;
 
-       void __iomem *regs;
        unsigned int devflags;
        struct gpio_desc *rst_gpio;
 
 
 void isp1760_set_pullup(struct isp1760_device *isp, bool enable);
 
-static inline u32 isp1760_read32(void __iomem *base, u32 reg)
+static inline u32 isp1760_field_read(struct regmap_field **fields, u32 field)
 {
-       return readl(base + reg);
+       unsigned int val;
+
+       regmap_field_read(fields[field], &val);
+
+       return val;
+}
+
+static inline void isp1760_field_write(struct regmap_field **fields, u32 field,
+                                      u32 val)
+{
+       regmap_field_write(fields[field], val);
+}
+
+static inline void isp1760_field_set(struct regmap_field **fields, u32 field)
+{
+       isp1760_field_write(fields, field, 0xFFFFFFFF);
 }
 
-static inline void isp1760_write32(void __iomem *base, u32 reg, u32 val)
+static inline void isp1760_field_clear(struct regmap_field **fields, u32 field)
 {
-       writel(val, base + reg);
+       isp1760_field_write(fields, field, 0);
 }
 
+static inline u32 isp1760_reg_read(struct regmap *regs, u32 reg)
+{
+       unsigned int val;
+
+       regmap_read(regs, reg, &val);
+
+       return val;
+}
+
+static inline void isp1760_reg_write(struct regmap *regs, u32 reg, u32 val)
+{
+       regmap_write(regs, reg, val);
+}
 #endif
 
 #define ATL_PTD_OFFSET         0x0c00
 #define PAYLOAD_OFFSET         0x1000
 
+#define ISP_BANK_0             0x00
+#define ISP_BANK_1             0x01
+#define ISP_BANK_2             0x02
+#define ISP_BANK_3             0x03
+
 #define TO_DW(x)       ((__force __dw)x)
 #define TO_U32(x)      ((__force u32)x)
 
 };
 
 /*
- * Access functions for isp176x registers (addresses 0..0x03FF).
+ * Access functions for isp176x registers regmap fields
  */
-static u32 reg_read32(void __iomem *base, u32 reg)
+static u32 isp1760_hcd_read(struct usb_hcd *hcd, u32 field)
+{
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
+       return isp1760_field_read(priv->fields, field);
+}
+
+static void isp1760_hcd_write(struct usb_hcd *hcd, u32 field, u32 val)
+{
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
+       isp1760_field_write(priv->fields, field, val);
+}
+
+static void isp1760_hcd_set(struct usb_hcd *hcd, u32 field)
+{
+       isp1760_hcd_write(hcd, field, 0xFFFFFFFF);
+}
+
+static void isp1760_hcd_clear(struct usb_hcd *hcd, u32 field)
+{
+       isp1760_hcd_write(hcd, field, 0);
+}
+
+static int isp1760_hcd_set_poll_timeout(struct usb_hcd *hcd, u32 field,
+                                       u32 timeout_us)
+{
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       unsigned int val;
+
+       isp1760_hcd_set(hcd, field);
+
+       return regmap_field_read_poll_timeout(priv->fields[field], val, 1, 1,
+                                             timeout_us);
+}
+
+static int isp1760_hcd_clear_poll_timeout(struct usb_hcd *hcd, u32 field,
+                                         u32 timeout_us)
 {
-       return isp1760_read32(base, reg);
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       unsigned int val;
+
+       isp1760_hcd_clear(hcd, field);
+
+       return regmap_field_read_poll_timeout(priv->fields[field], val, 0, 1,
+                                             timeout_us);
 }
 
-static void reg_write32(void __iomem *base, u32 reg, u32 val)
+static bool isp1760_hcd_is_set(struct usb_hcd *hcd, u32 field)
 {
-       isp1760_write32(base, reg, val);
+       return !!isp1760_hcd_read(hcd, field);
 }
 
 /*
        }
 }
 
-static void mem_reads8(void __iomem *src_base, u32 src_offset, void *dst,
-                                                               u32 bytes)
+static void mem_reads8(struct usb_hcd *hcd, void __iomem *src_base,
+                      u32 src_offset, void *dst, u32 bytes)
 {
-       reg_write32(src_base, HC_MEMORY_REG, src_offset + ISP_BANK(0));
+       isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0);
+       isp1760_hcd_write(hcd, MEM_START_ADDR, src_offset);
+
        ndelay(90);
-       bank_reads8(src_base, src_offset, ISP_BANK(0), dst, bytes);
+
+       bank_reads8(src_base, src_offset, ISP_BANK_0, dst, bytes);
 }
 
 static void mem_writes8(void __iomem *dst_base, u32 dst_offset,
  * Read and write ptds. 'ptd_offset' should be one of ISO_PTD_OFFSET,
  * INT_PTD_OFFSET, and ATL_PTD_OFFSET. 'slot' should be less than 32.
  */
-static void ptd_read(void __iomem *base, u32 ptd_offset, u32 slot,
-                                                               struct ptd *ptd)
+static void ptd_read(struct usb_hcd *hcd, void __iomem *base,
+                    u32 ptd_offset, u32 slot, struct ptd *ptd)
 {
-       reg_write32(base, HC_MEMORY_REG,
-                               ISP_BANK(0) + ptd_offset + slot*sizeof(*ptd));
+       isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0);
+       isp1760_hcd_write(hcd, MEM_START_ADDR,
+                         ptd_offset + slot * sizeof(*ptd));
        ndelay(90);
-       bank_reads8(base, ptd_offset + slot*sizeof(*ptd), ISP_BANK(0),
-                                               (void *) ptd, sizeof(*ptd));
+       bank_reads8(base, ptd_offset + slot * sizeof(*ptd), ISP_BANK_0,
+                   (void *)ptd, sizeof(*ptd));
 }
 
 static void ptd_write(void __iomem *base, u32 ptd_offset, u32 slot,
        qtd->payload_addr = 0;
 }
 
-static int handshake(struct usb_hcd *hcd, u32 reg,
-                     u32 mask, u32 done, int usec)
-{
-       u32 result;
-       int ret;
-
-       ret = readl_poll_timeout_atomic(hcd->regs + reg, result,
-                                       ((result & mask) == done ||
-                                        result == U32_MAX), 1, usec);
-       if (result == U32_MAX)
-               return -ENODEV;
-
-       return ret;
-}
-
 /* reset a non-running (STS_HALT == 1) controller */
 static int ehci_reset(struct usb_hcd *hcd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
 
-       u32 command = reg_read32(hcd->regs, HC_USBCMD);
-
-       command |= CMD_RESET;
-       reg_write32(hcd->regs, HC_USBCMD, command);
        hcd->state = HC_STATE_HALT;
        priv->next_statechange = jiffies;
 
-       return handshake(hcd, HC_USBCMD, CMD_RESET, 0, 250 * 1000);
+       return isp1760_hcd_set_poll_timeout(hcd, CMD_RESET, 250 * 1000);
 }
 
 static struct isp1760_qh *qh_alloc(gfp_t flags)
 /* one-time init, only for memory state */
 static int priv_init(struct usb_hcd *hcd)
 {
-       struct isp1760_hcd              *priv = hcd_to_priv(hcd);
-       u32                     hcc_params;
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       u32 isoc_cache;
+       u32 isoc_thres;
+
        int i;
 
        spin_lock_init(&priv->lock);
        priv->periodic_size = DEFAULT_I_TDPS;
 
        /* controllers may cache some of the periodic schedule ... */
-       hcc_params = reg_read32(hcd->regs, HC_HCCPARAMS);
+       isoc_cache = isp1760_hcd_read(hcd, HCC_ISOC_CACHE);
+       isoc_thres = isp1760_hcd_read(hcd, HCC_ISOC_THRES);
+
        /* full frame cache */
-       if (HCC_ISOC_CACHE(hcc_params))
+       if (isoc_cache)
                priv->i_thresh = 8;
        else /* N microframes cached */
-               priv->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+               priv->i_thresh = 2 + isoc_thres;
 
        return 0;
 }
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
        int result;
-       u32 scratch, hwmode;
+       u32 scratch;
+
+       isp1760_reg_write(priv->regs, ISP176x_HC_SCRATCH, 0xdeadbabe);
 
-       reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe);
        /* Change bus pattern */
-       scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG);
-       scratch = reg_read32(hcd->regs, HC_SCRATCH_REG);
+       scratch = isp1760_reg_read(priv->regs, ISP176x_HC_CHIP_ID);
+       scratch = isp1760_reg_read(priv->regs, ISP176x_HC_SCRATCH);
        if (scratch != 0xdeadbabe) {
                dev_err(hcd->self.controller, "Scratch test failed.\n");
                return -ENODEV;
         * the host controller through the EHCI USB Command register. The device
         * has been reset in core code anyway, so this shouldn't matter.
         */
-       reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0);
-       reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
-       reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
-       reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+       isp1760_reg_write(priv->regs, ISP176x_HC_BUFFER_STATUS, 0);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ATL_PTD_SKIPMAP,
+                         NO_TRANSFER_ACTIVE);
+       isp1760_reg_write(priv->regs, ISP176x_HC_INT_PTD_SKIPMAP,
+                         NO_TRANSFER_ACTIVE);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ISO_PTD_SKIPMAP,
+                         NO_TRANSFER_ACTIVE);
 
        result = ehci_reset(hcd);
        if (result)
        /* Step 11 passed */
 
        /* ATL reset */
-       hwmode = reg_read32(hcd->regs, HC_HW_MODE_CTRL) & ~ALL_ATX_RESET;
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET);
+       isp1760_hcd_set(hcd, ALL_ATX_RESET);
        mdelay(10);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
+       isp1760_hcd_clear(hcd, ALL_ATX_RESET);
 
-       reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK);
-
-       priv->hcs_params = reg_read32(hcd->regs, HC_HCSPARAMS);
+       isp1760_hcd_set(hcd, HC_INT_ENABLE);
 
        return priv_init(hcd);
 }
 
        /* Make sure done map has not triggered from some unlinked transfer */
        if (ptd_offset == ATL_PTD_OFFSET) {
-               priv->atl_done_map |= reg_read32(hcd->regs,
-                                               HC_ATL_PTD_DONEMAP_REG);
+               priv->atl_done_map |= isp1760_reg_read(priv->regs,
+                                               ISP176x_HC_ATL_PTD_DONEMAP);
                priv->atl_done_map &= ~(1 << slot);
        } else {
-               priv->int_done_map |= reg_read32(hcd->regs,
-                                               HC_INT_PTD_DONEMAP_REG);
+               priv->int_done_map |= isp1760_reg_read(priv->regs,
+                                              ISP176x_HC_INT_PTD_DONEMAP);
                priv->int_done_map &= ~(1 << slot);
        }
 
        slots[slot].timestamp = jiffies;
        slots[slot].qtd = qtd;
        slots[slot].qh = qh;
-       ptd_write(hcd->regs, ptd_offset, slot, ptd);
+       ptd_write(priv->base, ptd_offset, slot, ptd);
 
        if (ptd_offset == ATL_PTD_OFFSET) {
-               skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
+               skip_map = isp1760_reg_read(priv->regs,
+                                           ISP176x_HC_ATL_PTD_SKIPMAP);
                skip_map &= ~(1 << qh->slot);
-               reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
+               isp1760_reg_write(priv->regs, ISP176x_HC_ATL_PTD_SKIPMAP,
+                                 skip_map);
        } else {
-               skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
+               skip_map = isp1760_reg_read(priv->regs,
+                                           ISP176x_HC_INT_PTD_SKIPMAP);
                skip_map &= ~(1 << qh->slot);
-               reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
+               isp1760_reg_write(priv->regs, ISP176x_HC_INT_PTD_SKIPMAP,
+                                 skip_map);
        }
 }
 
 static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh,
                                                struct list_head *urb_list)
 {
-       int last_qtd;
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
        struct isp1760_qtd *qtd, *qtd_next;
        struct urb_listitem *urb_listitem;
+       int last_qtd;
 
        list_for_each_entry_safe(qtd, qtd_next, &qh->qtd_list, qtd_list) {
                if (qtd->status < QTD_XFER_COMPLETE)
                        if (qtd->actual_length) {
                                switch (qtd->packet_type) {
                                case IN_PID:
-                                       mem_reads8(hcd->regs, qtd->payload_addr,
-                                                       qtd->data_buffer,
-                                                       qtd->actual_length);
+                                       mem_reads8(hcd, priv->base,
+                                                  qtd->payload_addr,
+                                                  qtd->data_buffer,
+                                                  qtd->actual_length);
                                        fallthrough;
                                case OUT_PID:
                                        qtd->urb->actual_length +=
                        if ((qtd->length) &&
                            ((qtd->packet_type == SETUP_PID) ||
                             (qtd->packet_type == OUT_PID))) {
-                               mem_writes8(hcd->regs, qtd->payload_addr,
-                                               qtd->data_buffer, qtd->length);
+                               mem_writes8(priv->base, qtd->payload_addr,
+                                           qtd->data_buffer, qtd->length);
                        }
 
                        qtd->status = QTD_PAYLOAD_ALLOC;
        int modified;
        int skip_map;
 
-       skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
+       skip_map = isp1760_reg_read(priv->regs, ISP176x_HC_INT_PTD_SKIPMAP);
        priv->int_done_map &= ~skip_map;
-       skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
+       skip_map = isp1760_reg_read(priv->regs, ISP176x_HC_ATL_PTD_SKIPMAP);
        priv->atl_done_map &= ~skip_map;
 
        modified = priv->int_done_map || priv->atl_done_map;
                                continue;
                        }
                        ptd_offset = INT_PTD_OFFSET;
-                       ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd);
+                       ptd_read(hcd, priv->base, INT_PTD_OFFSET, slot, &ptd);
                        state = check_int_transfer(hcd, &ptd,
                                                        slots[slot].qtd->urb);
                } else {
                                continue;
                        }
                        ptd_offset = ATL_PTD_OFFSET;
-                       ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+                       ptd_read(hcd, priv->base, ATL_PTD_OFFSET, slot, &ptd);
                        state = check_atl_transfer(hcd, &ptd,
                                                        slots[slot].qtd->urb);
                }
 
                        qtd->status = QTD_XFER_COMPLETE;
                        if (list_is_last(&qtd->qtd_list, &qh->qtd_list) ||
-                                                       is_short_bulk(qtd))
+                           is_short_bulk(qtd))
                                qtd = NULL;
                        else
                                qtd = list_entry(qtd->qtd_list.next,
        if (!(hcd->state & HC_STATE_RUNNING))
                goto leave;
 
-       imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
+       imask = isp1760_reg_read(priv->regs, ISP176x_HC_INTERRUPT);
        if (unlikely(!imask))
                goto leave;
-       reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */
+       isp1760_reg_write(priv->regs, ISP176x_HC_INTERRUPT, imask); /* Clear */
 
-       priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
-       priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
+       priv->int_done_map |= isp1760_reg_read(priv->regs,
+                                              ISP176x_HC_INT_PTD_DONEMAP);
+       priv->atl_done_map |= isp1760_reg_read(priv->regs,
+                                              ISP176x_HC_ATL_PTD_DONEMAP);
 
        handle_done_ptds(hcd);
 
                if (priv->atl_slots[slot].qh && time_after(jiffies,
                                        priv->atl_slots[slot].timestamp +
                                        msecs_to_jiffies(SLOT_TIMEOUT))) {
-                       ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+                       ptd_read(hcd, priv->base, ATL_PTD_OFFSET, slot, &ptd);
                        if (!FROM_DW0_VALID(ptd.dw0) &&
                                        !FROM_DW3_ACTIVE(ptd.dw3))
                                priv->atl_done_map |= 1 << slot;
 
 static int isp1760_run(struct usb_hcd *hcd)
 {
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
        int retval;
-       u32 temp;
-       u32 command;
        u32 chipid;
 
        hcd->uses_new_polling = 1;
        hcd->state = HC_STATE_RUNNING;
 
        /* Set PTD interrupt AND & OR maps */
-       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ATL_IRQ_MASK_AND, 0);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ATL_IRQ_MASK_OR, 0xffffffff);
+       isp1760_reg_write(priv->regs, ISP176x_HC_INT_IRQ_MASK_AND, 0);
+       isp1760_reg_write(priv->regs, ISP176x_HC_INT_IRQ_MASK_OR, 0xffffffff);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ISO_IRQ_MASK_AND, 0);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ISO_IRQ_MASK_OR, 0xffffffff);
        /* step 23 passed */
 
-       temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN);
+       isp1760_hcd_set(hcd, HW_GLOBAL_INTR_EN);
 
-       command = reg_read32(hcd->regs, HC_USBCMD);
-       command &= ~(CMD_LRESET|CMD_RESET);
-       command |= CMD_RUN;
-       reg_write32(hcd->regs, HC_USBCMD, command);
+       isp1760_hcd_clear(hcd, CMD_LRESET);
+       isp1760_hcd_clear(hcd, CMD_RESET);
 
-       retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000);
+       retval = isp1760_hcd_set_poll_timeout(hcd, CMD_RUN, 250 * 1000);
        if (retval)
                return retval;
 
         * the semaphore while doing so.
         */
        down_write(&ehci_cf_port_reset_rwsem);
-       reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF);
 
-       retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000);
+       retval = isp1760_hcd_set_poll_timeout(hcd, FLAG_CF, 250 * 1000);
        up_write(&ehci_cf_port_reset_rwsem);
        if (retval)
                return retval;
        errata2_timer.expires = jiffies + msecs_to_jiffies(SLOT_CHECK_PERIOD);
        add_timer(&errata2_timer);
 
-       chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+       chipid = isp1760_reg_read(priv->regs, ISP176x_HC_CHIP_ID);
        dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
                                        chipid & 0xffff, chipid >> 16);
 
        /* PTD Register Init Part 2, Step 28 */
 
        /* Setup registers controlling PTD checking */
-       reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000);
-       reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000);
-       reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001);
-       reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_BUFFER_STATUS_REG,
-                                               ATL_BUF_FILL | INT_BUF_FILL);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ATL_PTD_LASTPTD, 0x80000000);
+       isp1760_reg_write(priv->regs, ISP176x_HC_INT_PTD_LASTPTD, 0x80000000);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ISO_PTD_LASTPTD, 0x00000001);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ATL_PTD_SKIPMAP, 0xffffffff);
+       isp1760_reg_write(priv->regs, ISP176x_HC_INT_PTD_SKIPMAP, 0xffffffff);
+       isp1760_reg_write(priv->regs, ISP176x_HC_ISO_PTD_SKIPMAP, 0xffffffff);
+
+       isp1760_hcd_set(hcd, ATL_BUF_FILL);
+       isp1760_hcd_set(hcd, INT_BUF_FILL);
 
        /* GRR this is run-once init(), being done every time the HC starts.
         * So long as they're part of class devices, we can't do it init()
        /* We need to forcefully reclaim the slot since some transfers never
           return, e.g. interrupt transfers and NAKed bulk transfers. */
        if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe)) {
-               skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
+               skip_map = isp1760_reg_read(priv->regs,
+                                           ISP176x_HC_ATL_PTD_SKIPMAP);
                skip_map |= (1 << qh->slot);
-               reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
+               isp1760_reg_write(priv->regs, ISP176x_HC_ATL_PTD_SKIPMAP,
+                                 skip_map);
                priv->atl_slots[qh->slot].qh = NULL;
                priv->atl_slots[qh->slot].qtd = NULL;
        } else {
-               skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
+               skip_map = isp1760_reg_read(priv->regs,
+                                           ISP176x_HC_INT_PTD_SKIPMAP);
                skip_map |= (1 << qh->slot);
-               reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
+               isp1760_reg_write(priv->regs, ISP176x_HC_INT_PTD_SKIPMAP,
+                                 skip_map);
                priv->int_slots[qh->slot].qh = NULL;
                priv->int_slots[qh->slot].qtd = NULL;
        }
 static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
-       u32 temp, status = 0;
-       u32 mask;
+       u32 status = 0;
        int retval = 1;
        unsigned long flags;
 
 
        /* init status to no-changes */
        buf[0] = 0;
-       mask = PORT_CSC;
 
        spin_lock_irqsave(&priv->lock, flags);
-       temp = reg_read32(hcd->regs, HC_PORTSC1);
 
-       if (temp & PORT_OWNER) {
-               if (temp & PORT_CSC) {
-                       temp &= ~PORT_CSC;
-                       reg_write32(hcd->regs, HC_PORTSC1, temp);
-                       goto done;
-               }
+       if (isp1760_hcd_is_set(hcd, PORT_OWNER) &&
+           isp1760_hcd_is_set(hcd, PORT_CSC)) {
+               isp1760_hcd_clear(hcd, PORT_CSC);
+               goto done;
        }
 
        /*
         * high-speed device is switched over to the companion
         * controller by the user.
         */
-
-       if ((temp & mask) != 0
-                       || ((temp & PORT_RESUME) != 0
-                               && time_after_eq(jiffies,
-                                       priv->reset_done))) {
+       if (isp1760_hcd_is_set(hcd, PORT_CSC) ||
+           (isp1760_hcd_is_set(hcd, PORT_RESUME) &&
+            time_after_eq(jiffies, priv->reset_done))) {
                buf [0] |= 1 << (0 + 1);
                status = STS_PCD;
        }
 static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
                struct usb_hub_descriptor *desc)
 {
-       int ports = HCS_N_PORTS(priv->hcs_params);
+       int ports;
        u16 temp;
 
+       ports = isp1760_hcd_read(priv->hcd, HCS_N_PORTS);
+
        desc->bDescriptorType = USB_DT_HUB;
        /* priv 1.0, 2.3.9 says 20ms max */
        desc->bPwrOn2PwrGood = 10;
 
        /* per-port overcurrent reporting */
        temp = HUB_CHAR_INDV_PORT_OCPM;
-       if (HCS_PPC(priv->hcs_params))
+       if (isp1760_hcd_is_set(priv->hcd, HCS_PPC))
                /* per-port power control */
                temp |= HUB_CHAR_INDV_PORT_LPSM;
        else
 
 #define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
-static int check_reset_complete(struct usb_hcd *hcd, int index,
-               int port_status)
+static void check_reset_complete(struct usb_hcd *hcd, int index)
 {
-       if (!(port_status & PORT_CONNECT))
-               return port_status;
+       if (!(isp1760_hcd_is_set(hcd, PORT_CONNECT)))
+               return;
 
        /* if reset finished and it's still not enabled -- handoff */
-       if (!(port_status & PORT_PE)) {
-
+       if (!isp1760_hcd_is_set(hcd, PORT_PE)) {
                dev_info(hcd->self.controller,
-                                       "port %d full speed --> companion\n",
-                                       index + 1);
+                        "port %d full speed --> companion\n", index + 1);
 
-               port_status |= PORT_OWNER;
-               port_status &= ~PORT_RWC_BITS;
-               reg_write32(hcd->regs, HC_PORTSC1, port_status);
+               isp1760_hcd_set(hcd, PORT_OWNER);
 
-       } else
+               isp1760_hcd_clear(hcd, PORT_CSC);
+       } else {
                dev_info(hcd->self.controller, "port %d high speed\n",
-                                                               index + 1);
+                        index + 1);
+       }
 
-       return port_status;
+       return;
 }
 
 static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
                u16 wValue, u16 wIndex, char *buf, u16 wLength)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
-       int ports = HCS_N_PORTS(priv->hcs_params);
-       u32 temp, status;
+       u32 status;
        unsigned long flags;
        int retval = 0;
+       int ports;
+
+       ports = isp1760_hcd_read(hcd, HCS_N_PORTS);
 
        /*
         * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
                if (!wIndex || wIndex > ports)
                        goto error;
                wIndex--;
-               temp = reg_read32(hcd->regs, HC_PORTSC1);
 
                /*
                 * Even if OWNER is set, so the port is owned by the
 
                switch (wValue) {
                case USB_PORT_FEAT_ENABLE:
-                       reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_PE);
+                       isp1760_hcd_clear(hcd, PORT_PE);
                        break;
                case USB_PORT_FEAT_C_ENABLE:
                        /* XXX error? */
                        break;
                case USB_PORT_FEAT_SUSPEND:
-                       if (temp & PORT_RESET)
+                       if (isp1760_hcd_is_set(hcd, PORT_RESET))
                                goto error;
 
-                       if (temp & PORT_SUSPEND) {
-                               if ((temp & PORT_PE) == 0)
+                       if (isp1760_hcd_is_set(hcd, PORT_SUSPEND)) {
+                               if (!isp1760_hcd_is_set(hcd, PORT_PE))
                                        goto error;
                                /* resume signaling for 20 msec */
-                               temp &= ~(PORT_RWC_BITS);
-                               reg_write32(hcd->regs, HC_PORTSC1,
-                                                       temp | PORT_RESUME);
+                               isp1760_hcd_clear(hcd, PORT_CSC);
+                               isp1760_hcd_set(hcd, PORT_RESUME);
+
                                priv->reset_done = jiffies +
                                        msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        }
                        /* we auto-clear this feature */
                        break;
                case USB_PORT_FEAT_POWER:
-                       if (HCS_PPC(priv->hcs_params))
-                               reg_write32(hcd->regs, HC_PORTSC1,
-                                                       temp & ~PORT_POWER);
+                       if (isp1760_hcd_is_set(hcd, HCS_PPC))
+                               isp1760_hcd_clear(hcd, PORT_POWER);
                        break;
                case USB_PORT_FEAT_C_CONNECTION:
-                       reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_CSC);
+                       isp1760_hcd_set(hcd, PORT_CSC);
                        break;
                case USB_PORT_FEAT_C_OVER_CURRENT:
                        /* XXX error ?*/
                default:
                        goto error;
                }
-               reg_read32(hcd->regs, HC_USBCMD);
+               isp1760_reg_read(priv->regs, ISP176x_HC_USBCMD);
                break;
        case GetHubDescriptor:
                isp1760_hub_descriptor(priv, (struct usb_hub_descriptor *)
                        goto error;
                wIndex--;
                status = 0;
-               temp = reg_read32(hcd->regs, HC_PORTSC1);
 
                /* wPortChange bits */
-               if (temp & PORT_CSC)
+               if (isp1760_hcd_is_set(hcd, PORT_CSC))
                        status |= USB_PORT_STAT_C_CONNECTION << 16;
 
 
                /* whoever resumes must GetPortStatus to complete it!! */
-               if (temp & PORT_RESUME) {
+               if (isp1760_hcd_is_set(hcd, PORT_RESUME)) {
                        dev_err(hcd->self.controller, "Port resume should be skipped.\n");
 
                        /* Remote Wakeup received? */
                                priv->reset_done = 0;
 
                                /* stop resume signaling */
-                               temp = reg_read32(hcd->regs, HC_PORTSC1);
-                               reg_write32(hcd->regs, HC_PORTSC1,
-                                       temp & ~(PORT_RWC_BITS | PORT_RESUME));
-                               retval = handshake(hcd, HC_PORTSC1,
-                                          PORT_RESUME, 0, 2000 /* 2msec */);
+                               isp1760_hcd_clear(hcd, PORT_CSC);
+
+                               retval = isp1760_hcd_clear_poll_timeout(hcd,
+                                                         PORT_RESUME, 2000);
                                if (retval != 0) {
                                        dev_err(hcd->self.controller,
                                                "port %d resume error %d\n",
                                                wIndex + 1, retval);
                                        goto error;
                                }
-                               temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
                        }
                }
 
                /* whoever resets must GetPortStatus to complete it!! */
-               if ((temp & PORT_RESET)
-                               && time_after_eq(jiffies,
-                                       priv->reset_done)) {
+               if (isp1760_hcd_is_set(hcd, PORT_RESET) &&
+                   time_after_eq(jiffies, priv->reset_done)) {
                        status |= USB_PORT_STAT_C_RESET << 16;
                        priv->reset_done = 0;
 
                        /* force reset to complete */
-                       reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_RESET);
                        /* REVISIT:  some hardware needs 550+ usec to clear
                         * this bit; seems too long to spin routinely...
                         */
-                       retval = handshake(hcd, HC_PORTSC1,
-                                       PORT_RESET, 0, 750);
+                       retval = isp1760_hcd_clear_poll_timeout(hcd, PORT_RESET,
+                                                               750);
                        if (retval != 0) {
                                dev_err(hcd->self.controller, "port %d reset error %d\n",
                                                wIndex + 1, retval);
                        }
 
                        /* see what we found out */
-                       temp = check_reset_complete(hcd, wIndex,
-                                       reg_read32(hcd->regs, HC_PORTSC1));
+                       check_reset_complete(hcd, wIndex);
                }
                /*
                 * Even if OWNER is set, there's no harm letting hub_wq
                 * for PORT_POWER anyway).
                 */
 
-               if (temp & PORT_OWNER)
+               if (isp1760_hcd_is_set(hcd, PORT_OWNER))
                        dev_err(hcd->self.controller, "PORT_OWNER is set\n");
 
-               if (temp & PORT_CONNECT) {
+               if (isp1760_hcd_is_set(hcd, PORT_CONNECT)) {
                        status |= USB_PORT_STAT_CONNECTION;
                        /* status may be from integrated TT */
                        status |= USB_PORT_STAT_HIGH_SPEED;
                }
-               if (temp & PORT_PE)
+               if (isp1760_hcd_is_set(hcd, PORT_PE))
                        status |= USB_PORT_STAT_ENABLE;
-               if (temp & (PORT_SUSPEND|PORT_RESUME))
+               if (isp1760_hcd_is_set(hcd, PORT_SUSPEND) &&
+                   isp1760_hcd_is_set(hcd, PORT_RESUME))
                        status |= USB_PORT_STAT_SUSPEND;
-               if (temp & PORT_RESET)
+               if (isp1760_hcd_is_set(hcd, PORT_RESET))
                        status |= USB_PORT_STAT_RESET;
-               if (temp & PORT_POWER)
+               if (isp1760_hcd_is_set(hcd, PORT_POWER))
                        status |= USB_PORT_STAT_POWER;
 
                put_unaligned(cpu_to_le32(status), (__le32 *) buf);
                if (!wIndex || wIndex > ports)
                        goto error;
                wIndex--;
-               temp = reg_read32(hcd->regs, HC_PORTSC1);
-               if (temp & PORT_OWNER)
+               if (isp1760_hcd_is_set(hcd, PORT_OWNER))
                        break;
 
-/*             temp &= ~PORT_RWC_BITS; */
                switch (wValue) {
                case USB_PORT_FEAT_ENABLE:
-                       reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_PE);
+                       isp1760_hcd_set(hcd, PORT_PE);
                        break;
 
                case USB_PORT_FEAT_SUSPEND:
-                       if ((temp & PORT_PE) == 0
-                                       || (temp & PORT_RESET) != 0)
+                       if (!isp1760_hcd_is_set(hcd, PORT_PE) ||
+                           isp1760_hcd_is_set(hcd, PORT_RESET))
                                goto error;
 
-                       reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_SUSPEND);
+                       isp1760_hcd_set(hcd, PORT_SUSPEND);
                        break;
                case USB_PORT_FEAT_POWER:
-                       if (HCS_PPC(priv->hcs_params))
-                               reg_write32(hcd->regs, HC_PORTSC1,
-                                                       temp | PORT_POWER);
+                       if (isp1760_hcd_is_set(hcd, HCS_PPC))
+                               isp1760_hcd_set(hcd, PORT_POWER);
                        break;
                case USB_PORT_FEAT_RESET:
-                       if (temp & PORT_RESUME)
+                       if (isp1760_hcd_is_set(hcd, PORT_RESUME))
                                goto error;
                        /* line status bits may report this as low speed,
                         * which can be fine if this root hub has a
                         * transaction translator built in.
                         */
-                       if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
-                                       && PORT_USB11(temp)) {
-                               temp |= PORT_OWNER;
+                       if ((isp1760_hcd_is_set(hcd, PORT_CONNECT) &&
+                            !isp1760_hcd_is_set(hcd, PORT_PE)) &&
+                           (isp1760_hcd_read(hcd, PORT_LSTATUS) == 1)) {
+                               isp1760_hcd_set(hcd, PORT_OWNER);
                        } else {
-                               temp |= PORT_RESET;
-                               temp &= ~PORT_PE;
+                               isp1760_hcd_set(hcd, PORT_RESET);
+                               isp1760_hcd_clear(hcd, PORT_PE);
 
                                /*
                                 * caller must wait, then call GetPortStatus
                                priv->reset_done = jiffies +
                                        msecs_to_jiffies(50);
                        }
-                       reg_write32(hcd->regs, HC_PORTSC1, temp);
                        break;
                default:
                        goto error;
                }
-               reg_read32(hcd->regs, HC_USBCMD);
+               isp1760_reg_read(priv->regs, ISP176x_HC_USBCMD);
                break;
 
        default:
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
        u32 fr;
 
-       fr = reg_read32(hcd->regs, HC_FRINDEX);
+       fr = isp1760_hcd_read(hcd, HC_FRINDEX);
        return (fr >> 3) % priv->periodic_size;
 }
 
 static void isp1760_stop(struct usb_hcd *hcd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
-       u32 temp;
 
        del_timer(&errata2_timer);
 
        spin_lock_irq(&priv->lock);
        ehci_reset(hcd);
        /* Disable IRQ */
-       temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
+       isp1760_hcd_clear(hcd, HW_GLOBAL_INTR_EN);
        spin_unlock_irq(&priv->lock);
 
-       reg_write32(hcd->regs, HC_CONFIGFLAG, 0);
+       isp1760_hcd_clear(hcd, FLAG_CF);
 }
 
 static void isp1760_shutdown(struct usb_hcd *hcd)
 {
-       u32 command, temp;
-
        isp1760_stop(hcd);
-       temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
 
-       command = reg_read32(hcd->regs, HC_USBCMD);
-       command &= ~CMD_RUN;
-       reg_write32(hcd->regs, HC_USBCMD, command);
+       isp1760_hcd_clear(hcd, HW_GLOBAL_INTR_EN);
+
+       isp1760_hcd_clear(hcd, CMD_RUN);
 }
 
 static void isp1760_clear_tt_buffer_complete(struct usb_hcd *hcd,
        kmem_cache_destroy(urb_listitem_cachep);
 }
 
-int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs,
-                        struct resource *mem, int irq, unsigned long irqflags,
+int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem,
+                        int irq, unsigned long irqflags,
                         struct device *dev)
 {
        struct usb_hcd *hcd;
        init_memory(priv);
 
        hcd->irq = irq;
-       hcd->regs = regs;
        hcd->rsrc_start = mem->start;
        hcd->rsrc_len = resource_size(mem);
 
 
 #define _ISP1760_HCD_H_
 
 #include <linux/spinlock.h>
+#include <linux/regmap.h>
+
+#include "isp1760-regs.h"
 
 struct isp1760_qh;
 struct isp1760_qtd;
 };
 
 struct isp1760_hcd {
-#ifdef CONFIG_USB_ISP1760_HCD
        struct usb_hcd          *hcd;
 
-       u32 hcs_params;
+       void __iomem            *base;
+
+       struct regmap           *regs;
+       struct regmap_field     *fields[HC_FIELD_MAX];
+
        spinlock_t              lock;
        struct isp1760_slotinfo atl_slots[32];
        int                     atl_done_map;
        unsigned                i_thresh;
        unsigned long           reset_done;
        unsigned long           next_statechange;
-#endif
 };
 
 #ifdef CONFIG_USB_ISP1760_HCD
-int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs,
-                        struct resource *mem, int irq, unsigned long irqflags,
-                        struct device *dev);
+int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem,
+                        int irq, unsigned long irqflags, struct device *dev);
 void isp1760_hcd_unregister(struct isp1760_hcd *priv);
 
 int isp1760_init_kmem_once(void);
 void isp1760_deinit_kmem_cache(void);
 #else
 static inline int isp1760_hcd_register(struct isp1760_hcd *priv,
-                                      void __iomem *regs, struct resource *mem,
+                                      struct resource *mem,
                                       int irq, unsigned long irqflags,
                                       struct device *dev)
 {
 
                /*by default host is in 16bit mode, so
                 * io operations at this stage must be 16 bit
                 * */
-               writel(0xface, iobase + HC_SCRATCH_REG);
+               writel(0xface, iobase + ISP176x_HC_SCRATCH);
                udelay(100);
-               reg_data = readl(iobase + HC_SCRATCH_REG) & 0x0000ffff;
+               reg_data = readl(iobase + ISP176x_HC_SCRATCH) & 0x0000ffff;
                retry_count--;
        }
 
 
  *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  */
 
-#ifndef _ISP1760_REGS_H_
-#define _ISP1760_REGS_H_
+#ifndef _ISP176x_REGS_H_
+#define _ISP176x_REGS_H_
 
 /* -----------------------------------------------------------------------------
  * Host Controller
  */
 
 /* EHCI capability registers */
-#define HC_CAPLENGTH           0x000
-#define HC_LENGTH(p)           (((p) >> 00) & 0x00ff)  /* bits 7:0 */
-#define HC_VERSION(p)          (((p) >> 16) & 0xffff)  /* bits 31:16 */
-
-#define HC_HCSPARAMS           0x004
-#define HCS_INDICATOR(p)       ((p) & (1 << 16))       /* true: has port indicators */
-#define HCS_PPC(p)             ((p) & (1 << 4))        /* true: port power control */
-#define HCS_N_PORTS(p)         (((p) >> 0) & 0xf)      /* bits 3:0, ports on HC */
-
-#define HC_HCCPARAMS           0x008
-#define HCC_ISOC_CACHE(p)       ((p) & (1 << 7))       /* true: can cache isoc frame */
-#define HCC_ISOC_THRES(p)       (((p) >> 4) & 0x7)     /* bits 6:4, uframes cached */
+#define ISP176x_HC_CAPLENGTH           0x000
+#define ISP176x_HC_VERSION             0x002
+#define ISP176x_HC_HCSPARAMS           0x004
+#define ISP176x_HC_HCCPARAMS           0x008
 
 /* EHCI operational registers */
-#define HC_USBCMD              0x020
-#define CMD_LRESET             (1 << 7)                /* partial reset (no ports, etc) */
-#define CMD_RESET              (1 << 1)                /* reset HC not bus */
-#define CMD_RUN                        (1 << 0)                /* start/stop HC */
-
-#define HC_USBSTS              0x024
-#define STS_PCD                        (1 << 2)                /* port change detect */
-
-#define HC_FRINDEX             0x02c
-
-#define HC_CONFIGFLAG          0x060
-#define FLAG_CF                        (1 << 0)                /* true: we'll support "high speed" */
-
-#define HC_PORTSC1             0x064
-#define PORT_OWNER             (1 << 13)               /* true: companion hc owns this port */
-#define PORT_POWER             (1 << 12)               /* true: has power (see PPC) */
-#define PORT_USB11(x)          (((x) & (3 << 10)) == (1 << 10))        /* USB 1.1 device */
-#define PORT_RESET             (1 << 8)                /* reset port */
-#define PORT_SUSPEND           (1 << 7)                /* suspend port */
-#define PORT_RESUME            (1 << 6)                /* resume it */
-#define PORT_PE                        (1 << 2)                /* port enable */
-#define PORT_CSC               (1 << 1)                /* connect status change */
-#define PORT_CONNECT           (1 << 0)                /* device connected */
-#define PORT_RWC_BITS          (PORT_CSC)
-
-#define HC_ISO_PTD_DONEMAP_REG 0x130
-#define HC_ISO_PTD_SKIPMAP_REG 0x134
-#define HC_ISO_PTD_LASTPTD_REG 0x138
-#define HC_INT_PTD_DONEMAP_REG 0x140
-#define HC_INT_PTD_SKIPMAP_REG 0x144
-#define HC_INT_PTD_LASTPTD_REG 0x148
-#define HC_ATL_PTD_DONEMAP_REG 0x150
-#define HC_ATL_PTD_SKIPMAP_REG 0x154
-#define HC_ATL_PTD_LASTPTD_REG 0x158
+#define ISP176x_HC_USBCMD              0x020
+#define ISP176x_HC_USBSTS              0x024
+#define ISP176x_HC_FRINDEX             0x02c
+
+#define ISP176x_HC_CONFIGFLAG          0x060
+#define ISP176x_HC_PORTSC1             0x064
+
+#define ISP176x_HC_ISO_PTD_DONEMAP     0x130
+#define ISP176x_HC_ISO_PTD_SKIPMAP     0x134
+#define ISP176x_HC_ISO_PTD_LASTPTD     0x138
+#define ISP176x_HC_INT_PTD_DONEMAP     0x140
+#define ISP176x_HC_INT_PTD_SKIPMAP     0x144
+#define ISP176x_HC_INT_PTD_LASTPTD     0x148
+#define ISP176x_HC_ATL_PTD_DONEMAP     0x150
+#define ISP176x_HC_ATL_PTD_SKIPMAP     0x154
+#define ISP176x_HC_ATL_PTD_LASTPTD     0x158
 
 /* Configuration Register */
-#define HC_HW_MODE_CTRL                0x300
-#define ALL_ATX_RESET          (1 << 31)
-#define HW_ANA_DIGI_OC         (1 << 15)
-#define HW_DEV_DMA             (1 << 11)
-#define HW_COMN_IRQ            (1 << 10)
-#define HW_COMN_DMA            (1 << 9)
-#define HW_DATA_BUS_32BIT      (1 << 8)
-#define HW_DACK_POL_HIGH       (1 << 6)
-#define HW_DREQ_POL_HIGH       (1 << 5)
-#define HW_INTR_HIGH_ACT       (1 << 2)
-#define HW_INTR_EDGE_TRIG      (1 << 1)
-#define HW_GLOBAL_INTR_EN      (1 << 0)
-
-#define HC_CHIP_ID_REG         0x304
-#define HC_SCRATCH_REG         0x308
-
-#define HC_RESET_REG           0x30c
-#define SW_RESET_RESET_HC      (1 << 1)
-#define SW_RESET_RESET_ALL     (1 << 0)
-
-#define HC_BUFFER_STATUS_REG   0x334
-#define ISO_BUF_FILL           (1 << 2)
-#define INT_BUF_FILL           (1 << 1)
-#define ATL_BUF_FILL           (1 << 0)
-
-#define HC_MEMORY_REG          0x33c
-#define ISP_BANK(x)            ((x) << 16)
-
-#define HC_PORT1_CTRL          0x374
-#define PORT1_POWER            (3 << 3)
-#define PORT1_INIT1            (1 << 7)
-#define PORT1_INIT2            (1 << 23)
-#define HW_OTG_CTRL_SET                0x374
-#define HW_OTG_CTRL_CLR                0x376
-#define HW_OTG_DISABLE         (1 << 10)
-#define HW_OTG_SE0_EN          (1 << 9)
-#define HW_BDIS_ACON_EN                (1 << 8)
-#define HW_SW_SEL_HC_DC                (1 << 7)
-#define HW_VBUS_CHRG           (1 << 6)
-#define HW_VBUS_DISCHRG                (1 << 5)
-#define HW_VBUS_DRV            (1 << 4)
-#define HW_SEL_CP_EXT          (1 << 3)
-#define HW_DM_PULLDOWN         (1 << 2)
-#define HW_DP_PULLDOWN         (1 << 1)
-#define HW_DP_PULLUP           (1 << 0)
+#define ISP176x_HC_HW_MODE_CTRL                0x300
+#define ISP176x_HC_CHIP_ID             0x304
+#define ISP176x_HC_SCRATCH             0x308
+#define ISP176x_HC_RESET               0x30c
+#define ISP176x_HC_BUFFER_STATUS       0x334
+#define ISP176x_HC_MEMORY              0x33c
 
 /* Interrupt Register */
-#define HC_INTERRUPT_REG       0x310
-
-#define HC_INTERRUPT_ENABLE    0x314
-#define HC_ISO_INT             (1 << 9)
-#define HC_ATL_INT             (1 << 8)
-#define HC_INTL_INT            (1 << 7)
-#define HC_EOT_INT             (1 << 3)
-#define HC_SOT_INT             (1 << 1)
-#define INTERRUPT_ENABLE_MASK  (HC_INTL_INT | HC_ATL_INT)
-
-#define HC_ISO_IRQ_MASK_OR_REG 0x318
-#define HC_INT_IRQ_MASK_OR_REG 0x31c
-#define HC_ATL_IRQ_MASK_OR_REG 0x320
-#define HC_ISO_IRQ_MASK_AND_REG        0x324
-#define HC_INT_IRQ_MASK_AND_REG        0x328
-#define HC_ATL_IRQ_MASK_AND_REG        0x32c
+#define ISP176x_HC_INTERRUPT           0x310
+#define ISP176x_HC_INTERRUPT_ENABLE    0x314
+#define ISP176x_HC_ISO_IRQ_MASK_OR     0x318
+#define ISP176x_HC_INT_IRQ_MASK_OR     0x31c
+#define ISP176x_HC_ATL_IRQ_MASK_OR     0x320
+#define ISP176x_HC_ISO_IRQ_MASK_AND    0x324
+#define ISP176x_HC_INT_IRQ_MASK_AND    0x328
+#define ISP176x_HC_ATL_IRQ_MASK_AND    0x32c
+
+enum isp176x_host_controller_fields {
+       /* HC_HCSPARAMS */
+       HCS_PPC, HCS_N_PORTS,
+       /* HC_HCCPARAMS */
+       HCC_ISOC_CACHE, HCC_ISOC_THRES,
+       /* HC_USBCMD */
+       CMD_LRESET, CMD_RESET, CMD_RUN,
+       /* HC_USBSTS */
+       STS_PCD,
+       /* HC_FRINDEX */
+       HC_FRINDEX,
+       /* HC_CONFIGFLAG */
+       FLAG_CF,
+       /* HC_PORTSC1 */
+       PORT_OWNER, PORT_POWER, PORT_LSTATUS, PORT_RESET, PORT_SUSPEND,
+       PORT_RESUME, PORT_PE, PORT_CSC, PORT_CONNECT,
+       /* HC_HW_MODE_CTRL */
+       ALL_ATX_RESET, HW_ANA_DIGI_OC, HW_DEV_DMA, HW_COMN_IRQ, HW_COMN_DMA,
+       HW_DATA_BUS_WIDTH, HW_DACK_POL_HIGH, HW_DREQ_POL_HIGH, HW_INTR_HIGH_ACT,
+       HW_INTR_EDGE_TRIG, HW_GLOBAL_INTR_EN,
+       /* HC_RESET */
+       SW_RESET_RESET_HC, SW_RESET_RESET_ALL,
+       /* HC_BUFFER_STATUS */
+       INT_BUF_FILL, ATL_BUF_FILL,
+       /* HC_MEMORY */
+       MEM_BANK_SEL, MEM_START_ADDR,
+       /* HC_INTERRUPT_ENABLE */
+       HC_INT_ENABLE,
+       /* Last element */
+       HC_FIELD_MAX,
+};
 
 /* -----------------------------------------------------------------------------
  * Peripheral Controller
  */
 
-/* Initialization Registers */
-#define DC_ADDRESS                     0x0200
-#define DC_DEVEN                       (1 << 7)
-
-#define DC_MODE                                0x020c
-#define DC_DMACLKON                    (1 << 9)
-#define DC_VBUSSTAT                    (1 << 8)
-#define DC_CLKAON                      (1 << 7)
-#define DC_SNDRSU                      (1 << 6)
-#define DC_GOSUSP                      (1 << 5)
-#define DC_SFRESET                     (1 << 4)
-#define DC_GLINTENA                    (1 << 3)
-#define DC_WKUPCS                      (1 << 2)
-
-#define DC_INTCONF                     0x0210
-#define DC_CDBGMOD_ACK_NAK             (0 << 6)
-#define DC_CDBGMOD_ACK                 (1 << 6)
-#define DC_CDBGMOD_ACK_1NAK            (2 << 6)
-#define DC_DDBGMODIN_ACK_NAK           (0 << 4)
-#define DC_DDBGMODIN_ACK               (1 << 4)
-#define DC_DDBGMODIN_ACK_1NAK          (2 << 4)
-#define DC_DDBGMODOUT_ACK_NYET_NAK     (0 << 2)
-#define DC_DDBGMODOUT_ACK_NYET         (1 << 2)
-#define DC_DDBGMODOUT_ACK_NYET_1NAK    (2 << 2)
-#define DC_INTLVL                      (1 << 1)
-#define DC_INTPOL                      (1 << 0)
-
-#define DC_DEBUG                       0x0212
-#define DC_INTENABLE                   0x0214
 #define DC_IEPTX(n)                    (1 << (11 + 2 * (n)))
 #define DC_IEPRX(n)                    (1 << (10 + 2 * (n)))
 #define DC_IEPRXTX(n)                  (3 << (10 + 2 * (n)))
-#define DC_IEP0SETUP                   (1 << 8)
-#define DC_IEVBUS                      (1 << 7)
-#define DC_IEDMA                       (1 << 6)
-#define DC_IEHS_STA                    (1 << 5)
-#define DC_IERESM                      (1 << 4)
-#define DC_IESUSP                      (1 << 3)
-#define DC_IEPSOF                      (1 << 2)
-#define DC_IESOF                       (1 << 1)
-#define DC_IEBRST                      (1 << 0)
+
+#define ISP176x_DC_CDBGMOD_ACK         BIT(6)
+#define ISP176x_DC_DDBGMODIN_ACK       BIT(4)
+#define ISP176x_DC_DDBGMODOUT_ACK      BIT(2)
+
+#define ISP176x_DC_IEP0SETUP           BIT(8)
+#define ISP176x_DC_IEVBUS              BIT(7)
+#define ISP176x_DC_IEHS_STA            BIT(5)
+#define ISP176x_DC_IERESM              BIT(4)
+#define ISP176x_DC_IESUSP              BIT(3)
+#define ISP176x_DC_IEBRST              BIT(0)
+
+#define ISP176x_DC_ENDPTYP_ISOC                0x01
+#define ISP176x_DC_ENDPTYP_BULK                0x02
+#define ISP176x_DC_ENDPTYP_INTERRUPT   0x03
+
+/* Initialization Registers */
+#define ISP176x_DC_ADDRESS             0x0200
+#define ISP176x_DC_MODE                        0x020c
+#define ISP176x_DC_INTCONF             0x0210
+#define ISP176x_DC_DEBUG               0x0212
+#define ISP176x_DC_INTENABLE           0x0214
 
 /* Data Flow Registers */
-#define DC_EPINDEX                     0x022c
-#define DC_EP0SETUP                    (1 << 5)
-#define DC_ENDPIDX(n)                  ((n) << 1)
-#define DC_EPDIR                       (1 << 0)
-
-#define DC_CTRLFUNC                    0x0228
-#define DC_CLBUF                       (1 << 4)
-#define DC_VENDP                       (1 << 3)
-#define DC_DSEN                                (1 << 2)
-#define DC_STATUS                      (1 << 1)
-#define DC_STALL                       (1 << 0)
-
-#define DC_DATAPORT                    0x0220
-#define DC_BUFLEN                      0x021c
-#define DC_DATACOUNT_MASK              0xffff
-#define DC_BUFSTAT                     0x021e
-#define DC_EPMAXPKTSZ                  0x0204
-
-#define DC_EPTYPE                      0x0208
-#define DC_NOEMPKT                     (1 << 4)
-#define DC_EPENABLE                    (1 << 3)
-#define DC_DBLBUF                      (1 << 2)
-#define DC_ENDPTYP_ISOC                        (1 << 0)
-#define DC_ENDPTYP_BULK                        (2 << 0)
-#define DC_ENDPTYP_INTERRUPT           (3 << 0)
+#define ISP176x_DC_EPMAXPKTSZ          0x0204
+#define ISP176x_DC_EPTYPE              0x0208
+
+#define ISP176x_DC_BUFLEN              0x021c
+#define ISP176x_DC_BUFSTAT             0x021e
+#define ISP176x_DC_DATAPORT            0x0220
+
+#define ISP176x_DC_CTRLFUNC            0x0228
+#define ISP176x_DC_EPINDEX             0x022c
+
+#define ISP1761_DC_OTG_CTRL_SET                0x374
+#define ISP1761_DC_OTG_CTRL_CLEAR      0x376
 
 /* DMA Registers */
-#define DC_DMACMD                      0x0230
-#define DC_DMATXCOUNT                  0x0234
-#define DC_DMACONF                     0x0238
-#define DC_DMAHW                       0x023c
-#define DC_DMAINTREASON                        0x0250
-#define DC_DMAINTEN                    0x0254
-#define DC_DMAEP                       0x0258
-#define DC_DMABURSTCOUNT               0x0264
+#define ISP176x_DC_DMACMD              0x0230
+#define ISP176x_DC_DMATXCOUNT          0x0234
+#define ISP176x_DC_DMACONF             0x0238
+#define ISP176x_DC_DMAHW               0x023c
+#define ISP176x_DC_DMAINTREASON                0x0250
+#define ISP176x_DC_DMAINTEN            0x0254
+#define ISP176x_DC_DMAEP               0x0258
+#define ISP176x_DC_DMABURSTCOUNT       0x0264
 
 /* General Registers */
-#define DC_INTERRUPT                   0x0218
-#define DC_CHIPID                      0x0270
-#define DC_FRAMENUM                    0x0274
-#define DC_SCRATCH                     0x0278
-#define DC_UNLOCKDEV                   0x027c
-#define DC_INTPULSEWIDTH               0x0280
-#define DC_TESTMODE                    0x0284
+#define ISP176x_DC_INTERRUPT           0x0218
+#define ISP176x_DC_CHIPID              0x0270
+#define ISP176x_DC_FRAMENUM            0x0274
+#define ISP176x_DC_SCRATCH             0x0278
+#define ISP176x_DC_UNLOCKDEV           0x027c
+#define ISP176x_DC_INTPULSEWIDTH       0x0280
+#define ISP176x_DC_TESTMODE            0x0284
+
+enum isp176x_device_controller_fields {
+       /* DC_ADDRESS */
+       DC_DEVEN, DC_DEVADDR,
+       /* DC_MODE */
+       DC_VBUSSTAT, DC_SFRESET, DC_GLINTENA,
+       /* DC_INTCONF */
+       DC_CDBGMOD_ACK, DC_DDBGMODIN_ACK, DC_DDBGMODOUT_ACK, DC_INTPOL,
+       /* DC_INTENABLE */
+       DC_IEPRXTX_7, DC_IEPRXTX_6, DC_IEPRXTX_5, DC_IEPRXTX_4, DC_IEPRXTX_3,
+       DC_IEPRXTX_2, DC_IEPRXTX_1, DC_IEPRXTX_0,
+       DC_IEP0SETUP, DC_IEVBUS, DC_IEHS_STA, DC_IERESM, DC_IESUSP, DC_IEBRST,
+       /* DC_EPINDEX */
+       DC_EP0SETUP, DC_ENDPIDX, DC_EPDIR,
+       /* DC_CTRLFUNC */
+       DC_CLBUF, DC_VENDP, DC_DSEN, DC_STATUS, DC_STALL,
+       /* DC_BUFLEN */
+       DC_BUFLEN,
+       /* DC_EPMAXPKTSZ */
+       DC_FFOSZ,
+       /* DC_EPTYPE */
+       DC_EPENABLE, DC_ENDPTYP,
+       /* DC_FRAMENUM */
+       DC_FRAMENUM, DC_UFRAMENUM,
+       /* HW_OTG_CTRL_SET */
+       HW_OTG_DISABLE, HW_SW_SEL_HC_DC, HW_VBUS_DRV, HW_SEL_CP_EXT,
+       HW_DM_PULLDOWN, HW_DP_PULLDOWN, HW_DP_PULLUP,
+       /* HW_OTG_CTRL_CLR */
+       HW_OTG_DISABLE_CLEAR, HW_SW_SEL_HC_DC_CLEAR, HW_VBUS_DRV_CLEAR,
+       HW_SEL_CP_EXT_CLEAR, HW_DM_PULLDOWN_CLEAR, HW_DP_PULLDOWN_CLEAR,
+       HW_DP_PULLUP_CLEAR,
+       /* Last element */
+       DC_FIELD_MAX,
+};
 
 #endif
 
        return container_of(req, struct isp1760_request, req);
 }
 
-static inline u32 isp1760_udc_read(struct isp1760_udc *udc, u16 reg)
+static u32 isp1760_udc_read(struct isp1760_udc *udc, u16 field)
 {
-       return isp1760_read32(udc->regs, reg);
+       return isp1760_field_read(udc->fields, field);
 }
 
-static inline void isp1760_udc_write(struct isp1760_udc *udc, u16 reg, u32 val)
+static void isp1760_udc_write(struct isp1760_udc *udc, u16 field, u32 val)
 {
-       isp1760_write32(udc->regs, reg, val);
+       isp1760_field_write(udc->fields, field, val);
 }
 
+static u32 isp1760_udc_read_raw(struct isp1760_udc *udc, u16 reg)
+{
+       __le32 val;
+
+       regmap_raw_read(udc->regs, reg, &val, 4);
+
+       return le32_to_cpu(val);
+}
+
+static u16 isp1760_udc_read_raw16(struct isp1760_udc *udc, u16 reg)
+{
+       __le16 val;
+
+       regmap_raw_read(udc->regs, reg, &val, 2);
+
+       return le16_to_cpu(val);
+}
+
+static void isp1760_udc_write_raw(struct isp1760_udc *udc, u16 reg, u32 val)
+{
+       __le32 val_le = cpu_to_le32(val);
+
+       regmap_raw_write(udc->regs, reg, &val_le, 4);
+}
+
+static void isp1760_udc_write_raw16(struct isp1760_udc *udc, u16 reg, u16 val)
+{
+       __le16 val_le = cpu_to_le16(val);
+
+       regmap_raw_write(udc->regs, reg, &val_le, 2);
+}
+
+static void isp1760_udc_set(struct isp1760_udc *udc, u32 field)
+{
+       isp1760_udc_write(udc, field, 0xFFFFFFFF);
+}
+
+static void isp1760_udc_clear(struct isp1760_udc *udc, u32 field)
+{
+       isp1760_udc_write(udc, field, 0);
+}
+
+static bool isp1760_udc_is_set(struct isp1760_udc *udc, u32 field)
+{
+       return !!isp1760_udc_read(udc, field);
+}
 /* -----------------------------------------------------------------------------
  * Endpoint Management
  */
        return NULL;
 }
 
-static void __isp1760_udc_select_ep(struct isp1760_ep *ep, int dir)
+static void __isp1760_udc_select_ep(struct isp1760_udc *udc,
+                                   struct isp1760_ep *ep, int dir)
 {
-       isp1760_udc_write(ep->udc, DC_EPINDEX,
-                         DC_ENDPIDX(ep->addr & USB_ENDPOINT_NUMBER_MASK) |
-                         (dir == USB_DIR_IN ? DC_EPDIR : 0));
+       isp1760_udc_write(udc, DC_ENDPIDX, ep->addr & USB_ENDPOINT_NUMBER_MASK);
+
+       if (dir == USB_DIR_IN)
+               isp1760_udc_set(udc, DC_EPDIR);
+       else
+               isp1760_udc_clear(udc, DC_EPDIR);
 }
 
 /**
  *
  * Called with the UDC spinlock held.
  */
-static void isp1760_udc_select_ep(struct isp1760_ep *ep)
+static void isp1760_udc_select_ep(struct isp1760_udc *udc,
+                                 struct isp1760_ep *ep)
 {
-       __isp1760_udc_select_ep(ep, ep->addr & USB_ENDPOINT_DIR_MASK);
+       __isp1760_udc_select_ep(udc, ep, ep->addr & USB_ENDPOINT_DIR_MASK);
 }
 
 /* Called with the UDC spinlock held. */
         * the direction opposite to the data stage data packets, we thus need
         * to select the OUT/IN endpoint for IN/OUT transfers.
         */
-       isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) |
-                         (dir == USB_DIR_IN ? 0 : DC_EPDIR));
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_STATUS);
+       if (dir == USB_DIR_IN)
+               isp1760_udc_clear(udc, DC_EPDIR);
+       else
+               isp1760_udc_set(udc, DC_EPDIR);
+
+       isp1760_udc_write(udc, DC_ENDPIDX, 1);
+       isp1760_udc_set(udc, DC_STATUS);
 
        /*
         * The hardware will terminate the request automatically and go back to
        spin_lock_irqsave(&udc->lock, flags);
 
        /* Stall both the IN and OUT endpoints. */
-       __isp1760_udc_select_ep(ep, USB_DIR_OUT);
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL);
-       __isp1760_udc_select_ep(ep, USB_DIR_IN);
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL);
+       __isp1760_udc_select_ep(udc, ep, USB_DIR_OUT);
+       isp1760_udc_set(udc, DC_STALL);
+       __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
+       isp1760_udc_set(udc, DC_STALL);
 
        /* A protocol stall completes the control transaction. */
        udc->ep0_state = ISP1760_CTRL_SETUP;
        u32 *buf;
        int i;
 
-       isp1760_udc_select_ep(ep);
-       len = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK;
+       isp1760_udc_select_ep(udc, ep);
+       len = isp1760_udc_read(udc, DC_BUFLEN);
 
        dev_dbg(udc->isp->dev, "%s: received %u bytes (%u/%u done)\n",
                __func__, len, req->req.actual, req->req.length);
                 * datasheet doesn't clearly document how this should be
                 * handled.
                 */
-               isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
+               isp1760_udc_set(udc, DC_CLBUF);
                return false;
        }
 
         * the next packet might be removed from the FIFO.
         */
        for (i = len; i > 2; i -= 4, ++buf)
-               *buf = le32_to_cpu(isp1760_udc_read(udc, DC_DATAPORT));
+               *buf = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
        if (i > 0)
-               *(u16 *)buf = le16_to_cpu(readw(udc->regs + DC_DATAPORT));
+               *(u16 *)buf = isp1760_udc_read_raw16(udc, ISP176x_DC_DATAPORT);
 
        req->req.actual += len;
 
                __func__, req->packet_size, req->req.actual,
                req->req.length);
 
-       __isp1760_udc_select_ep(ep, USB_DIR_IN);
+       __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
 
        if (req->packet_size)
                isp1760_udc_write(udc, DC_BUFLEN, req->packet_size);
         * the FIFO for this kind of conditions, but doesn't seem to work.
         */
        for (i = req->packet_size; i > 2; i -= 4, ++buf)
-               isp1760_udc_write(udc, DC_DATAPORT, cpu_to_le32(*buf));
+               isp1760_udc_write_raw(udc, ISP176x_DC_DATAPORT, *buf);
        if (i > 0)
-               writew(cpu_to_le16(*(u16 *)buf), udc->regs + DC_DATAPORT);
+               isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, *(u16 *)buf);
 
        if (ep->addr == 0)
-               isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+               isp1760_udc_set(udc, DC_DSEN);
        if (!req->packet_size)
-               isp1760_udc_write(udc, DC_CTRLFUNC, DC_VENDP);
+               isp1760_udc_set(udc, DC_VENDP);
 }
 
 static void isp1760_ep_rx_ready(struct isp1760_ep *ep)
                return -EINVAL;
        }
 
-       isp1760_udc_select_ep(ep);
-       isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0);
+       isp1760_udc_select_ep(udc, ep);
+
+       if (halt)
+               isp1760_udc_set(udc, DC_STALL);
+       else
+               isp1760_udc_clear(udc, DC_STALL);
 
        if (ep->addr == 0) {
                /* When halting the control endpoint, stall both IN and OUT. */
-               __isp1760_udc_select_ep(ep, USB_DIR_IN);
-               isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0);
+               __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
+               if (halt)
+                       isp1760_udc_set(udc, DC_STALL);
+               else
+                       isp1760_udc_clear(udc, DC_STALL);
        } else if (!halt) {
                /* Reset the data PID by cycling the endpoint enable bit. */
-               u16 eptype = isp1760_udc_read(udc, DC_EPTYPE);
-
-               isp1760_udc_write(udc, DC_EPTYPE, eptype & ~DC_EPENABLE);
-               isp1760_udc_write(udc, DC_EPTYPE, eptype);
+               isp1760_udc_clear(udc, DC_EPENABLE);
+               isp1760_udc_set(udc, DC_EPENABLE);
 
                /*
                 * Disabling the endpoint emptied the transmit FIFO, fill it
                return -EINVAL;
        }
 
-       isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) | DC_EPDIR);
+       isp1760_udc_set(udc, DC_EPDIR);
+       isp1760_udc_write(udc, DC_ENDPIDX, 1);
+
        isp1760_udc_write(udc, DC_BUFLEN, 2);
 
-       writew(cpu_to_le16(status), udc->regs + DC_DATAPORT);
+       isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, status);
 
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+       isp1760_udc_set(udc, DC_DSEN);
 
        dev_dbg(udc->isp->dev, "%s: status 0x%04x\n", __func__, status);
 
        usb_gadget_set_state(&udc->gadget, addr ? USB_STATE_ADDRESS :
                             USB_STATE_DEFAULT);
 
-       isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN | addr);
+       isp1760_udc_write(udc, DC_DEVADDR, addr);
+       isp1760_udc_set(udc, DC_DEVEN);
 
        spin_lock(&udc->lock);
        isp1760_udc_ctrl_send_status(&udc->ep[0], USB_DIR_OUT);
 
        spin_lock(&udc->lock);
 
-       isp1760_udc_write(udc, DC_EPINDEX, DC_EP0SETUP);
+       isp1760_udc_set(udc, DC_EP0SETUP);
 
-       count = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK;
+       count = isp1760_udc_read(udc, DC_BUFLEN);
        if (count != sizeof(req)) {
                spin_unlock(&udc->lock);
 
                return;
        }
 
-       req.data[0] = isp1760_udc_read(udc, DC_DATAPORT);
-       req.data[1] = isp1760_udc_read(udc, DC_DATAPORT);
+       req.data[0] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
+       req.data[1] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
 
        if (udc->ep0_state != ISP1760_CTRL_SETUP) {
                spin_unlock(&udc->lock);
 
        switch (usb_endpoint_type(desc)) {
        case USB_ENDPOINT_XFER_ISOC:
-               type = DC_ENDPTYP_ISOC;
+               type = ISP176x_DC_ENDPTYP_ISOC;
                break;
        case USB_ENDPOINT_XFER_BULK:
-               type = DC_ENDPTYP_BULK;
+               type = ISP176x_DC_ENDPTYP_BULK;
                break;
        case USB_ENDPOINT_XFER_INT:
-               type = DC_ENDPTYP_INTERRUPT;
+               type = ISP176x_DC_ENDPTYP_INTERRUPT;
                break;
        case USB_ENDPOINT_XFER_CONTROL:
        default:
        uep->halted = false;
        uep->wedged = false;
 
-       isp1760_udc_select_ep(uep);
-       isp1760_udc_write(udc, DC_EPMAXPKTSZ, uep->maxpacket);
+       isp1760_udc_select_ep(udc, uep);
+
+       isp1760_udc_write(udc, DC_FFOSZ, uep->maxpacket);
        isp1760_udc_write(udc, DC_BUFLEN, uep->maxpacket);
-       isp1760_udc_write(udc, DC_EPTYPE, DC_EPENABLE | type);
+
+       isp1760_udc_write(udc, DC_ENDPTYP, type);
+       isp1760_udc_set(udc, DC_EPENABLE);
 
        spin_unlock_irqrestore(&udc->lock, flags);
 
        uep->desc = NULL;
        uep->maxpacket = 0;
 
-       isp1760_udc_select_ep(uep);
-       isp1760_udc_write(udc, DC_EPTYPE, 0);
+       isp1760_udc_select_ep(udc, uep);
+       isp1760_udc_clear(udc, DC_EPENABLE);
+       isp1760_udc_clear(udc, DC_ENDPTYP);
 
        /* TODO Synchronize with the IRQ handler */
 
 
                case ISP1760_CTRL_DATA_OUT:
                        list_add_tail(&req->queue, &uep->queue);
-                       __isp1760_udc_select_ep(uep, USB_DIR_OUT);
-                       isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+                       __isp1760_udc_select_ep(udc, uep, USB_DIR_OUT);
+                       isp1760_udc_set(udc, DC_DSEN);
                        break;
 
                case ISP1760_CTRL_STATUS:
 
        spin_lock_irqsave(&udc->lock, flags);
 
-       isp1760_udc_select_ep(uep);
+       isp1760_udc_select_ep(udc, uep);
 
        /*
         * Set the CLBUF bit twice to flush both buffers in case double
         * buffering is enabled.
         */
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
-       isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
+       isp1760_udc_set(udc, DC_CLBUF);
+       isp1760_udc_set(udc, DC_CLBUF);
 
        spin_unlock_irqrestore(&udc->lock, flags);
 }
         * ACK tokens only (and NYET for the out pipe). The default
         * configuration also generates an interrupt on the first NACK token.
         */
-       isp1760_udc_write(udc, DC_INTCONF, DC_CDBGMOD_ACK | DC_DDBGMODIN_ACK |
-                         DC_DDBGMODOUT_ACK_NYET);
-
-       isp1760_udc_write(udc, DC_INTENABLE, DC_IEPRXTX(7) | DC_IEPRXTX(6) |
-                         DC_IEPRXTX(5) | DC_IEPRXTX(4) | DC_IEPRXTX(3) |
-                         DC_IEPRXTX(2) | DC_IEPRXTX(1) | DC_IEPRXTX(0) |
-                         DC_IEP0SETUP | DC_IEVBUS | DC_IERESM | DC_IESUSP |
-                         DC_IEHS_STA | DC_IEBRST);
+       isp1760_reg_write(udc->regs, ISP176x_DC_INTCONF,
+                         ISP176x_DC_CDBGMOD_ACK | ISP176x_DC_DDBGMODIN_ACK |
+                         ISP176x_DC_DDBGMODOUT_ACK);
+
+       isp1760_reg_write(udc->regs, ISP176x_DC_INTENABLE, DC_IEPRXTX(7) |
+                         DC_IEPRXTX(6) | DC_IEPRXTX(5) | DC_IEPRXTX(4) |
+                         DC_IEPRXTX(3) | DC_IEPRXTX(2) | DC_IEPRXTX(1) |
+                         DC_IEPRXTX(0) | ISP176x_DC_IEP0SETUP |
+                         ISP176x_DC_IEVBUS | ISP176x_DC_IERESM |
+                         ISP176x_DC_IESUSP | ISP176x_DC_IEHS_STA |
+                         ISP176x_DC_IEBRST);
 
        if (udc->connected)
                isp1760_set_pullup(udc->isp, true);
 
-       isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN);
+       isp1760_udc_set(udc, DC_DEVEN);
 }
 
 static void isp1760_udc_reset(struct isp1760_udc *udc)
 {
        struct isp1760_udc *udc = gadget_to_udc(gadget);
 
-       return isp1760_udc_read(udc, DC_FRAMENUM) & ((1 << 11) - 1);
+       return isp1760_udc_read(udc, DC_FRAMENUM);
 }
 
 static int isp1760_udc_wakeup(struct usb_gadget *gadget)
        usb_gadget_set_state(&udc->gadget, USB_STATE_ATTACHED);
 
        /* DMA isn't supported yet, don't enable the DMA clock. */
-       isp1760_udc_write(udc, DC_MODE, DC_GLINTENA);
+       isp1760_udc_set(udc, DC_GLINTENA);
 
        isp1760_udc_init_hw(udc);
 
 
        del_timer_sync(&udc->vbus_timer);
 
-       isp1760_udc_write(udc, DC_MODE, 0);
+       isp1760_reg_write(udc->regs, ISP176x_DC_MODE, 0);
 
        spin_lock_irqsave(&udc->lock, flags);
        udc->driver = NULL;
        unsigned int i;
        u32 status;
 
-       status = isp1760_udc_read(udc, DC_INTERRUPT)
-              & isp1760_udc_read(udc, DC_INTENABLE);
-       isp1760_udc_write(udc, DC_INTERRUPT, status);
+       status = isp1760_reg_read(udc->regs, ISP176x_DC_INTERRUPT)
+              & isp1760_reg_read(udc->regs, ISP176x_DC_INTENABLE);
+       isp1760_reg_write(udc->regs, ISP176x_DC_INTERRUPT, status);
 
        if (status & DC_IEVBUS) {
                dev_dbg(udc->isp->dev, "%s(VBUS)\n", __func__);
                dev_dbg(udc->isp->dev, "%s(SUSP)\n", __func__);
 
                spin_lock(&udc->lock);
-               if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT))
+               if (!isp1760_udc_is_set(udc, DC_VBUSSTAT))
                        isp1760_udc_disconnect(udc);
                else
                        isp1760_udc_suspend(udc);
 
        spin_lock_irqsave(&udc->lock, flags);
 
-       if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT))
+       if (!(isp1760_udc_is_set(udc, DC_VBUSSTAT)))
                isp1760_udc_disconnect(udc);
        else if (udc->gadget.state >= USB_STATE_POWERED)
                mod_timer(&udc->vbus_timer,
         * register, and reading the scratch register value back. The chip ID
         * and scratch register contents must match the expected values.
         */
-       isp1760_udc_write(udc, DC_SCRATCH, 0xbabe);
-       chipid = isp1760_udc_read(udc, DC_CHIPID);
-       scratch = isp1760_udc_read(udc, DC_SCRATCH);
+       isp1760_reg_write(udc->regs, ISP176x_DC_SCRATCH, 0xbabe);
+       chipid = isp1760_reg_read(udc->regs, ISP176x_DC_CHIPID);
+       scratch = isp1760_reg_read(udc->regs, ISP176x_DC_SCRATCH);
 
        if (scratch != 0xbabe) {
                dev_err(udc->isp->dev,
        }
 
        /* Reset the device controller. */
-       isp1760_udc_write(udc, DC_MODE, DC_SFRESET);
+       isp1760_udc_set(udc, DC_SFRESET);
        usleep_range(10000, 11000);
-       isp1760_udc_write(udc, DC_MODE, 0);
+       isp1760_reg_write(udc->regs, ISP176x_DC_MODE, 0);
        usleep_range(10000, 11000);
 
        return 0;
 
        udc->irq = -1;
        udc->isp = isp;
-       udc->regs = isp->regs;
 
        spin_lock_init(&udc->lock);
        timer_setup(&udc->vbus_timer, isp1760_udc_vbus_poll, 0);
 
 #include <linux/timer.h>
 #include <linux/usb/gadget.h>
 
+#include "isp1760-regs.h"
+
 struct isp1760_device;
 struct isp1760_udc;
 
  * struct isp1760_udc - UDC state information
  * irq: IRQ number
  * irqname: IRQ name (as passed to request_irq)
- * regs: Base address of the UDC registers
+ * regs: regmap for UDC registers
  * driver: Gadget driver
  * gadget: Gadget device
  * lock: Protects driver, vbus_timer, ep, ep0_*, DC_EPINDEX register
  * connected: Tracks gadget driver bus connection state
  */
 struct isp1760_udc {
-#ifdef CONFIG_USB_ISP1761_UDC
        struct isp1760_device *isp;
 
        int irq;
        char *irqname;
-       void __iomem *regs;
+
+       struct regmap *regs;
+       struct regmap_field *fields[DC_FIELD_MAX];
 
        struct usb_gadget_driver *driver;
        struct usb_gadget gadget;
        bool connected;
 
        unsigned int devstatus;
-#endif
 };
 
 #ifdef CONFIG_USB_ISP1761_UDC