usb: isp1760: Initialize the bus interface in core code

Although the corresponding register is part of the HCD register space,
processor bus initialization is not specific to the HCD. To prepare for
device controller support, move bus interface initialization to core
code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c
index 35278a8..e840a1d 100644
--- a/drivers/usb/host/isp1760-core.c
+++ b/drivers/usb/host/isp1760-core.c
@@ -13,7 +13,8 @@
  * 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>
@@ -22,6 +23,54 @@
 
 #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)
@@ -39,12 +88,21 @@
 	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;