[PATCH 03/10] OMAP3: PM: move device-specific special cases from PM core into CPUidle

Paul Walmsley paul at pwsan.com
Tue Sep 21 03:52:37 EDT 2010


Hi Kevin,

On Wed, 15 Sep 2010, Kevin Hilman wrote:

> In an effort to simplify the core idle path, move any device-specific
> special case handling from the core PM idle path into the CPUidle
> pre-idle checking path.
> 
> This keeps the core, interrupts-disabled idle path streamlined and
> independent of any device-specific handling, and also allows CPUidle
> to do the checking only for certain C-states as needed.  This patch
> has the device checks in place for all states with the CHECK_BM flag,
> namely all states >= C2.
> 
> This patch was inspired by a similar patch written by Tero Kristo as
> part of a larger series to add INACTIVE state support.

As with the original patch, I don't quite understand the improvement 
here.  In particular, this part:

> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 3d3d035..0923b82 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -233,14 +234,54 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
>  			       struct cpuidle_state *state)
>  {
>  	struct cpuidle_state *new_state = next_valid_state(dev, state);
> +	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
> +	u32 cam_state;
> +	struct omap3_processor_cx *cx;
> +	int ret;
>  
>  	if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
>  		BUG_ON(!dev->safe_state);
>  		new_state = dev->safe_state;
> +		goto select_state;
> +	}
> +
> +	cx = cpuidle_get_statedata(state);
> +	core_next_state = cx->core_state;
> +
> +	/*
> +	 * Prevent idle completely if CAM is active.
> +	 * CAM does not have wakeup capability in OMAP3.
> +	 */
> +	cam_state = pwrdm_read_pwrst(cam_pd);
> +	if (cam_state == PWRDM_POWER_ON) {
> +		new_state = dev->safe_state;
> +		goto select_state;
>  	}
>  
> +	/*
> +	 * Prevent PER off if CORE is not in retention or off as this
> +	 * would disable PER wakeups completely.
> +	 */
> +	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
> +	if ((per_next_state == PWRDM_POWER_OFF) &&
> +	    (core_next_state > PWRDM_POWER_RET)) {
> +		per_next_state = PWRDM_POWER_RET;
> +		pwrdm_set_next_pwrst(per_pd, per_next_state);
> +	}
> +
> +	/* Are we changing PER target state? */
> +	if (per_next_state != per_saved_state)
> +		pwrdm_set_next_pwrst(per_pd, per_next_state);

In this case, the PER / CORE constraints don't have anything to do with 
the MPU or CPUIdle, so they don't seem to belong in the CPUIdle code.  The 
extra comments are certainly nice -- they make it more clear as to what is 
going on here -- but maybe those can just be added to pm34xx.c ?

> +
> +select_state:
>  	dev->last_state = new_state;
> -	return omap3_enter_idle(dev, new_state);
> +	ret = omap3_enter_idle(dev, new_state);
> +
> +	/* Restore original PER state if it was modified */
> +	if (per_next_state != per_saved_state)
> +		pwrdm_set_next_pwrst(per_pd, per_saved_state);
> +
> +	return ret;
>  }
>  
>  DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
> @@ -328,7 +369,8 @@ void omap_init_power_states(void)
>  			cpuidle_params_table[OMAP3_STATE_C2].threshold;
>  	omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
>  	omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
> -	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
> +	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
> +				CPUIDLE_FLAG_CHECK_BM;
>  
>  	/* C3 . MPU CSWR + Core inactive */
>  	omap3_power_states[OMAP3_STATE_C3].valid =
> @@ -426,6 +468,8 @@ int __init omap3_idle_init(void)
>  
>  	mpu_pd = pwrdm_lookup("mpu_pwrdm");
>  	core_pd = pwrdm_lookup("core_pwrdm");
> +	per_pd = pwrdm_lookup("per_pwrdm");
> +	cam_pd = pwrdm_lookup("cam_pwrdm");
>  
>  	omap_init_power_states();
>  	cpuidle_register_driver(&omap3_idle_driver);
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 429268e..bb2ba1e 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -346,7 +346,6 @@ void omap_sram_idle(void)
>  	int core_next_state = PWRDM_POWER_ON;
>  	int core_prev_state, per_prev_state;
>  	u32 sdrc_pwr = 0;
> -	int per_state_modified = 0;
>  
>  	if (!_omap_sram_idle)
>  		return;
> @@ -391,19 +390,10 @@ void omap_sram_idle(void)
>  	if (per_next_state < PWRDM_POWER_ON) {
>  		omap_uart_prepare_idle(2);
>  		omap2_gpio_prepare_for_idle(per_next_state);
> -		if (per_next_state == PWRDM_POWER_OFF) {
> -			if (core_next_state == PWRDM_POWER_ON) {
> -				per_next_state = PWRDM_POWER_RET;
> -				pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
> -				per_state_modified = 1;
> -			} else
> +		if (per_next_state == PWRDM_POWER_OFF)
>  				omap3_per_save_context();
> -		}
>  	}
>  
> -	if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
> -		omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
> -
>  	/* CORE */
>  	if (core_next_state < PWRDM_POWER_ON) {
>  		omap_uart_prepare_idle(0);
> @@ -470,8 +460,6 @@ void omap_sram_idle(void)
>  		if (per_prev_state == PWRDM_POWER_OFF)
>  			omap3_per_restore_context();
>  		omap_uart_resume_idle(2);
> -		if (per_state_modified)
> -			pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
>  	}
>  
>  	/* Disable IO-PAD and IO-CHAIN wakeup */
> -- 
> 1.7.2.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


- Paul



More information about the linux-arm-kernel mailing list