* version 2 as published by the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
 #include "isp1760-core.h"
 #include "isp1760-hcd.h"
+#include "isp1760-regs.h"
+
+static void isp1760_init_core(struct isp1760_device *isp)
+{
+       u32 hwmode;
+
+       /* Low-level chip reset */
+       if (isp->rst_gpio) {
+               gpiod_set_value_cansleep(isp->rst_gpio, 1);
+               mdelay(50);
+               gpiod_set_value_cansleep(isp->rst_gpio, 0);
+       }
+
+       /*
+        * Reset the host controller, including the CPU interface
+        * configuration.
+        */
+       isp1760_write32(isp->regs, HC_RESET_REG, 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;
+       if (isp->devflags & ISP1760_FLAG_ANALOG_OC)
+               hwmode |= HW_ANA_DIGI_OC;
+       if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH)
+               hwmode |= HW_DACK_POL_HIGH;
+       if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
+               hwmode |= HW_DREQ_POL_HIGH;
+       if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH)
+               hwmode |= HW_INTR_HIGH_ACT;
+       if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
+               hwmode |= HW_INTR_EDGE_TRIG;
+
+       /*
+        * 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);
+
+       dev_info(isp->dev, "bus width: %u, oc: %s\n",
+                isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
+                isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital");
+}
 
 int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
                     struct device *dev, unsigned int devflags)
        if (!isp)
                return -ENOMEM;
 
+       isp->dev = dev;
+       isp->devflags = devflags;
+
+       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);
 
+       isp1760_init_core(isp);
+
        ret = isp1760_hcd_register(&isp->hcd, isp->regs, mem, irq,
-                                  irqflags | IRQF_SHARED, dev, devflags);
+                                  irqflags | IRQF_SHARED, dev);
        if (ret < 0)
                return ret;
 
 
 
 #include "isp1760-hcd.h"
 
+struct device;
+struct gpio_desc;
+
+/*
+ * Device flags that can vary from board to board.  All of these
+ * indicate the most "atypical" case, so that a devflags of 0 is
+ * a sane default configuration.
+ */
+#define ISP1760_FLAG_BUS_WIDTH_16      0x00000002 /* 16-bit data bus width */
+#define ISP1760_FLAG_OTG_EN            0x00000004 /* Port 1 supports OTG */
+#define ISP1760_FLAG_ANALOG_OC         0x00000008 /* Analog overcurrent */
+#define ISP1760_FLAG_DACK_POL_HIGH     0x00000010 /* DACK active high */
+#define ISP1760_FLAG_DREQ_POL_HIGH     0x00000020 /* DREQ active high */
+#define ISP1760_FLAG_ISP1761           0x00000040 /* Chip is ISP1761 */
+#define ISP1760_FLAG_INTR_POL_HIGH     0x00000080 /* Interrupt polarity active high */
+#define ISP1760_FLAG_INTR_EDGE_TRIG    0x00000100 /* Interrupt edge triggered */
+
 struct isp1760_device {
+       struct device *dev;
+
        void __iomem *regs;
+       unsigned int devflags;
+       struct gpio_desc *rst_gpio;
 
        struct isp1760_hcd hcd;
 };
                     struct device *dev, unsigned int devflags);
 void isp1760_unregister(struct device *dev);
 
+static inline u32 isp1760_read32(void __iomem *base, u32 reg)
+{
+       return readl(base + reg);
+}
+
+static inline void isp1760_write32(void __iomem *base, u32 reg, u32 val)
+{
+       writel(val, base + reg);
+}
+
 #endif
 
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
 
