index 1723f755fabd18a745916d4edfc331e5b923a3c6..2d5ea6b49f4a155a5e85d0eb622facf5c0d9f3b8 100644 (file)
*/
static int _idle(struct omap_hwmod *oh)
{
+ if (oh->flags & HWMOD_NO_IDLE) {
+ oh->_int_flags |= _HWMOD_SKIP_ENABLE;
+ return 0;
+ }
+
pr_debug("omap_hwmod: %s: idling\n", oh->name);
if (oh->_state != _HWMOD_STATE_ENABLED) {
* registers. This address is needed early so the OCP registers that
* are part of the device's address space can be ioremapped properly.
*
+ * If SYSC access is not needed, the registers will not be remapped
+ * and non-availability of MPU access is not treated as an error.
+ *
* Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
* -ENXIO on absent or invalid register target address space.
*/
_save_mpu_port_index(oh);
+ /* if we don't need sysc access we don't need to ioremap */
+ if (!oh->class->sysc)
+ return 0;
+
+ /* we can't continue without MPU PORT if we need sysc access */
if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
return -ENXIO;
oh->name);
/* Extract the IO space from device tree blob */
- if (!np)
+ if (!np) {
+ pr_err("omap_hwmod: %s: no dt node\n", oh->name);
return -ENXIO;
+ }
va_start = of_iomap(np, index + oh->mpu_rt_idx);
} else {
oh->name, np->name);
}
- if (oh->class->sysc) {
- r = _init_mpu_rt_base(oh, NULL, index, np);
- if (r < 0) {
- WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
- oh->name);
- return 0;
- }
+ r = _init_mpu_rt_base(oh, NULL, index, np);
+ if (r < 0) {
+ WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+ oh->name);
+ return 0;
}
r = _init_clocks(oh, NULL);
oh->flags |= HWMOD_INIT_NO_RESET;
if (of_find_property(np, "ti,no-idle-on-init", NULL))
oh->flags |= HWMOD_INIT_NO_IDLE;
+ if (of_find_property(np, "ti,enable-opt-clks-on-reset", NULL))
+ oh->flags |= HWMOD_CONTROL_OPT_CLKS_IN_RESET;
if (of_find_property(np, "ti,no-init", NULL))
oh->flags |= HWMOD_NO_INIT;
+ if (of_find_property(np, "ti,no-idle", NULL))
+ oh->flags |= HWMOD_NO_IDLE;
}
if (oh->flags & HWMOD_NO_INIT)
oh->_state = _HWMOD_STATE_DISABLED;
* XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
* it should be set by the core code as a runtime flag during startup
*/
- if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
+ if ((oh->flags & (HWMOD_INIT_NO_IDLE | HWMOD_NO_IDLE)) &&
(postsetup_state == _HWMOD_STATE_IDLE)) {
oh->_int_flags |= _HWMOD_SKIP_ENABLE;
postsetup_state = _HWMOD_STATE_ENABLED;
oh->prcm.omap4.rstctrl_offs);
}
+/**
+ * _reidle - enable then idle a single hwmod
+ *
+ * enables and then immediately reidles an hwmod, as certain hwmods may
+ * not have their sysconfig registers programmed in an idle friendly state
+ * by default
+ */
+static void _reidle(struct omap_hwmod *oh)
+{
+ pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+ omap_hwmod_enable(oh);
+ omap_hwmod_softreset(oh);
+ omap_hwmod_idle(oh);
+}
+
/**
* _reidle_all - enable then idle all hwmods in oh_reidle_list
*
struct omap_hwmod_list *oh_list_item = NULL;
list_for_each_entry(oh_list_item, &oh_reidle_list, oh_list) {
- omap_hwmod_enable(oh_list_item->oh);
- omap_hwmod_idle(oh_list_item->oh);
+ _reidle(oh_list_item->oh);
}
return 0;
for (i = 0; i < oh->rst_lines_cnt; i++)
if (oh->rst_lines[i].context)
_assert_hardreset(oh, oh->rst_lines[i].name);
- else if (oh->_state == _HWMOD_STATE_ENABLED)
+ else
_deassert_hardreset(oh, oh->rst_lines[i].name);
if (oh->_state == _HWMOD_STATE_ENABLED) {
if (soc_ops.enable_module)
soc_ops.enable_module(oh);
} else {
- if (soc_ops.disable_module)
+ if (oh->flags & HWMOD_NEEDS_REIDLE)
+ _reidle(oh);
+ else if (soc_ops.disable_module)
soc_ops.disable_module(oh);
}