[PATCH v4 7/7] OMAP3630: PM: Erratum i583: disable coreoff if < ES1.2

Kevin Hilman khilman at deeprootsystems.com
Mon Dec 20 14:05:00 EST 2010


Nishanth Menon <nm at ti.com> writes:

> From: Eduardo Valentin <eduardo.valentin at nokia.com>
>
> Limitation i583: Self_Refresh Exit issue after OFF mode
>
> Issue:
> When device is waking up from OFF mode, then SDRC state machine sends
> inappropriate sequence violating JEDEC standards.
>
> Impact:
> OMAP3630 < ES1.2 is impacted as follows depending on the platform:
> CS0: for 38.4MHz as internal sysclk, DDR content seen to be stable, while
> 	for all other sysclk frequencies, varied levels of instability
> 	seen based on varied parameters.
> CS1: impacted
>
> This patch takes option #3 as recommended by the Silicon erratum:
> Avoid core power domain transitioning to OFF mode. Power consumption
> impact is expected in this case.
> To do this, we route core OFF requests to RET request on the impacted
> revisions of silicon.
>
> [nm at ti.com: rebased the code to 2.6.37-rc2- short circuit code changed a bit]
> Signed-off-by: Nishanth Menon <nm at ti.com>
> Signed-off-by: Eduardo Valentin <eduardo.valentin at nokia.com>
> ---
> v4: idle state control changed a bit -we wont register or enable
>     the states which cannot be enabled.

I like this version.  Thanks.

> v3: http://marc.info/?t=129140247800027&r=1&w=2
>     no functional change in erratum wa implementation, just registration of
>  	erratum is collated to a single cpu detection and version check
> v2: https://patchwork.kernel.org/patch/365262/
>     rebased to this patch series instead of depending on hs changes
>     fix typo for macro definition
> v1: http://marc.info/?l=linux-omap&m=129013173425266&w=2
>  arch/arm/mach-omap2/cpuidle34xx.c |   10 ++++++++++
>  arch/arm/mach-omap2/pm.h          |    1 +
>  arch/arm/mach-omap2/pm34xx.c      |   24 +++++++++++++++++++++---
>  3 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index f80d3f6..1b32e98 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -453,6 +453,16 @@ void omap_init_power_states(void)
>  	omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
>  	omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
>  				CPUIDLE_FLAG_CHECK_BM;
> +
> +	/*
> +	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
> +	 * enable OFF mode in a stable form for previous revisions.
> +	 * we disable C7 state as a result.
> +	 */
> +	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
> +		omap3_power_states[OMAP3_STATE_C7].valid = 0;
> +		cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
> +	}
>  }
>  
>  struct cpuidle_driver omap3_idle_driver = {
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 92ef400..9032d09 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -87,6 +87,7 @@ extern unsigned int omap24xx_cpu_suspend_sz;
>  extern unsigned int omap34xx_cpu_suspend_sz;
>  
>  #define PM_RTA_ERRATUM_i608		(1 << 0)
> +#define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1)
>  
>  #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
>  extern u16 pm34xx_errata;
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 21cd36e..7faea55 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -928,12 +928,28 @@ void omap3_pm_off_mode_enable(int enable)
>  		state = PWRDM_POWER_RET;
>  
>  #ifdef CONFIG_CPU_IDLE
> -	omap3_cpuidle_update_states(state, state);
> +	/*
> +	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
> +	 * enable OFF mode in a stable form for previous revisions, restrict
> +	 * instead to RET
> +	 */
> +	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
> +		omap3_cpuidle_update_states(state, PWRDM_POWER_RET);
> +	else
> +		omap3_cpuidle_update_states(state, state);
>  #endif
>  
>  	list_for_each_entry(pwrst, &pwrst_list, node) {
> -		pwrst->next_state = state;
> -		omap_set_pwrdm_state(pwrst->pwrdm, state);
> +		if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
> +				pwrst->pwrdm == core_pwrdm &&
> +				state == PWRDM_POWER_OFF) {
> +			pwrst->next_state = PWRDM_POWER_RET;
> +			pr_err("%s: Core OFF disabled due to errata i583\n",
> +				__func__);

This is a warning, not an error condition, so should probably be
pr_warning().

That being said, this could be noisy if enable_off_mode is being toggled
repeatedly, so using WARN_ONCE() might be more appropriate as suggested
by others.

Kevin


> +		} else {
> +			pwrst->next_state = state;
> +		}
> +		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
>  	}
>  }
>  
> @@ -1011,6 +1027,8 @@ static void __init pm_errata_configure(void)
>  		pm34xx_errata |= PM_RTA_ERRATUM_i608;
>  		/* Enable the l2 cache toggling in sleep logic */
>  		enable_omap3630_toggle_l2_on_restore();
> +		if (omap_rev() < OMAP3630_REV_ES1_2)
> +			pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
>  	}
>  }



More information about the linux-arm-kernel mailing list