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
					
				| @ -312,6 +312,11 @@ static int __init _omap2_init_reprogram_sdrc(void) | |||||||
| 	return v; | 	return v; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data) | ||||||
|  | { | ||||||
|  | 	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Initialize asm_irq_base for entry-macro.S |  * Initialize asm_irq_base for entry-macro.S | ||||||
|  */ |  */ | ||||||
| @ -333,6 +338,8 @@ static inline void omap_irq_base_init(void) | |||||||
| 
 | 
 | ||||||
| void __init omap2_init_common_infrastructure(void) | void __init omap2_init_common_infrastructure(void) | ||||||
| { | { | ||||||
|  | 	u8 postsetup_state; | ||||||
|  | 
 | ||||||
| 	pwrdm_init(powerdomains_omap); | 	pwrdm_init(powerdomains_omap); | ||||||
| 	clkdm_init(clockdomains_omap, clkdm_autodeps); | 	clkdm_init(clockdomains_omap, clkdm_autodeps); | ||||||
| 	if (cpu_is_omap242x()) | 	if (cpu_is_omap242x()) | ||||||
| @ -343,6 +350,16 @@ void __init omap2_init_common_infrastructure(void) | |||||||
| 		omap3xxx_hwmod_init(); | 		omap3xxx_hwmod_init(); | ||||||
| 	else if (cpu_is_omap44xx()) | 	else if (cpu_is_omap44xx()) | ||||||
| 		omap44xx_hwmod_init(); | 		omap44xx_hwmod_init(); | ||||||
|  | 	else | ||||||
|  | 		pr_err("Could not init hwmod data - unknown SoC\n"); | ||||||
|  | 
 | ||||||
|  | 	/* Set the default postsetup state for all hwmods */ | ||||||
|  | #ifdef CONFIG_PM_RUNTIME | ||||||
|  | 	postsetup_state = _HWMOD_STATE_IDLE; | ||||||
|  | #else | ||||||
|  | 	postsetup_state = _HWMOD_STATE_ENABLED; | ||||||
|  | #endif | ||||||
|  | 	omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state); | ||||||
| 
 | 
 | ||||||
| 	omap_pm_if_early_init(); | 	omap_pm_if_early_init(); | ||||||
| 
 | 
 | ||||||
| @ -355,25 +372,16 @@ void __init omap2_init_common_infrastructure(void) | |||||||
| 	else if (cpu_is_omap44xx()) | 	else if (cpu_is_omap44xx()) | ||||||
| 		omap4xxx_clk_init(); | 		omap4xxx_clk_init(); | ||||||
| 	else | 	else | ||||||
| 		pr_err("Could not init clock framework - unknown CPU\n"); | 		pr_err("Could not init clock framework - unknown SoC\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * XXX Ideally, this function will dwindle into nothingness over time; |  | ||||||
|  * almost all device init code should be possible through initcalls |  | ||||||
|  * and other generalized mechanisms |  | ||||||
|  */ |  | ||||||
| void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0, | void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0, | ||||||
| 				      struct omap_sdrc_params *sdrc_cs1) | 				      struct omap_sdrc_params *sdrc_cs1) | ||||||
| { | { | ||||||
| 	u8 skip_setup_idle = 0; |  | ||||||
| 
 |  | ||||||
| 	omap_serial_early_init(); | 	omap_serial_early_init(); | ||||||
| 
 | 
 | ||||||
| #ifndef CONFIG_PM_RUNTIME | 	omap_hwmod_late_init(); | ||||||
| 	skip_setup_idle = 1; | 
 | ||||||
| #endif |  | ||||||
| 	omap_hwmod_late_init(skip_setup_idle); |  | ||||||
| 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | ||||||
| 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1); | 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1); | ||||||
| 		_omap2_init_reprogram_sdrc(); | 		_omap2_init_reprogram_sdrc(); | ||||||
|  | |||||||
| @ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh) | |||||||
| /**
 | /**
 | ||||||
|  * _setup - do initial configuration of omap_hwmod |  * _setup - do initial configuration of omap_hwmod | ||||||
|  * @oh: struct 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 |  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh | ||||||
|  * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on |  * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the | ||||||
|  * a system that will not call omap_hwmod_enable() to enable devices |  * wrong state or returns 0. | ||||||
|  * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod |  | ||||||
|  * is in the wrong state or returns 0. |  | ||||||
|  */ |  */ | ||||||
| static int _setup(struct omap_hwmod *oh, void *data) | static int _setup(struct omap_hwmod *oh, void *data) | ||||||
| { | { | ||||||
| 	int i, r; | 	int i, r; | ||||||
| 	u8 skip_setup_idle; | 	u8 postsetup_state; | ||||||
| 
 |  | ||||||
| 	if (!oh || !data) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	skip_setup_idle = *(u8 *)data; |  | ||||||
| 
 | 
 | ||||||
| 	/* Set iclk autoidle mode */ | 	/* Set iclk autoidle mode */ | ||||||
| 	if (oh->slaves_cnt > 0) { | 	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; | 	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); | 		_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; | 	return 0; | ||||||
| } | } | ||||||
| @ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh) | |||||||
| 
 | 
 | ||||||