+#include "isp1760-core.h"
 #include "isp1760-hcd.h"
 #include "isp1760-regs.h"
 
  */
 static u32 reg_read32(void __iomem *base, u32 reg)
 {
-       return readl(base + reg);
+       return isp1760_read32(base, reg);
 }
 
 static void reg_write32(void __iomem *base, u32 reg, u32 val)
 {
-       writel(val, base + reg);
+       isp1760_write32(base, reg, val);
 }
 
 /*
        int result;
        u32 scratch, hwmode;
 
-       /* low-level chip reset */
-       if (priv->rst_gpio) {
-               gpiod_set_value_cansleep(priv->rst_gpio, 1);
-               mdelay(50);
-               gpiod_set_value_cansleep(priv->rst_gpio, 0);
-       }
-
-       /* Setup HW Mode Control: This assumes a level active-low interrupt */
-       hwmode = HW_DATA_BUS_32BIT;
-
-       if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16)
-               hwmode &= ~HW_DATA_BUS_32BIT;
-       if (priv->devflags & ISP1760_FLAG_ANALOG_OC)
-               hwmode |= HW_ANA_DIGI_OC;
-       if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH)
-               hwmode |= HW_DACK_POL_HIGH;
-       if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
-               hwmode |= HW_DREQ_POL_HIGH;
-       if (priv->devflags & ISP1760_FLAG_INTR_POL_HIGH)
-               hwmode |= HW_INTR_HIGH_ACT;
-       if (priv->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
-               hwmode |= HW_INTR_EDGE_TRIG;
-
-       /*
-        * 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.
-        */
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
-
        reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe);
        /* Change bus pattern */
        scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG);
                return -ENODEV;
        }
 
-       /* pre reset */
+       /*
+        * The RESET_HC bit in the SW_RESET register is supposed to reset the
+        * host controller without touching the CPU interface registers, but at
+        * least on the ISP1761 it seems to behave as the RESET_ALL bit and
+        * reset the whole device. We thus can't use it here, so let's reset
+        * 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);
 
-       /* reset */
-       reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_ALL);
-       mdelay(100);
-
-       reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_HC);
-       mdelay(100);
-
        result = ehci_reset(hcd);
        if (result)
                return result;
 
        /* Step 11 passed */
 
-       dev_info(hcd->self.controller, "bus width: %d, oc: %s\n",
-                          (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
-                          16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
-                          "analog" : "digital");
-
        /* 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);
        mdelay(10);
        reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
 
 int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs,
                         struct resource *mem, int irq, unsigned long irqflags,
-                        struct device *dev, unsigned int devflags)
+                        struct device *dev)
 {
        struct usb_hcd *hcd;
        int ret;
        *(struct isp1760_hcd **)hcd->hcd_priv = priv;
 
        priv->hcd = hcd;
-       priv->devflags = devflags;
-
-       priv->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH);
-       if (IS_ERR(priv->rst_gpio)) {
-               ret = PTR_ERR(priv->rst_gpio);
-               goto error;
-       }
 
        init_memory(priv);
 
 
 
 #include <linux/spinlock.h>
 
-struct gpio_desc;
 struct isp1760_qh;
 struct isp1760_qtd;
 struct resource;
 #define MAX_PAYLOAD_SIZE BLOCK_3_SIZE
 #define PAYLOAD_AREA_SIZE 0xf000
 
-/*
- * Device flags that can vary from board to board.  All of these
- * indicate the most "atypical" case, so that a devflags of 0 is
- * a sane default configuration.
- */
-#define ISP1760_FLAG_BUS_WIDTH_16      0x00000002 /* 16-bit data bus width */
-#define ISP1760_FLAG_OTG_EN            0x00000004 /* Port 1 supports OTG */
-#define ISP1760_FLAG_ANALOG_OC         0x00000008 /* Analog overcurrent */
-#define ISP1760_FLAG_DACK_POL_HIGH     0x00000010 /* DACK active high */
-#define ISP1760_FLAG_DREQ_POL_HIGH     0x00000020 /* DREQ active high */
-#define ISP1760_FLAG_ISP1761           0x00000040 /* Chip is ISP1761 */
-#define ISP1760_FLAG_INTR_POL_HIGH     0x00000080 /* Interrupt polarity active high */
-#define ISP1760_FLAG_INTR_EDGE_TRIG    0x00000100 /* Interrupt edge triggered */
-
 struct isp1760_slotinfo {
        struct isp1760_qh *qh;
        struct isp1760_qtd *qtd;
        unsigned                i_thresh;
        unsigned long           reset_done;
        unsigned long           next_statechange;
-       unsigned int            devflags;
-
-       struct gpio_desc        *rst_gpio;
 };
 
 int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs,
                         struct resource *mem, int irq, unsigned long irqflags,
-                        struct device *dev, unsigned int devflags);
+                        struct device *dev);
 void isp1760_hcd_unregister(struct isp1760_hcd *priv);
 
 int isp1760_init_kmem_once(void);