diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 113 |
1 files changed, 27 insertions, 86 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d25a95fe9921..7341eff63f56 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1356,13 +1356,27 @@ static void _enable_sysc(struct omap_hwmod *oh) clkdm = _get_clkdm(oh); if (sf & SYSC_HAS_SIDLEMODE) { + if (oh->flags & HWMOD_SWSUP_SIDLE || + oh->flags & HWMOD_SWSUP_SIDLE_ACT) { + idlemode = HWMOD_IDLEMODE_NO; + } else { + if (sf & SYSC_HAS_ENAWAKEUP) + _enable_wakeup(oh, &v); + if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) + idlemode = HWMOD_IDLEMODE_SMART_WKUP; + else + idlemode = HWMOD_IDLEMODE_SMART; + } + + /* + * This is special handling for some IPs like + * 32k sync timer. Force them to idle! + */ clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU); if (clkdm_act && !(oh->class->sysc->idlemodes & (SIDLE_SMART | SIDLE_SMART_WKUP))) idlemode = HWMOD_IDLEMODE_FORCE; - else - idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ? - HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; + _set_slave_idlemode(oh, idlemode, &v); } @@ -1391,10 +1405,6 @@ static void _enable_sysc(struct omap_hwmod *oh) (sf & SYSC_HAS_CLOCKACTIVITY)) _set_clockactivity(oh, oh->class->sysc->clockact, &v); - /* If slave is in SMARTIDLE, also enable wakeup */ - if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE)) - _enable_wakeup(oh, &v); - _write_sysconfig(v, oh); /* @@ -1430,13 +1440,16 @@ static void _idle_sysc(struct omap_hwmod *oh) sf = oh->class->sysc->sysc_flags; if (sf & SYSC_HAS_SIDLEMODE) { - /* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */ - if (oh->flags & HWMOD_SWSUP_SIDLE || - !(oh->class->sysc->idlemodes & - (SIDLE_SMART | SIDLE_SMART_WKUP))) + if (oh->flags & HWMOD_SWSUP_SIDLE) { idlemode = HWMOD_IDLEMODE_FORCE; - else - idlemode = HWMOD_IDLEMODE_SMART; + } else { + if (sf & SYSC_HAS_ENAWAKEUP) + _enable_wakeup(oh, &v); + if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) + idlemode = HWMOD_IDLEMODE_SMART_WKUP; + else + idlemode = HWMOD_IDLEMODE_SMART; + } _set_slave_idlemode(oh, idlemode, &v); } @@ -1455,10 +1468,6 @@ static void _idle_sysc(struct omap_hwmod *oh) _set_master_standbymode(oh, idlemode, &v); } - /* If slave is in SMARTIDLE, also enable wakeup */ - if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE)) - _enable_wakeup(oh, &v); - _write_sysconfig(v, oh); } @@ -2065,7 +2074,7 @@ static int _omap4_get_context_lost(struct omap_hwmod *oh) * do so is present in the hwmod data, then call it and pass along the * return value; otherwise, return 0. */ -static int __init _enable_preprogram(struct omap_hwmod *oh) +static int _enable_preprogram(struct omap_hwmod *oh) { if (!oh->class->enable_preprogram) return 0; @@ -2246,42 +2255,6 @@ static int _idle(struct omap_hwmod *oh) } /** - * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit - * @oh: struct omap_hwmod * - * @autoidle: desired AUTOIDLE bitfield value (0 or 1) - * - * Sets the IP block's OCP autoidle bit in hardware, and updates our - * local copy. Intended to be used by drivers that require - * direct manipulation of the AUTOIDLE bits. - * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes - * along the return value from _set_module_autoidle(). - * - * Any users of this function should be scrutinized carefully. - */ -int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle) -{ - u32 v; - int retval = 0; - unsigned long flags; - - if (!oh || oh->_state != _HWMOD_STATE_ENABLED) - return -EINVAL; - - spin_lock_irqsave(&oh->_lock, flags); - - v = oh->_sysc_cache; - - retval = _set_module_autoidle(oh, autoidle, &v); - - if (!retval) - _write_sysconfig(v, oh); - - spin_unlock_irqrestore(&oh->_lock, flags); - - return retval; -} - -/** * _shutdown - shutdown an omap_hwmod * @oh: struct omap_hwmod * * @@ -3180,38 +3153,6 @@ error: } /** - * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode - * @oh: struct omap_hwmod * - * @idlemode: SIDLEMODE field bits (shifted to bit 0) - * - * Sets the IP block's OCP slave idlemode in hardware, and updates our - * local copy. Intended to be used by drivers that have some erratum - * that requires direct manipulation of the SIDLEMODE bits. Returns - * -EINVAL if @oh is null, or passes along the return value from - * _set_slave_idlemode(). - * - * XXX Does this function have any current users? If not, we should - * remove it; it is better to let the rest of the hwmod code handle this. - * Any users of this function should be scrutinized carefully. - */ -int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode) -{ - u32 v; - int retval = 0; - - if (!oh) - return -EINVAL; - - v = oh->_sysc_cache; - - retval = _set_slave_idlemode(oh, idlemode, &v); - if (!retval) - _write_sysconfig(v, oh); - - return retval; -} - -/** * omap_hwmod_lookup - look up a registered omap_hwmod by name * @name: name of the omap_hwmod to look up * |