oh->prcm.omap4.clkctrl_offs);
 }
 
-/**
- * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
- * @oh: struct omap_hwmod *
- *
- * Disable the PRCM module mode related to the hwmod @oh.
- * Return EINVAL if the modulemode is not supported and 0 in case of success.
- */
-static int _omap4_disable_module(struct omap_hwmod *oh)
-{
-       int v;
-
-       /* The module mode does not exist prior OMAP4 */
-       if (!cpu_is_omap44xx())
-               return -EINVAL;
-
-       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
-               return -EINVAL;
-
-       pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
-
-       omap4_cminst_module_disable(oh->clkdm->prcm_partition,
-                                   oh->clkdm->cm_inst,
-                                   oh->clkdm->clkdm_offs,
-                                   oh->prcm.omap4.clkctrl_offs);
-
-       v = _omap4_wait_target_disable(oh);
-       if (v)
-               pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
-                       oh->name);
-
-       return 0;
-}
-
 /**
  * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
  * @oh: struct omap_hwmod *oh
        }
 }
 
+/**
+ * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset
+ * @oh: struct omap_hwmod *
+ *
+ * If any hardreset line associated with @oh is asserted, then return true.
+ * Otherwise, if @oh has no hardreset lines associated with it, or if
+ * no hardreset lines associated with @oh are asserted, then return false.
+ * This function is used to avoid executing some parts of the IP block
+ * enable/disable sequence if a hardreset line is set.
+ */
+static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
+{
+       int i;
+
+       if (oh->rst_lines_cnt == 0)
+               return false;
+
+       for (i = 0; i < oh->rst_lines_cnt; i++)
+               if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
+                       return true;
+
+       return false;
+}
+
+/**
+ * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * Return EINVAL if the modulemode is not supported and 0 in case of success.
+ */
+static int _omap4_disable_module(struct omap_hwmod *oh)
+{
+       int v;
+
+       /* The module mode does not exist prior OMAP4 */
+       if (!cpu_is_omap44xx())
+               return -EINVAL;
+
+       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+               return -EINVAL;
+
+       pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+       omap4_cminst_module_disable(oh->clkdm->prcm_partition,
+                                   oh->clkdm->cm_inst,
+                                   oh->clkdm->clkdm_offs,
+                                   oh->prcm.omap4.clkctrl_offs);
+
+       if (_are_any_hardreset_lines_asserted(oh))
+               return 0;
+
+       v = _omap4_wait_target_disable(oh);
+       if (v)
+               pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+                       oh->name);
+
+       return 0;
+}
+
 /**
  * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
  * @oh: struct omap_hwmod *
  */
 static int _enable(struct omap_hwmod *oh)
 {
-       int r, i;
+       int r;
        int hwsup = 0;
 
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
        }
 
        /*
-        * If an IP contains HW reset lines, then de-assert them in order
-        * to allow the module state transition. Otherwise the PRCM will return
-        * Intransition status, and the init will failed.
+        * If an IP block contains HW reset lines and any of them are
+        * asserted, we let integration code associated with that
+        * block handle the enable.  We've received very little
+        * information on what those driver authors need, and until
+        * detailed information is provided and the driver code is
+        * posted to the public lists, this is probably the best we
+        * can do.
         */
-       if (oh->_state == _HWMOD_STATE_INITIALIZED ||
-           oh->_state == _HWMOD_STATE_DISABLED)
-               for (i = 0; i < oh->rst_lines_cnt; i++)
-                       _deassert_hardreset(oh, oh->rst_lines[i].name);
+       if (_are_any_hardreset_lines_asserted(oh))
+               return 0;
 
        /* Mux pins for device runtime if populated */
        if (oh->mux && (!oh->mux->enabled ||
                return -EINVAL;
        }
 
+       if (_are_any_hardreset_lines_asserted(oh))
+               return 0;
+
        if (oh->class->sysc)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
                return -EINVAL;
        }
 
+       if (_are_any_hardreset_lines_asserted(oh))
+               return 0;
+
        pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
        if (oh->class->pre_shutdown) {
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
 
-       /*
-        * In the case of hwmod with hardreset that should not be
-        * de-assert at boot time, we have to keep the module
-        * initialized, because we cannot enable it properly with the
-        * reset asserted. Exit without warning because that behavior
-        * is expected.
-        */
-       if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt > 0)
-               return 0;
-
-       r = _enable(oh);
-       if (r) {
-               pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
-                          oh->name, oh->_state);
-               return 0;
+       if (oh->rst_lines_cnt == 0) {
+               r = _enable(oh);
+               if (r) {
+                       pr_warning("omap_hwmod: %s: cannot be enabled for reset (%d)\n",
+                                  oh->name, oh->_state);
+                       return -EINVAL;
+               }
        }
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET))