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))