diff options
author | Cedric Vamour <c-vamour@ti.com> | 2012-03-27 14:39:44 +0200 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 12:58:30 +0200 |
commit | b3acd0cb053a25e55b62c42685cc3ecfa5c3359b (patch) | |
tree | fb8499f797f1f2b730f938ed7722a1ac7e0592d1 | |
parent | 23b1bbc6f40bb187875fce4bc8597f2b6fee98bf (diff) | |
download | kernel_samsung_tuna-b3acd0cb053a25e55b62c42685cc3ecfa5c3359b.zip kernel_samsung_tuna-b3acd0cb053a25e55b62c42685cc3ecfa5c3359b.tar.gz kernel_samsung_tuna-b3acd0cb053a25e55b62c42685cc3ecfa5c3359b.tar.bz2 |
OMAP4: PM: IVA AUTO RET relaxed workaround in idle path
AUTO RET for IVA VDD Cannot be permanently enabled during OFF mode due to
potential race between IVA VDD entering RET and start of Device OFF mode.
It is mandatory to have AUTO RET for IVA VDD exlusive with Devide OFF mode.
In order to avoid lockup in OFF mode sequence, system must ensure IVA
voltage domain transitions straight from stable ON to OFF.
In addition, management of IVA VDD SmartReflex sensor at exit of idle path
may introduce a misalignment between IVA Voltage Controller state and IVA
PRCM voltage FSM based on following identified scenario:
IVA Voltage Controller is woken-up due to SmartReflex management while
IVA PRCM voltage FSM stays in RET in absence of any IVA module wake-up event
(which is not systematic in idle path as opposed to MPU and CORE VDDs being
necessarily woken up with MPU and CORE PDs).
WA involves:
Ensure stable ON-OFF transition for IVA voltage domain during OFF mode sequence.
Ensure VCON and PRCM FSM are kept aligned due to IVA SR handling in idle path.
1) AUTO RET for IVA VDD is enabled entering in idle path, disabled exiting idle
path and IVA VDD is always woken-up with a SW dummy wakeup.
2) OFF mode is enabled only in Suspend path.
3) AUTO RET for IVA VDD remains disabled in Suspend path (before OFF mode).
REVISIT: Update the patch once proper Errata is out for 44xx.
Benefits:
1) This patch ensures it is possible to gate SYS_CLK during OS-Idle LCD OFF
when all domains are idled, saving up to 2mA at VBAT from external clock buffer.
2) IVA voltage domain is now allowed to scale to Retention during idle which
reduces power consumption on all types of use case allowing extensive use of
idle path (e.g.: Home screen, Page reading). Effects are especially visible
if system uses Smart-Reflex Class 1.5 compared to Class 3 considering the
increased difference of voltage from converged Voltage SR vs Retention voltage.
TODO: quantify the actual savings from IVA-RET with further measurements.
Change-Id: I01f0431f7556f0baf0b5b6b42092cd11c2442f00
Signed-off-by: Cedric Vamour <c-vamour@ti.com>
-rwxr-xr-x | arch/arm/mach-omap2/pm44xx.c | 132 |
1 files changed, 123 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 6a008e3..065a94f 100755 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -82,9 +82,20 @@ static struct clockdomain *tesla_clkdm; static struct powerdomain *tesla_pwrdm; static struct clockdomain *emif_clkdm, *mpuss_clkdm; +static struct clockdomain *abe_clkdm; -/* Yet un-named erratum which requires AUTORET to be disabled for IVA PD */ +/* Yet un-named erratum which requires AUTORET to be disabled for IVA PD +* +* NOTE: This erratum is disabled and replaced with updated work-around relaxing +* constraint of always holding IVA AUTO RET disabled (now only before OFF), +* which in turn was preventing IVA VDD from reaching RET and SYS_CLK from +* being automatically gated in idle path. This previous work-around code is +* kept and maintained for reference until Errata documentation is updated. +* TODO: Once final Errata documentation is available, remove reference to this +* previous IVA AUTO RET erratum. +*/ #define OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX BIT(1) + /* * HSI - OMAP4430-2.2BUG00055: * HSI: DSP Swakeup generated is the same than MPU Swakeup. @@ -145,7 +156,42 @@ static struct clockdomain *emif_clkdm, *mpuss_clkdm; **/ #define OMAP4_PM_ERRATUM_IO_WAKEUP_CLOCK_NOT_RECYCLED_i612 BIT(7) -u8 pm44xx_errata; +/* + * AUTO RET for IVA VDD Cannot be permanently enabled during OFF mode due to + * potential race between IVA VDD entering RET and start of Device OFF mode. + * + * It is mandatory to have AUTO RET for IVA VDD exlusive with Devide OFF mode. + * In order to avoid lockup in OFF mode sequence, system must ensure IVA + * voltage domain transitions straight from stable ON to OFF. + * + * In addition, management of IVA VDD SmartReflex sensor at exit of idle path + * may introduce a misalignment between IVA Voltage Controller state and IVA + * PRCM voltage FSM based on following identified scenario: + * + * IVA Voltage Controller is woken-up due to SmartReflex management while + * IVA PRCM voltage FSM stays in RET in absence of any IVA module wake-up event + * (which is not systematic in idle path as opposed to MPU and CORE VDDs being + * necessarily woken up with MPU and CORE PDs). + * + * NOTE: This updated work-around relaxes constraint of always holding + * IVA AUTO RET disabled (now only before OFF), which in turn was preventing + * IVA VDD from reaching RET and SYS_CLK from being automatically gated in + * idle path. Ensure previous work-around code is kept and maintained for + * reference until Errata documentation is updated. + * TODO: Once this is available, update with final iXXX Errata number. + * + * WA involves: + * Ensure stable ON-OFF transition for IVA VDD during OFF mode sequence. + * Ensure VCON and PRCM FSM are synced despite IVA SR handling in idle path. + * 1) AUTO RET for IVA VDD is enabled entering in idle path, disabled exiting + * idle path and IVA VDD is always woken-up with a SW dummy wakeup. + * 2) OFF mode is enabled only in Suspend path. + * 3) AUTO RET for IVA VDD remains disabled in Suspend path (before OFF mode). + */ +#define OMAP4_PM_ERRATUM_IVA_AUTO_RET_IDLE_iXXX BIT(8) +static int iva_toggle_wa_applied; + +u16 pm44xx_errata; #define is_pm44xx_erratum(erratum) (pm44xx_errata & OMAP4_PM_ERRATUM_##erratum) /* HACK: check CAWAKE wakeup event */ @@ -303,9 +349,29 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) goto abort_device_off; omap_vc_set_auto_trans(core_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); - if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) { - omap_vc_set_auto_trans(iva_voltdm, - OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); + + /* + * Do not enable IVA AUTO-RET if device targets OFF mode. + * In such case, purpose of IVA AUTO-RET WA is to ensure + * IVA domain goes straight from stable Voltage ON to OFF. + */ + if (is_pm44xx_erratum(IVA_AUTO_RET_IDLE_iXXX)) { + if (!omap4_device_next_state_off()) + omap_vc_set_auto_trans(iva_voltdm, + OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); + /* Normal path without IVA AUTO RET IDLE work-around applied */ + } else { + /* + * Note: The previous erratum is deactivated and replaced + * with updated work-around in idle path which relaxes + * constraint of always holding IVA AUTO RET disabled + * (now only before OFF). Code is kept and maintained for + * reference until Errata is updated. + */ + if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) { + omap_vc_set_auto_trans(iva_voltdm, + OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); + } } omap_temp_sensor_prepare_idle(); @@ -320,6 +386,12 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) omap4_pm_suspend_save_regs(); if (omap4_device_next_state_off()) { + /* Proceed with OFF mode sequence only if WA is applied */ + if (is_pm44xx_erratum(IVA_AUTO_RET_IDLE_iXXX)) { + if (!iva_toggle_wa_applied) + goto abort_device_off; + } + /* Save the device context to SAR RAM */ if (omap4_sar_save()) goto abort_device_off; @@ -356,9 +428,47 @@ abort_device_off: /* See note above */ omap_vc_set_auto_trans(core_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE); - if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) { - omap_vc_set_auto_trans(iva_voltdm, + + if (is_pm44xx_erratum(IVA_AUTO_RET_IDLE_iXXX)) { + if (omap_vc_set_auto_trans(iva_voltdm, + OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE)){ + pr_err("%s: Failed to disable autoret for %s\n", + __func__, iva_voltdm->name); + iva_toggle_wa_applied = 0; + /* + * Ensure PRCM IVA Voltage FSM is ON upon exit of idle. + * Upon successful IVA AUTO-RET disabling, trigger a + * Dummy SW Wakup on IVA domain. Later on, upon enabling + * of IVA Smart-Reflex, IVA Voltage Controller state will + * be ON as well. Both FSMs would now be aligned and safe + * during active and for further attempts to Device OFF + * mode for which IVA would go straight from ON to OFF. + */ + } else { + /* Configures ABE clockdomain in SW_WKUP */ + if (clkdm_wakeup(abe_clkdm)) { + pr_err("%s: Failed to force wakeup of %s\n", + __func__, abe_clkdm->name); + iva_toggle_wa_applied = 0; + /* Configures ABE clockdomain back to HW_AUTO */ + } else { + clkdm_allow_idle(abe_clkdm); + iva_toggle_wa_applied = 1; + } + } + /* Normal path without IVA AUTO RET IDLE work-around applied */ + } else { + /* + * Note: The previous erratum is deactivated and replaced + * with updated work-around in idle path which relaxes + * constraint of always holding IVA AUTO RET disabled + * (now only before OFF). Code is kept and maintained for + * reference until Errata is updated. + */ + if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) { + omap_vc_set_auto_trans(iva_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE); + } } omap_temp_sensor_resume_idle(); @@ -1354,10 +1464,12 @@ static void __init omap4_pm_setup_errata(void) * all OMAP4 silica */ if (cpu_is_omap44xx()) - pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX | + pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_IDLE_iXXX | OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX | OMAP4_PM_ERRATUM_LPDDR_CLK_IO_i736; + iva_toggle_wa_applied = 0; + if (cpu_is_omap443x()) { /* Dynamic Dependency errata for all silicon !=443x */ pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688; @@ -1444,6 +1556,7 @@ static int __init omap4_pm_init(void) */ mpuss_clkdm = clkdm_lookup("mpuss_clkdm"); emif_clkdm = clkdm_lookup("l3_emif_clkdm"); + abe_clkdm = clkdm_lookup("abe_clkdm"); l3_1_clkdm = clkdm_lookup("l3_1_clkdm"); l3_2_clkdm = clkdm_lookup("l3_2_clkdm"); ducati_clkdm = clkdm_lookup("ducati_clkdm"); @@ -1451,7 +1564,8 @@ static int __init omap4_pm_init(void) l4_cfg = clkdm_lookup("l4_cfg_clkdm"); l4wkup = clkdm_lookup("l4_wkup_clkdm"); if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || (!l4wkup) || - (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per) || (!l4_cfg)) + (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per) || (!l4_cfg) || + (!abe_clkdm)) goto err2; /* if we cannot ever enable static dependency. */ |