summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp1760-core.c
diff options
context:
space:
mode:
authorLaurent Pinchart2015-01-20 23:55:59 +0100
committerFelipe Balbi2015-01-27 16:39:26 +0100
commit5171446a3aec607c4f94a32758f51a68bc627fe3 (patch)
treeef715105026ba279886ab33ef1a089a4606b11dc /drivers/usb/host/isp1760-core.c
parentusb: isp1760: Set IRQF_SHARED flag in core code (diff)
downloadkernel-qcow2-linux-5171446a3aec607c4f94a32758f51a68bc627fe3.tar.gz
kernel-qcow2-linux-5171446a3aec607c4f94a32758f51a68bc627fe3.tar.xz
kernel-qcow2-linux-5171446a3aec607c4f94a32758f51a68bc627fe3.zip
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>
Diffstat (limited to 'drivers/usb/host/isp1760-core.c')
-rw-r--r--drivers/usb/host/isp1760-core.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c
index 35278a8356b3..e840a1d3676b 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 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
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;