|  | @@ -555,3 +555,134 @@ static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
 | 
	
		
			
				|  |  |  	int j;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (!oh->mux || !oh->mux->enabled)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
 | 
	
		
			
				|  |  | +		pad = oh->mux->pads_dynamic[j];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
 | 
	
		
			
				|  |  | +			continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		prev_idle = pad->idle;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (set_wake)
 | 
	
		
			
				|  |  | +			pad->idle |= OMAP_WAKEUP_EN;
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +			pad->idle &= ~OMAP_WAKEUP_EN;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (prev_idle != pad->idle)
 | 
	
		
			
				|  |  | +			change = true;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (change && oh->_state == _HWMOD_STATE_IDLE)
 | 
	
		
			
				|  |  | +		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
 | 
	
		
			
				|  |  | + * @oh: struct omap_hwmod *
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Allow the hardware module @oh to send wakeups.  Returns -EINVAL
 | 
	
		
			
				|  |  | + * upon error or 0 upon success.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (!oh->class->sysc ||
 | 
	
		
			
				|  |  | +	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
 | 
	
		
			
				|  |  | +	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
 | 
	
		
			
				|  |  | +	      (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!oh->class->sysc->sysc_fields) {
 | 
	
		
			
				|  |  | +		WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name);
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
 | 
	
		
			
				|  |  | +		*v |= 0x1 << oh->class->sysc->sysc_fields->enwkup_shift;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
 | 
	
		
			
				|  |  | +		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
 | 
	
		
			
				|  |  | +		_set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	oh->_int_flags |= _HWMOD_WAKEUP_ENABLED;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * _disable_wakeup: clear OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
 | 
	
		
			
				|  |  | + * @oh: struct omap_hwmod *
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Prevent the hardware module @oh to send wakeups.  Returns -EINVAL
 | 
	
		
			
				|  |  | + * upon error or 0 upon success.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (!oh->class->sysc ||
 | 
	
		
			
				|  |  | +	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
 | 
	
		
			
				|  |  | +	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
 | 
	
		
			
				|  |  | +	      (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!oh->class->sysc->sysc_fields) {
 | 
	
		
			
				|  |  | +		WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name);
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
 | 
	
		
			
				|  |  | +		*v &= ~(0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
 | 
	
		
			
				|  |  | +		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
 | 
	
		
			
				|  |  | +	if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
 | 
	
		
			
				|  |  | +		_set_master_standbymode(oh, HWMOD_IDLEMODE_SMART, v);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	oh->_int_flags &= ~_HWMOD_WAKEUP_ENABLED;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct clk_hw_omap *clk;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (oh->clkdm) {
 | 
	
		
			
				|  |  | +		return oh->clkdm;
 | 
	
		
			
				|  |  | +	} else if (oh->_clk) {
 | 
	
		
			
				|  |  | +		clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
 | 
	
		
			
				|  |  | +		return  clk->clkdm;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return NULL;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active
 | 
	
		
			
				|  |  | + * @oh: struct omap_hwmod *
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Prevent the hardware module @oh from entering idle while the
 | 
	
		
			
				|  |  | + * hardare module initiator @init_oh is active.  Useful when a module
 | 
	
		
			
				|  |  | + * will be accessed by a particular initiator (e.g., if a module will
 | 
	
		
			
				|  |  | + * be accessed by the IVA, there should be a sleepdep between the IVA
 | 
	
		
			
				|  |  | + * initiator and the module).  Only applies to modules in smart-idle
 | 
	
		
			
				|  |  | + * mode.  If the clockdomain is marked as not needing autodeps, return
 | 
	
		
			
				|  |  | + * 0 without doing anything.  Otherwise, returns -EINVAL upon error or
 | 
	
		
			
				|  |  | + * passes along clkdm_add_sleepdep() value upon success.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct clockdomain *clkdm, *init_clkdm;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	clkdm = _get_clkdm(oh);
 | 
	
		
			
				|  |  | +	init_clkdm = _get_clkdm(init_oh);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!clkdm || !init_clkdm)
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
 | 
	
		
			
				|  |  | +		return 0;
 |