--- /dev/null
+From 313a76ee11cda6700548afe68499ef174a240688 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Sun, 8 Dec 2013 18:39:02 -0700
+Subject: ARM: OMAP2+: hwmod: Fix SOFTRESET logic
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 313a76ee11cda6700548afe68499ef174a240688 upstream.
+
+In _ocp_softreset(), after _set_softreset() + write_sysconfig(),
+the hwmod's sysc_cache will always contain SOFTRESET bit set
+so all further writes to sysconfig using this cache will initiate
+a repeated SOFTRESET e.g. enable_sysc(). This is true for OMAP3 like
+platforms that have RESET_DONE status in the SYSSTATUS register and
+so the the SOFTRESET bit in SYSCONFIG is not automatically cleared.
+It is not a problem for OMAP4 like platforms that indicate RESET
+completion by clearing the SOFTRESET bit in the SYSCONFIG register.
+
+This repeated SOFTRESET is undesired and was the root cause of
+USB host issues on OMAP3 platforms when hwmod was allowed to do the
+SOFTRESET for the USB Host module.
+
+To fix this we clear the SOFTRESET bit and update the sysconfig
+register + sysc_cache using write_sysconfig().
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Tested-by: Tomi Valkeinen <tomi.valkeinen@ti.com> # Panda, BeagleXM
+[paul@pwsan.com: renamed _clr_softreset() to _clear_softreset()]
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/mach-omap2/omap_hwmod.c | 43 ++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 42 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mach-omap2/omap_hwmod.c
++++ b/arch/arm/mach-omap2/omap_hwmod.c
+@@ -317,7 +317,7 @@ static int _set_clockactivity(struct oma
+ }
+
+ /**
+- * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
++ * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
+ * @oh: struct omap_hwmod *
+ * @v: pointer to register contents to modify
+ *
+@@ -1378,6 +1378,36 @@ static int _read_hardreset(struct omap_h
+ }
+
+ /**
++ * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
++ * @oh: struct omap_hwmod *
++ * @v: pointer to register contents to modify
++ *
++ * Clear the SOFTRESET bit in @v for hwmod @oh. Returns -EINVAL upon
++ * error or 0 upon success.
++ */
++static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
++{
++ u32 softrst_mask;
++
++ if (!oh->class->sysc ||
++ !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
++ return -EINVAL;
++
++ if (!oh->class->sysc->sysc_fields) {
++ WARN(1,
++ "omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
++ oh->name);
++ return -EINVAL;
++ }
++
++ softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
++
++ *v &= ~softrst_mask;
++
++ return 0;
++}
++
++/**
+ * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
+ * @oh: struct omap_hwmod *
+ *
+@@ -1420,6 +1450,12 @@ static int _ocp_softreset(struct omap_hw
+ ret = _set_softreset(oh, &v);
+ if (ret)
+ goto dis_opt_clks;
++
++ _write_sysconfig(v, oh);
++ ret = _clear_softreset(oh, &v);
++ if (ret)
++ goto dis_opt_clks;
++
+ _write_sysconfig(v, oh);
+
+ if (oh->class->sysc->srst_udelay)
+@@ -1917,6 +1953,11 @@ int omap_hwmod_softreset(struct omap_hwm
+ if (ret)
+ goto error;
+ _write_sysconfig(v, oh);
++
++ ret = _clear_softreset(oh, &v);
++ if (ret)
++ goto error;
++ _write_sysconfig(v, oh);
+
+ error:
+ return ret;