summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-07-28 23:34:43 -0700
committerGary King <gking@nvidia.com>2010-07-30 15:36:40 -0700
commitfcecf3fdc2f7a68f9ee7dac84cf0db03907da53f (patch)
tree43e32cd2684ddb43634c08ae4320800709db8554
parentab138a11e2905f4474eee188648196a2f050cf53 (diff)
[ARM/tegra] RM: preserved core clocks in RM resume.
Preserved EMC, AVP, and system bus clocks during RM resume instead of setting them to maximum. This is necessary, since some PMUs set fixed boot core voltage value after LP0, which may be below nominal. DVFS will scale the above clocks after resume along with core voltage as necessary. Change-Id: I33ad90f39696eca569bd3bd76bb3cbf72ed18681 Reviewed-on: http://git-master/r/4569 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com> Reviewed-by: Narendra Damahe <ndamahe@nvidia.com> Tested-by: Narendra Damahe <ndamahe@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c53
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c5
2 files changed, 42 insertions, 16 deletions
diff --git a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c
index 63b546d5b64a..3a7a7bb7b921 100644
--- a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c
+++ b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c
@@ -690,6 +690,14 @@ Ap20Emc2xClockSourceFind(
break;
}
+ // In case, when boot EMC configuration does not match any entry in
+ // EMC sorted table switch to undivided PLLM0 first
+ if ((i != 0) && (s_Ap20EmcConfig.Index >= NVRM_AP20_DFS_EMC_FREQ_STEPS))
+ {
+ i = 0;
+ FinalStep = NV_FALSE;
+ }
+
// Target can be reached in one step, provided:
// - either current or target entry is PLLM0 OR
// - current and target entries have same source OR
@@ -1557,6 +1565,8 @@ void
NvRmPrivAp20FastClockConfig(NvRmDeviceHandle hRmDevice)
{
#if !NV_OAL
+ static NvBool resume = NV_FALSE;
+
NvU32 divc1, divm1, divp2;
NvRmFreqKHz SclkKHz, CpuKHz, PllP2KHz, PllM1KHz, PllC1KHz;
NvRmDfsSource VdeSource;
@@ -1567,21 +1577,26 @@ NvRmPrivAp20FastClockConfig(NvRmDeviceHandle hRmDevice)
// Set fastest EMC/MC configuration provided PLLM0 boot frequency matches
// one of the pre-defined configurations, i.e, it is the first entry in the
- // sorted table
+ // sorted table. Preserve warm boot EMC configuration during resume.
if ((s_Ap20EmcConfigSortedTable[0].Emc2xKHz == FreqKHz) &&
- (s_Ap20EmcConfig.Index != 0))
+ (s_Ap20EmcConfig.Index != 0) && (!resume))
{
Ap20EmcSwitchToUndividedPllM0(hRmDevice, s_Ap20EmcConfigSortedTable);
s_Ap20EmcConfig.Index = 0;
}
- // Set AVP/System Bus clock (now, with nominal core voltage it can be up
- // to SoC maximum). First determine settings for PLLP/PLLM/PLLC secondary
- // dividers to get maximum possible frequency on PLLP_OUT2, or PLLM_OUT1
- // or PLLC_OUT1 outputs.
- SclkKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Avp)->MaxKHz;
+ // Set AVP/System Bus clock to maximum during initialization (core voltage
+ // is already nominal). During resume core voltage maybe below nominal,
+ // hence, preserve system bus frequency set by the warm boot code, but
+ // re-arrange source selection, and dividers settings per RM convention.
+ if (!resume)
+ SclkKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Avp)->MaxKHz;
+ else
+ SclkKHz = NvRmPrivGetClockSourceFreq(NvRmClockSource_SystemBus);
NV_ASSERT(SclkKHz);
+ // First determine settings for PLLP/PLLM/PLLC secondary dividers to get
+ // closest target approximation from below
FreqKHz = NvRmPrivGetClockSourceFreq(NvRmClockSource_PllP0);
PllP2KHz = SclkKHz;
divp2 = NvRmPrivFindFreqMaxBelow(
@@ -1632,16 +1647,20 @@ NvRmPrivAp20FastClockConfig(NvRmDeviceHandle hRmDevice)
}
NvRmPrivBusClockInit(hRmDevice, SclkKHz);
- // Set VDE maximum clock (VDE is disabled after basic reset - need to
- // temporary enable it for configuration)
- FreqKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Vde)->MaxKHz;
- NvRmPowerModuleClockControl(hRmDevice, NvRmModuleID_Vde, 0, NV_TRUE);
- Ap20VdeClockSourceFind(hRmDevice, FreqKHz, FreqKHz, &VdeSource);
- Ap20VdeClockConfigure(hRmDevice, FreqKHz, &FreqKHz, &VdeSource);
- NvRmPowerModuleClockControl(hRmDevice, NvRmModuleID_Vde, 0, NV_FALSE);
+ // No need for VDE re-configurations during resume.
+ if (!resume)
+ {
+ // Set VDE maximum clock during initialization (VDE is disabled
+ // after basic reset - need to temporary enable it for configuration)
+ FreqKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Vde)->MaxKHz;
+ NvRmPowerModuleClockControl(hRmDevice, NvRmModuleID_Vde, 0, NV_TRUE);
+ Ap20VdeClockSourceFind(hRmDevice, FreqKHz, FreqKHz, &VdeSource);
+ Ap20VdeClockConfigure(hRmDevice, FreqKHz, &FreqKHz, &VdeSource);
+ NvRmPowerModuleClockControl(hRmDevice, NvRmModuleID_Vde, 0, NV_FALSE);
+ }
- // Set PLLX0 and CPU clock to SoC maximum (can be done now, when core
- // voltage is guaranteed to be nominal)
+ // Set PLLX0 and CPU clock to SoC maximum (cpu voltage is guaranteed to
+ // be nominal during initialization and resume as well)
CpuKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Cpu)->MaxKHz;
FreqKHz = NvRmPrivGetClockSourceFreq(NvRmClockSource_PllX0);
if (CpuKHz != FreqKHz)
@@ -1657,6 +1676,8 @@ NvRmPrivAp20FastClockConfig(NvRmDeviceHandle hRmDevice)
hRmDevice,
NvRmPrivGetClockSourceHandle(NvRmClockSource_PllP4)->pInfo.pDivider,
NVRM_AP20_FIXED_PLLP4_SETTING);
+
+ resume = NV_TRUE;
#endif
}
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 c8ca30d059cb..565030cb922d 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
@@ -1433,6 +1433,11 @@ static NvRmPmRequest DfsThread(NvRmDfs* pDfs)
{
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;