unsigned                i_thresh;
        unsigned long           reset_done;
        unsigned long           next_statechange;
+       unsigned int            devflags;
 };
 
 static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
        int result;
-       u32 scratch;
+       u32 scratch, hwmode;
+
+       /* 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;
+
+       /*
+        * 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_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
 
        isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+       /* Change bus pattern */
+       scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
        scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
        if (scratch != 0xdeadbabe) {
                printk(KERN_ERR "ISP1760: Scratch test failed.\n");
 
        /* Step 11 passed */
 
-       isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
-       isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+       isp1760_info(priv, "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 */
-       scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-       isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
        mdelay(10);
-       isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
 
-       isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL);
-       mdelay(10);
+       isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
+       isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+
+       /*
+        * PORT 1 Control register of the ISP1760 is the OTG control
+        * register on ISP1761.
+        */
+       if (!(priv->devflags & ISP1760_FLAG_ISP1761) &&
+           !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) {
+               isp1760_writel(PORT1_POWER | PORT1_INIT2,
+                              hcd->regs + HC_PORT1_CTRL);
+               mdelay(10);
+       }
 
        priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
 
        hcd->state = HC_STATE_RUNNING;
        isp1760_enable_interrupts(hcd);
        temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-       temp |= FINAL_HW_CONFIG;
-       isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
 
        command = isp1760_readl(hcd->regs + HC_USBCMD);
        command &= ~(CMD_LRESET|CMD_RESET);
 static void isp1760_stop(struct usb_hcd *hcd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       u32 temp;
 
        isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
                        NULL, 0);
        spin_lock_irq(&priv->lock);
        ehci_reset(priv);
        /* Disable IRQ */
-       isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+       temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
        spin_unlock_irq(&priv->lock);
 
        isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
 
 static void isp1760_shutdown(struct usb_hcd *hcd)
 {
-       u32 command;
+       u32 command, temp;
 
        isp1760_stop(hcd);
-       isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+       temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+       isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
 
        command = isp1760_readl(hcd->regs + HC_USBCMD);
        command &= ~CMD_RUN;
 }
 
 struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-               u64 irqflags, struct device *dev, const char *busname)
+               u64 irqflags, struct device *dev, const char *busname,
+               unsigned int devflags)
 {
        struct usb_hcd *hcd;
        struct isp1760_hcd *priv;
                return ERR_PTR(-ENOMEM);
 
        priv = hcd_to_priv(hcd);
+       priv->devflags = devflags;
        init_memory(priv);
        hcd->regs = ioremap(res_start, res_len);
        if (!hcd->regs) {
 
 
 /* exports for if */
 struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-               u64 irqflags, struct device *dev, const char *busname);
+               u64 irqflags, struct device *dev, const char *busname,
+               unsigned int devflags);
 int init_kmem_once(void);
 void deinit_kmem_cache(void);
 
 /* Configuration Register */
 #define HC_HW_MODE_CTRL                0x300
 #define ALL_ATX_RESET          (1 << 31)
+#define HW_ANA_DIGI_OC         (1 << 15)
 #define HW_DATA_BUS_32BIT      (1 << 8)
 #define HW_DACK_POL_HIGH       (1 << 6)
 #define HW_DREQ_POL_HIGH       (1 << 5)
 #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
 
 /* Interrupt Register */
 #define HC_INTERRUPT_REG       0x310
 
 #define HC_INTERRUPT_ENABLE    0x314
 #define INTERRUPT_ENABLE_MASK  (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
-#define FINAL_HW_CONFIG        (HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT)
 
 #define HC_ISO_INT             (1 << 9)
 #define HC_ATL_INT             (1 << 8)
 #define isp1760_err(priv, fmt, args...) \
        dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
 
+/*
+ * 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_PORT1_DIS         0x00000001 /* Port 1 disabled */
+#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 */
+
 /* chip memory management */
 struct memory_chunk {
        unsigned int start;
 
        int virq;
        u64 res_len;
        int ret;
+       const unsigned int *prop;
+       unsigned int devflags = 0;
 
        ret = of_address_to_resource(dp, 0, &memory);
        if (ret)
        virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
                        oirq.size);
 
+       if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
+               devflags |= ISP1760_FLAG_ISP1761;
+
+       if (of_get_property(dp, "port1-disable", NULL) != NULL)
+               devflags |= ISP1760_FLAG_PORT1_DIS;
+
+       /* Some systems wire up only 16 of the 32 data lines */
+       prop = of_get_property(dp, "bus-width", NULL);
+       if (prop && *prop == 16)
+               devflags |= ISP1760_FLAG_BUS_WIDTH_16;
+
+       if (of_get_property(dp, "port1-otg", NULL) != NULL)
+               devflags |= ISP1760_FLAG_OTG_EN;
+
+       if (of_get_property(dp, "analog-oc", NULL) != NULL)
+               devflags |= ISP1760_FLAG_ANALOG_OC;
+
+       if (of_get_property(dp, "dack-polarity", NULL) != NULL)
+               devflags |= ISP1760_FLAG_DACK_POL_HIGH;
+
+       if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
+               devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
+
        hcd = isp1760_register(memory.start, res_len, virq,
-               IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev));
+               IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+               devflags);
        if (IS_ERR(hcd)) {
                ret = PTR_ERR(hcd);
                goto release_reg;
        {
                .compatible = "nxp,usb-isp1760",
        },
+       {
+               .compatible = "nxp,usb-isp1761",
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, of_isp1760_match);
        int length;
        int status = 1;
        struct usb_hcd *hcd;
+       unsigned int devflags = 0;
 
        if (usb_disabled())
                return -ENODEV;
 
        dev->dev.dma_mask = NULL;
        hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
-               IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev));
+               IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+               devflags);
        pci_set_drvdata(dev, hcd);
        if (!hcd)
                return 0;