| 	list_add_tail(&oh->node, &omap_hwmod_list); | 	list_add_tail(&oh->node, &omap_hwmod_list); | ||||||
| 
 | 
 | ||||||
|  | 	mutex_init(&oh->_mutex); | ||||||
|  | 
 | ||||||
| 	oh->_state = _HWMOD_STATE_REGISTERED; | 	oh->_state = _HWMOD_STATE_REGISTERED; | ||||||
| 
 | 
 | ||||||
| 	ret = 0; | 	ret = 0; | ||||||
| @ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs) | |||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * omap_hwmod_late_init - do some post-clock framework initialization |  * 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 |  * Must be called after omap2_clk_init().  Resolves the struct clk names | ||||||
|  * to struct clk pointers for each registered omap_hwmod.  Also calls |  * to struct clk pointers for each registered omap_hwmod.  Also calls | ||||||
|  * _setup() on each hwmod.  Returns 0. |  * _setup() on each hwmod.  Returns 0. | ||||||
|  */ |  */ | ||||||
| int omap_hwmod_late_init(u8 skip_setup_idle) | int omap_hwmod_late_init(void) | ||||||
| { | { | ||||||
| 	int r; | 	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", | 	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", | ||||||
| 	     MPU_INITIATOR_NAME); | 	     MPU_INITIATOR_NAME); | ||||||
| 
 | 
 | ||||||
| 	if (skip_setup_idle) | 	omap_hwmod_for_each(_setup, NULL); | ||||||
| 		pr_debug("omap_hwmod: will leave hwmods enabled during setup\n"); |  | ||||||
| 
 |  | ||||||
| 	omap_hwmod_for_each(_setup, &skip_setup_idle); |  | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname, | |||||||
| 	return ret; | 	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; | ||||||
|  | } | ||||||
|  | |||||||
| @ -462,6 +462,7 @@ struct omap_hwmod_class { | |||||||
|  * @response_lat: device OCP response latency (in interface clock cycles) |  * @response_lat: device OCP response latency (in interface clock cycles) | ||||||
|  * @_int_flags: internal-use hwmod flags |  * @_int_flags: internal-use hwmod flags | ||||||
|  * @_state: internal-use hwmod state |  * @_state: internal-use hwmod state | ||||||
|  |  * @_postsetup_state: internal-use state to leave the hwmod in after _setup() | ||||||
|  * @flags: hwmod flags (documented below) |  * @flags: hwmod flags (documented below) | ||||||
|  * @omap_chip: OMAP chips this hwmod is present on |  * @omap_chip: OMAP chips this hwmod is present on | ||||||
|  * @_mutex: mutex serializing operations on this hwmod |  * @_mutex: mutex serializing operations on this hwmod | ||||||
| @ -510,6 +511,7 @@ struct omap_hwmod { | |||||||
| 	u8				hwmods_cnt; | 	u8				hwmods_cnt; | ||||||
| 	u8				_int_flags; | 	u8				_int_flags; | ||||||
| 	u8				_state; | 	u8				_state; | ||||||
|  | 	u8				_postsetup_state; | ||||||
| 	const struct omap_chip_id	omap_chip; | 	const struct omap_chip_id	omap_chip; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -519,7 +521,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh); | |||||||
| struct omap_hwmod *omap_hwmod_lookup(const char *name); | struct omap_hwmod *omap_hwmod_lookup(const char *name); | ||||||
| int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), | int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), | ||||||
| 			void *data); | 			void *data); | ||||||
| int omap_hwmod_late_init(u8 skip_setup_idle); | int omap_hwmod_late_init(void); | ||||||
| 
 | 
 | ||||||
| int omap_hwmod_enable(struct omap_hwmod *oh); | int omap_hwmod_enable(struct omap_hwmod *oh); | ||||||
| int _omap_hwmod_enable(struct omap_hwmod *oh); | int _omap_hwmod_enable(struct omap_hwmod *oh); | ||||||
| @ -566,6 +568,8 @@ int omap_hwmod_for_each_by_class(const char *classname, | |||||||
| 					   void *user), | 					   void *user), | ||||||
| 				 void *user); | 				 void *user); | ||||||
| 
 | 
 | ||||||
|  | int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Chip variant-specific hwmod init routines - XXX should be converted |  * Chip variant-specific hwmod init routines - XXX should be converted | ||||||
|  * to use initcalls once the initial boot ordering is straightened out |  * to use initcalls once the initial boot ordering is straightened out | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user