OMAP2+: hwmod: add postsetup state
Allow board files and OMAP core code to control the state that some or all of the hwmods end up in at the end of _setup() (called by omap_hwmod_late_init() ). Reimplement the old skip_setup_idle code in terms of this new postsetup state code. There are two use-cases for this patch: the !CONFIG_PM_RUNTIME case, in which all IP blocks should stay enabled after _setup() finishes; and the MPU watchdog case, in which the watchdog IP block should enter idle if watchdog coverage of kernel initialization is desired, and should be disabled otherwise. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Benoît Cousson <b-cousson@ti.com> Cc: Kevin Hilman <khilman@deeprootsystems.com> Cc: Charulatha Varadarajan <charu@ti.com>
This commit is contained in:
		
					parent
					
						
							
								e4dc8f507c
							
						
					
				
			
			
				commit
				
					
						2092e5ccf8
					
				
			
		
					 3 changed files with 88 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh)
 | 
			
		|||
/**
 | 
			
		||||
 * _setup - do initial configuration of omap_hwmod
 | 
			
		||||
 * @oh: struct omap_hwmod *
 | 
			
		||||
 * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
 | 
			
		||||
 *
 | 
			
		||||
 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
 | 
			
		||||
 * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
 | 
			
		||||
 * a system that will not call omap_hwmod_enable() to enable devices
 | 
			
		||||
 * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
 | 
			
		||||
 * is in the wrong state or returns 0.
 | 
			
		||||
 * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
 | 
			
		||||
 * wrong state or returns 0.
 | 
			
		||||
 */
 | 
			
		||||
static int _setup(struct omap_hwmod *oh, void *data)
 | 
			
		||||
{
 | 
			
		||||
	int i, r;
 | 
			
		||||
	u8 skip_setup_idle;
 | 
			
		||||
 | 
			
		||||
	if (!oh || !data)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	skip_setup_idle = *(u8 *)data;
 | 
			
		||||
	u8 postsetup_state;
 | 
			
		||||
 | 
			
		||||
	/* Set iclk autoidle mode */
 | 
			
		||||
	if (oh->slaves_cnt > 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1349,7 +1341,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mutex_init(&oh->_mutex);
 | 
			
		||||
	oh->_state = _HWMOD_STATE_INITIALIZED;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -1383,8 +1374,25 @@ static int _setup(struct omap_hwmod *oh, void *data)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
 | 
			
		||||
	postsetup_state = oh->_postsetup_state;
 | 
			
		||||
	if (postsetup_state == _HWMOD_STATE_UNKNOWN)
 | 
			
		||||
		postsetup_state = _HWMOD_STATE_ENABLED;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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) &&
 | 
			
		||||
	    (postsetup_state == _HWMOD_STATE_IDLE))
 | 
			
		||||
		postsetup_state = _HWMOD_STATE_ENABLED;
 | 
			
		||||
 | 
			
		||||
	if (postsetup_state == _HWMOD_STATE_IDLE)
 | 
			
		||||
		_omap_hwmod_idle(oh);
 | 
			
		||||
	else if (postsetup_state == _HWMOD_STATE_DISABLED)
 | 
			
		||||
		_shutdown(oh);
 | 
			
		||||
	else if (postsetup_state != _HWMOD_STATE_ENABLED)
 | 
			
		||||
		WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
 | 
			
		||||
		     oh->name, postsetup_state);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh)
 | 
			
		|||
 | 
			
		||||
	list_add_tail(&oh->node, &omap_hwmod_list);
 | 
			
		||||
 | 
			
		||||
	mutex_init(&oh->_mutex);
 | 
			
		||||
 | 
			
		||||
	oh->_state = _HWMOD_STATE_REGISTERED;
 | 
			
		||||
 | 
			
		||||
	ret = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
 | 
			
		|||
 | 
			
		||||
/**
 | 
			
		||||
 * omap_hwmod_late_init - do some post-clock framework initialization
 | 
			
		||||
 * @skip_setup_idle: if 1, do not idle hwmods in _setup()
 | 
			
		||||
 *
 | 
			
		||||
 * Must be called after omap2_clk_init().  Resolves the struct clk names
 | 
			
		||||
 * to struct clk pointers for each registered omap_hwmod.  Also calls
 | 
			
		||||
 * _setup() on each hwmod.  Returns 0.
 | 
			
		||||
 */
 | 
			
		||||
int omap_hwmod_late_init(u8 skip_setup_idle)
 | 
			
		||||
int omap_hwmod_late_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1603,10 +1612,7 @@ int omap_hwmod_late_init(u8 skip_setup_idle)
 | 
			
		|||
	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
 | 
			
		||||
	     MPU_INITIATOR_NAME);
 | 
			
		||||
 | 
			
		||||
	if (skip_setup_idle)
 | 
			
		||||
		pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
 | 
			
		||||
 | 
			
		||||
	omap_hwmod_for_each(_setup, &skip_setup_idle);
 | 
			
		||||
	omap_hwmod_for_each(_setup, NULL);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname,
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod
 | 
			
		||||
 * @oh: struct omap_hwmod *
 | 
			
		||||
 * @state: state that _setup() should leave the hwmod in
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the hwmod state that @oh will enter at the end of _setup() (called by
 | 
			
		||||
 * omap_hwmod_late_init()).  Only valid to call between calls to
 | 
			
		||||
 * omap_hwmod_init() and omap_hwmod_late_init().  Returns 0 upon success or
 | 
			
		||||
 * -EINVAL if there is a problem with the arguments or if the hwmod is
 | 
			
		||||
 * in the wrong state.
 | 
			
		||||
 */
 | 
			
		||||
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!oh)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (state != _HWMOD_STATE_DISABLED &&
 | 
			
		||||
	    state != _HWMOD_STATE_ENABLED &&
 | 
			
		||||
	    state != _HWMOD_STATE_IDLE)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&oh->_mutex);
 | 
			
		||||
 | 
			
		||||
	if (oh->_state != _HWMOD_STATE_REGISTERED) {
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		goto ohsps_unlock;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oh->_postsetup_state = state;
 | 
			
		||||
	ret = 0;
 | 
			
		||||
 | 
			
		||||
ohsps_unlock:
 | 
			
		||||
	mutex_unlock(&oh->_mutex);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue