summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-10-06 00:02:41 -0700
committerVarun Colbert <vcolbert@nvidia.com>2010-10-20 15:44:13 -0700
commit24026696dcd728be545c07fcd3b4bd7e1483c553 (patch)
tree70eb96192b21234c8d131669de912a8d1c2e5c48
parentb5ec7cc7a010e333f63eac4e9ff605cb51361bfd (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>
-rw-r--r--arch/arm/mach-tegra/include/nvrm_power_private.h1
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c104
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h2
-rw-r--r--arch/arm/mach-tegra/suspend.c1
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
}