diff options
| -rw-r--r-- | arch/arm/mach-omap2/clockdomain.h | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clockdomains44xx_data.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 32 | 
4 files changed, 30 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index f7b58609bad..6227e9505c2 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -31,12 +31,16 @@   *   * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this   *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.) + * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is + *     active whenever the MPU is active.  True for interconnects and + *     the WKUP clockdomains.   */  #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)  #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)  #define CLKDM_CAN_ENABLE_AUTO			(1 << 2)  #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)  #define CLKDM_NO_AUTODEPS			(1 << 4) +#define CLKDM_ACTIVE_WITH_MPU			(1 << 5)  #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)  #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c index 839145e1cfb..4972219653c 100644 --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c @@ -88,4 +88,5 @@ struct clockdomain wkup_common_clkdm = {  	.name		= "wkup_clkdm",  	.pwrdm		= { .name = "wkup_pwrdm" },  	.dep_bit	= OMAP_EN_WKUP_SHIFT, +	.flags		= CLKDM_ACTIVE_WITH_MPU,  }; diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index c5342584749..7f2133abe7d 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -381,7 +381,7 @@ static struct clockdomain l4_wkup_44xx_clkdm = {  	.cm_inst	  = OMAP4430_PRM_WKUP_CM_INST,  	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,  	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT, -	.flags		  = CLKDM_CAN_HWSUP, +	.flags		  = CLKDM_CAN_HWSUP | CLKDM_ACTIVE_WITH_MPU,  };  static struct clockdomain emu_sys_44xx_clkdm = { diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 773193670ea..2d710f50fca 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1124,15 +1124,18 @@ static struct omap_hwmod_addr_space * __init _find_mpu_rt_addr_space(struct omap   * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG   * @oh: struct omap_hwmod *   * - * If module is marked as SWSUP_SIDLE, force the module out of slave - * idle; otherwise, configure it for smart-idle.  If module is marked - * as SWSUP_MSUSPEND, force the module out of master standby; - * otherwise, configure it for smart-standby.  No return value. + * Ensure that the OCP_SYSCONFIG register for the IP block represented + * by @oh is set to indicate to the PRCM that the IP block is active. + * Usually this means placing the module into smart-idle mode and + * smart-standby, but if there is a bug in the automatic idle handling + * for the IP block, it may need to be placed into the force-idle or + * no-idle variants of these modes.  No return value.   */  static void _enable_sysc(struct omap_hwmod *oh)  {  	u8 idlemode, sf;  	u32 v; +	bool clkdm_act;  	if (!oh->class->sysc)  		return; @@ -1141,8 +1144,16 @@ static void _enable_sysc(struct omap_hwmod *oh)  	sf = oh->class->sysc->sysc_flags;  	if (sf & SYSC_HAS_SIDLEMODE) { -		idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ? -			HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; +		clkdm_act = ((oh->clkdm && +			      oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) || +			     (oh->_clk && oh->_clk->clkdm && +			      oh->_clk->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);  	} @@ -1208,8 +1219,13 @@ static void _idle_sysc(struct omap_hwmod *oh)  	sf = oh->class->sysc->sysc_flags;  	if (sf & SYSC_HAS_SIDLEMODE) { -		idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ? -			HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART; +		/* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */ +		if (oh->flags & HWMOD_SWSUP_SIDLE || +		    !(oh->class->sysc->idlemodes & +		      (SIDLE_SMART | SIDLE_SMART_WKUP))) +			idlemode = HWMOD_IDLEMODE_FORCE; +		else +			idlemode = HWMOD_IDLEMODE_SMART;  		_set_slave_idlemode(oh, idlemode, &v);  	}  |