diff options
author | Alex Frid <afrid@nvidia.com> | 2010-10-06 00:02:41 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2010-10-20 15:44:13 -0700 |
commit | 24026696dcd728be545c07fcd3b4bd7e1483c553 (patch) | |
tree | 70eb96192b21234c8d131669de912a8d1c2e5c48 /arch | |
parent | b5ec7cc7a010e333f63eac4e9ff605cb51361bfd (diff) |
[ARM/tegra] suspend: Consolidated dvfs/TMON resume.
Moved dvfs resume into finish suspend ops call (from the 1st dvfs
thread invocation after suspend). This would guarantee dvfs re-start
in case when suspend is aborted by other driver.
Bug 742504
(cherry picked from commit 3a8bf2922f2f266381c887f3c05b7a755b40fae2)
Added thermal monitor (TMON) suspend/resume functionality.
Bug 698425
Bug 746601
(cherry picked from commit d6aa039689b31d311c836fe478c5943470d7203d)
Change-Id: I643f5bd9021989af569bd0ebba40af60738a6bdf
Reviewed-on: http://git-master/r/8719
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Tested-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'arch')
4 files changed, 59 insertions, 49 deletions
diff --git a/arch/arm/mach-tegra/include/nvrm_power_private.h b/arch/arm/mach-tegra/include/nvrm_power_private.h index 9ca3cee24e92..8f8a8375d63e 100644 --- a/arch/arm/mach-tegra/include/nvrm_power_private.h +++ b/arch/arm/mach-tegra/include/nvrm_power_private.h @@ -574,6 +574,7 @@ void NvRmPrivDfsResync(void); * */ void NvRmPrivDfsSuspend(NvOdmSocPowerState state); +void NvRmPrivDfsResume(void); /** * Restore clock sources after exit from low power state. diff --git a/arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c b/arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c index 98cee408f9d7..3107ad526908 100644 --- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c +++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c @@ -1385,7 +1385,6 @@ static NvRmPmRequest DfsThread(NvRmDfs* pDfs) { static NvRmDfsFrequencies LastKHz = {{0}}; - NvRmPowerEvent PowerEvent; NvRmDfsRunState DfsRunState; NvRmDfsFrequencies DfsKHz, HighKHz; NvBool LowCornerHit, LowCornerReport, NeedClockUpdate; @@ -1420,51 +1419,6 @@ static NvRmPmRequest DfsThread(NvRmDfs* pDfs) NvOsIntrMutexUnlock(pDfs->hIntrMutex); /* - * On exit from low power state re-initialize DFS h/w, samplers, and - * start monitors provided DFS is running. If DFS is stopped just get - * DFS h/w ready. - */ - NV_ASSERT_SUCCESS(NvRmPowerGetEvent( - pDfs->hRm, pDfs->PowerClientId, &PowerEvent)); - if (PowerEvent != NvRmPowerEvent_NoEvent) - { - // Full h/w re-initialization after LP0 - if (PowerEvent == NvRmPowerEvent_WakeLP0) - { - DfsHwDeinit(pDfs); - NV_ASSERT_SUCCESS(DfsHwInit(pDfs)); - - // Some PMUs do not restore core voltage after LP0 - NvRmPmuGetVoltage(pDfs->hRm, - pDfs->VoltageScaler.CoreRailAddress, - &pDfs->VoltageScaler.CurrentCoreMv); - } - // Re-initialize samplers if DVFS was running, but stopped on - // entry to LPx; keep sampling history, if DVFS was not stopped; - // restart monitors in either case - NvRmPrivLockSharedPll(); - if (pDfs->DfsLPxSavedState > NvRmDfsRunState_Stopped) - { - DfsClockFreqGet(pDfs->hRm, &DfsKHz); - - NvOsIntrMutexLock(pDfs->hIntrMutex); - if (pDfs->DfsRunState <= NvRmDfsRunState_Stopped) - { - pDfs->DfsRunState = pDfs->DfsLPxSavedState; - DfsSamplersInit(&DfsKHz, pDfs); - } - NV_ASSERT(pDfs->DfsRunState == pDfs->DfsLPxSavedState); - pDfs->CurrentKHz = DfsKHz; - DfsStartMonitors( - pDfs, &DfsKHz, pDfs->SamplingWindow.MinIntervalMs); - NvOsIntrMutexUnlock(pDfs->hIntrMutex); - } - NvRmPrivDvsRun(); // enable v-scaling even if DFS is stopped - NvRmPrivUnlockSharedPll(); - return PmRequest; - } - - /* * Advance busy hint state machine if DFS thread has been signaled by * synchronous busy hint. */ @@ -1948,7 +1902,7 @@ NvError NvRmPrivDfsInit(NvRmDeviceHandle hRmDeviceHandle) goto failed; } // Register DFS as power client and obtain client id - error = NvRmPowerRegister(hRmDeviceHandle, pDfs->hSemaphore, &pDfs->PowerClientId); + error = NvRmPowerRegister(hRmDeviceHandle, NULL, &pDfs->PowerClientId); if (error != NvSuccess) { goto failed; @@ -2602,6 +2556,55 @@ static void NvRmPrivDvsRun(void) pDvs->StopFlag = NV_FALSE; } +void NvRmPrivDfsResume(void) +{ + NvRmDfs* pDfs = &s_Dfs; + NvRmPowerEvent PowerEvent; + NvRmDfsFrequencies DfsKHz; + + /* + * On exit from low power state re-initialize DFS h/w, samplers, and + * start monitors provided DFS is running. If DFS is stopped just get + * DFS h/w ready. + */ + NV_ASSERT_SUCCESS(NvRmPowerGetEvent( + pDfs->hRm, pDfs->PowerClientId, &PowerEvent)); + + // Full h/w re-initialization after LP0 + if (PowerEvent == NvRmPowerEvent_WakeLP0) + { + DfsHwDeinit(pDfs); + NV_ASSERT_SUCCESS(DfsHwInit(pDfs)); + + // Some PMUs do not restore core voltage after LP0 + NvRmPmuGetVoltage(pDfs->hRm, + pDfs->VoltageScaler.CoreRailAddress, + &pDfs->VoltageScaler.CurrentCoreMv); + } + + // After LPx or aborted suspend re-initialize samplers if DFS was + // running + NvRmPrivLockSharedPll(); + DfsClockFreqGet(pDfs->hRm, &DfsKHz); + + NvOsIntrMutexLock(pDfs->hIntrMutex); + pDfs->DfsRunState = pDfs->DfsLPxSavedState; + pDfs->CurrentKHz = DfsKHz; + if (pDfs->DfsLPxSavedState > NvRmDfsRunState_Stopped) + { + DfsSamplersInit(&DfsKHz, pDfs); + DfsStartMonitors(pDfs, &DfsKHz, pDfs->SamplingWindow.MinIntervalMs); + } + NvRmPrivDvsRun(); // enable v-scaling even if DFS is stopped + NvOsIntrMutexUnlock(pDfs->hIntrMutex); + + // Resume thermal monitoring + if (pDfs->ThermalThrottler.hOdmTcore) + NvOdmTmonResume(pDfs->ThermalThrottler.hOdmTcore); + + NvRmPrivUnlockSharedPll(); +} + void NvRmPrivDfsSuspend(NvOdmSocPowerState state) { NvRmDfs* pDfs = &s_Dfs; @@ -2637,7 +2640,7 @@ void NvRmPrivDfsSuspend(NvOdmSocPowerState state) NvRmPrivDvsStopAtNominal(); pDfs->VoltageScaler.StopFlag = NV_TRUE; } - else if (state == NvOdmSocPowerState_Suspend) + else// if (state == NvOdmSocPowerState_Suspend): any other treat as LP1 { // On entry to suspend (LP1): set target frequencies for all DFS // clock domains, stop DFS monitors, and then configure clocks and @@ -2688,6 +2691,11 @@ void NvRmPrivDfsSuspend(NvOdmSocPowerState state) pDfs->VoltageScaler.StopFlag = NV_TRUE; } + + // Suspend thermal monitoring + if (pDfs->ThermalThrottler.hOdmTcore) + NvOdmTmonSuspend(pDfs->ThermalThrottler.hOdmTcore); + NvRmPrivUnlockSharedPll(); } diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h index e0e930e79fe7..55dbdcb4f33e 100644 --- a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h @@ -44,7 +44,7 @@ extern "C" #define ADT7461_ODM_EXTENDED_RANGE (1) // ODM policy: enable=1 (disable=0) ADT7461 standby mode -#define ADT7461_ODM_STANDBY_ENABLED (0) +#define ADT7461_ODM_STANDBY_ENABLED (1) // ODM policy: protect=1 (not=0) thermal limits from being overwritten by API #define ADT7461_ODM_LOCAL_INTR_LIMITS_PROTECTED (1) diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c index b38833211302..dd623bdb69dc 100644 --- a/arch/arm/mach-tegra/suspend.c +++ b/arch/arm/mach-tegra/suspend.c @@ -522,6 +522,7 @@ static void tegra_suspend_finish(void) NvOdmSocPowerState state = NvRmPowerLowestStateGet(); NvRmPrivPmuLPxStateConfig(s_hRmGlobal, state, NV_FALSE); + NvRmPrivDfsResume(); #endif } |