lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 29 Nov 2013 15:01:58 +0200
From:	Roger Quadros <rogerq@...com>
To:	<lee.jones@...aro.org>, <sameo@...ux.intel.com>
CC:	<tomi.valkeinen@...com>, <balbi@...com>, <sr@...x.de>,
	<ljkenny.mailinglists@...il.com>, <linux-omap@...r.kernel.org>,
	<linux-usb@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	Roger Quadros <rogerq@...com>, <stable@...r.kernel.org>
Subject: [PATCH 1/1] mfd: omap-usb-host: Fix USB device detection problems on OMAP4 Panda

With u-boot 2013.10, USB devices are sometimes not detected
on OMAP4 Panda. To make us independent of what bootloader does
with the USB Host module, we must RESET it to get it to a known
good state. This patch Soft RESETs the USB Host module.

Reported-by: Tomi Valkeinen <tomi.valkeinen@...com>
Cc: <stable@...r.kernel.org> # 3.10+
Signed-off-by: Roger Quadros <rogerq@...com>
---
 drivers/mfd/omap-usb-host.c | 115 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 109 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 142650f..d4bd464 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -43,14 +43,18 @@
 /* UHH Register Set */
 #define	OMAP_UHH_REVISION				(0x00)
 #define	OMAP_UHH_SYSCONFIG				(0x10)
-#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
+#define	OMAP_UHH_SYSCONFIG_MIDLEMASK			(3 << 12)
+#define OMAP_UHH_SYSCONFIG_MIDLESHIFT			(12)
 #define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_UHH_SYSCONFIG_SIDLEMASK			(3 << 3)
+#define	OMAP_UHH_SYSCONFIG_SIDLESHIFT			(3)
 #define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
 #define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
 #define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
 
 #define	OMAP_UHH_SYSSTATUS				(0x14)
+#define OMAP_UHH_SYSSTATUS_RESETDONE			(1 << 0)
+
 #define	OMAP_UHH_HOSTCONFIG				(0x40)
 #define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
 #define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
@@ -66,10 +70,10 @@
 #define OMAP4_UHH_HOSTCONFIG_APP_START_CLK		(1 << 31)
 
 /* OMAP4-specific defines */
-#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
-#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
-#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
-#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
+#define OMAP4_UHH_SYSCONFIG_MIDLEMASK			(3 << 2)
+#define OMAP4_UHH_SYSCONFIG_MIDLESHIFT			(2)
+#define OMAP4_UHH_SYSCONFIG_SIDLEMASK			(3 << 4)
+#define OMAP4_UHH_SYSCONFIG_SIDLESHIFT			(4)
 #define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
 
 #define OMAP4_P1_MODE_CLEAR				(3 << 16)
@@ -81,6 +85,12 @@
 
 #define	OMAP_UHH_DEBUG_CSR				(0x44)
 
+/* MIDLE modes */
+#define OMAP_UHH_SYSCONFIG_MIDLE_NOSTANDBY		(1)
+
+/* SIDLE modes */
+#define OMAP_UHH_SYSCONFIG_SIDLE_NOIDLE			(1)
+
 /* Values of UHH_REVISION - Note: these are not given in the TRM */
 #define OMAP_USBHS_REV1		0x00000010	/* OMAP3 */
 #define OMAP_USBHS_REV2		0x50700100	/* OMAP4 */
@@ -474,6 +484,97 @@ static unsigned omap_usbhs_rev2_hostconfig(struct usbhs_hcd_omap *omap,
 	return reg;
 }
 
+static void omap_usbhs_rev1_reset(struct device *dev)
+{
+	struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
+	u32 reg;
+	unsigned long timeout;
+
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
+
+	/* Soft Reset */
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
+		    reg | OMAP_UHH_SYSCONFIG_SOFTRESET);
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+			& OMAP_UHH_SYSSTATUS_RESETDONE)) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(dev, "Soft RESET operation timed out\n");
+			break;
+		}
+	}
+
+	/* Set No-Standby */
+	reg &= ~OMAP_UHH_SYSCONFIG_MIDLEMASK;
+	reg |= OMAP_UHH_SYSCONFIG_MIDLE_NOSTANDBY
+		<< OMAP_UHH_SYSCONFIG_MIDLESHIFT;
+
+	/* Set No-Idle */
+	reg &= ~OMAP_UHH_SYSCONFIG_SIDLEMASK;
+	reg |= OMAP_UHH_SYSCONFIG_SIDLE_NOIDLE
+		<< OMAP_UHH_SYSCONFIG_SIDLESHIFT;
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
+}
+
+static void omap_usbhs_rev2_reset(struct device *dev)
+{
+	struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
+	u32 reg;
+	unsigned long timeout;
+
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
+
+	/* Soft Reset */
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
+		    reg | OMAP4_UHH_SYSCONFIG_SOFTRESET);
+
+	/* OMAP4: Need to wait before SYSCONFIG can be accessed */
+	udelay(2);
+	timeout = jiffies + msecs_to_jiffies(100);
+
+	/* SOFTRESET bit clears when RESET completes */
+	while (usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG)
+			& OMAP4_UHH_SYSCONFIG_SOFTRESET) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(dev, "Soft RESET operation timed out\n");
+			break;
+		}
+	}
+
+	/* Set No-Standby */
+	reg &= ~OMAP4_UHH_SYSCONFIG_MIDLEMASK;
+	reg |= OMAP_UHH_SYSCONFIG_MIDLE_NOSTANDBY
+		<< OMAP4_UHH_SYSCONFIG_MIDLESHIFT;
+
+	/* Set No-Idle */
+	reg &= ~OMAP4_UHH_SYSCONFIG_SIDLEMASK;
+	reg |= OMAP_UHH_SYSCONFIG_SIDLE_NOIDLE
+		<< OMAP4_UHH_SYSCONFIG_SIDLESHIFT;
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
+}
+
+static void omap_usbhs_softreset(struct device *dev)
+{
+	struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
+
+	switch (omap->usbhs_rev) {
+	case OMAP_USBHS_REV1:
+		omap_usbhs_rev1_reset(dev);
+		break;
+
+	default:	/* Rev 2 onwards */
+		omap_usbhs_rev2_reset(dev);
+		break;
+	}
+}
+
 static void omap_usbhs_init(struct device *dev)
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
@@ -483,6 +584,8 @@ static void omap_usbhs_init(struct device *dev)
 
 	pm_runtime_get_sync(dev);
 
+	omap_usbhs_softreset(dev);
+
 	reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
 	/* setup ULPI bypass and burst configurations */
 	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