[PATCH 15/17] usb: isp1760: Initialize the bus interface in core code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxx>
---
 drivers/usb/host/isp1760-core.c | 62 ++++++++++++++++++++++++++++++++++++--
 drivers/usb/host/isp1760-core.h | 30 ++++++++++++++++++
 drivers/usb/host/isp1760-hcd.c  | 67 ++++++++---------------------------------
 drivers/usb/host/isp1760-hcd.h  | 20 +-----------
 4 files changed, 104 insertions(+), 75 deletions(-)

diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c
index 718fd6c..cde66d3 100644
--- a/drivers/usb/host/isp1760-core.c
+++ b/drivers/usb/host/isp1760-core.c
@@ -13,6 +13,7 @@
  * version 2 as published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -22,6 +23,59 @@
 
 #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 (gpio_is_valid(isp->rst_gpio)) {
+		unsigned int rst_lvl;
+
+		rst_lvl = (isp->devflags &
+			   ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0;
+
+		gpio_set_value(isp->rst_gpio, rst_lvl);
+		mdelay(50);
+		gpio_set_value(isp->rst_gpio, !rst_lvl);
+	}
+
+	/*
+	 * 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,
 		     int rst_gpio, struct device *dev, unsigned int devflags)
@@ -39,6 +93,9 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
 	if (!isp)
 		return -ENOMEM;
 
+	isp->dev = dev;
+	isp->devflags = devflags;
+
 	if (gpio_is_valid(rst_gpio)) {
 		ret = gpio_request(rst_gpio, dev_name(dev));
 		if (!ret) {
@@ -62,9 +119,10 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
 		goto error;
 	}
 
-	isp->hcd.rst_gpio = rst_gpio;
+	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)
 		goto error;
 
diff --git a/drivers/usb/host/isp1760-core.h b/drivers/usb/host/isp1760-core.h
index 8bd997c..862dff4 100644
--- a/drivers/usb/host/isp1760-core.h
+++ b/drivers/usb/host/isp1760-core.h
@@ -20,11 +20,31 @@
 
 #include "isp1760-hcd.h"
 
+struct device;
+
+/*
+ * 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 */
+#define ISP1760_FLAG_RESET_ACTIVE_HIGH	0x80000000 /* RESET GPIO active high */
+
 struct isp1760_device {
+	struct device *dev;
+
 	resource_size_t mem_start;
 	resource_size_t mem_size;
 
 	void __iomem *regs;
+	unsigned int devflags;
 	int rst_gpio;
 
 	struct isp1760_hcd hcd;
@@ -34,4 +54,14 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
 		     int rst_gpio, 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
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index f903ad9..596a1a9 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -24,8 +24,8 @@
 #include <linux/timer.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
-#include <linux/gpio.h>
 
+#include "isp1760-core.h"
 #include "isp1760-hcd.h"
 #include "isp1760-regs.h"
 
@@ -160,12 +160,12 @@ struct urb_listitem {
  */
 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);
 }
 
 /*
@@ -466,42 +466,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	int result;
 	u32 scratch, hwmode;
 
-	/* low-level chip reset */
-	if (gpio_is_valid(priv->rst_gpio)) {
-		unsigned int rst_lvl;
-
-		rst_lvl = (priv->devflags &
-			   ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0;
-
-		gpio_set_value(priv->rst_gpio, rst_lvl);
-		mdelay(50);
-		gpio_set_value(priv->rst_gpio, !rst_lvl);
-	}
-
-	/* 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);
@@ -511,31 +475,27 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 		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);
@@ -2239,7 +2199,7 @@ void isp1760_deinit_kmem_cache(void)
 
 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;
@@ -2251,7 +2211,6 @@ int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs,
 	*(struct isp1760_hcd **)hcd->hcd_priv = priv;
 
 	priv->hcd = hcd;
-	priv->devflags = devflags;
 
 	init_memory(priv);
 
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index 51996a2..df7ea36 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -26,21 +26,6 @@ struct usb_hcd;
 #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 */
-#define ISP1760_FLAG_RESET_ACTIVE_HIGH	0x80000000 /* RESET GPIO active high */
-
 struct isp1760_slotinfo {
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
@@ -79,14 +64,11 @@ struct isp1760_hcd {
 	unsigned		i_thresh;
 	unsigned long		reset_done;
 	unsigned long		next_statechange;
-	unsigned int		devflags;
-
-	int			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);
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux