diff options
author | Alex Frid <afrid@nvidia.com> | 2010-03-01 14:51:46 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-03-01 18:36:56 -0800 |
commit | ed5c62e6e22b6dd379e2519cc5befbda86784e75 (patch) | |
tree | 8a1dbdd60c228907d9554fdfd1cc27aae5aedc06 /arch/arm | |
parent | 5db8fe51ef51627b751fe2c71c6b0a8ab2f49df3 (diff) |
tegra RM: Increased LP1 entry/exit frequencies.
Increased LP1 entry/exit frequencies to match core voltage target 1.0V
(instead of pushing clocks into low corner). This would allow to reduce
entry/exit time without compromising LP1 power.
Change-Id: I30d6db88545a158a697db0c2b4ff705f55ce26f0
Reviewed-on: http://git-master/r/722
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm')
4 files changed, 88 insertions, 1 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 8b57925ce6c6..5883bffdaea7 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 @@ -1481,6 +1481,76 @@ NvRmPrivAp20DfsClockFreqGet( (s_Ap20EmcConfig.pEmc2xState->actual_freq >> 1); } +void +NvRmPrivAp20DfsSuspendFreqGet( + NvRmDeviceHandle hRmDevice, + NvRmMilliVolts TargetMv, + NvRmDfsFrequencies* pDfsKHz) +{ + NvU32 i; + NvRmMilliVolts v; + NvRmFreqKHz Fa, Fb, f; + NvRmDfsSource DfsClockSource; + NvRmFreqKHz CpuMaxKHz = + NvRmPrivGetSocClockLimits(NvRmModuleID_Cpu)->MaxKHz; + NvRmFreqKHz SysMaxKHz = + NvRmPrivGetSocClockLimits(NvRmPrivModuleID_System)->MaxKHz; + NV_ASSERT(hRmDevice && pDfsKHz); + + // Binary search for maximum System/Avp frequency, with source that + // can be used at target voltage or below + Fb = SysMaxKHz; + Fa = NvRmPrivGetClockSourceFreq(NvRmClockSource_ClkM); + NV_ASSERT(Fa <= Fb); + while ((Fb - Fa) > 1000) // 1MHz resolution + { + f = (Fa + Fb) >> 1; + Ap20SystemClockSourceFind(hRmDevice, SysMaxKHz, f, &DfsClockSource); + v = DfsClockSource.MinMv; + if (v <= TargetMv) + Fa = f; + else + Fb = f; + } + pDfsKHz->Domains[NvRmDfsClockId_System] = Fa; + pDfsKHz->Domains[NvRmDfsClockId_Avp] = Fa; + pDfsKHz->Domains[NvRmDfsClockId_Ahb] = Fa; + pDfsKHz->Domains[NvRmDfsClockId_Apb] = Fa; + // On AP20 Vde clock has its own voltage scale; however, it is disabled + // on suspend entry; hence, the setting below is "don't care" + pDfsKHz->Domains[NvRmDfsClockId_Vpipe] = Fa; + + // If PLLM0 entry in EMC scaling table is valid, search the table for + // the entry below and closest to the traget voltage. Otherwise, there + // is no EMC scaling - just return current EMC frequency. + pDfsKHz->Domains[NvRmDfsClockId_Emc] = + (s_Ap20EmcConfig.pEmc2xState->actual_freq >> 1); + if (s_Ap20EmcConfigSortedTable[0].Emc2xKHz != 0) + { + for (i = 0; i < (NVRM_AP20_DFS_EMC_FREQ_STEPS - 1); i++) + { + if ((s_Ap20EmcConfigSortedTable[i+1].Emc2xKHz == 0) || + (s_Ap20EmcConfigSortedTable[i].pOdmEmcConfig->EmcCoreVoltageMv + <= TargetMv)) + break; // exit if found entry or next entry is invalid + } + pDfsKHz->Domains[NvRmDfsClockId_Emc] = + (s_Ap20EmcConfigSortedTable[i].Emc2xKHz >> 1); + f = s_Ap20EmcConfigSortedTable[i].CpuLimitKHz; + CpuMaxKHz = NV_MIN(CpuMaxKHz, f); // throttle CPU if necessary + } + + // CPU voltage is turned Off in suspend. Use CPU frequency derived from + // PLLP as LP1 resume start-up clock + f = s_Ap20PllPCpuClockPolicy[s_Ap20PllPCpuClockPolicyEntries-1].SourceKHz; + pDfsKHz->Domains[NvRmDfsClockId_Cpu] = NV_MIN(CpuMaxKHz, f); + + NvOsDebugPrintf("LP1 entry/exit kHz: Cpu = %6d, Emc = %6d, Sys = %6d\n", + pDfsKHz->Domains[NvRmDfsClockId_Cpu], + pDfsKHz->Domains[NvRmDfsClockId_Emc], + pDfsKHz->Domains[NvRmDfsClockId_System]); +} + /*****************************************************************************/ /*****************************************************************************/ diff --git a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h index 389778a5334a..0179bccdb90b 100644 --- a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h +++ b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h @@ -254,6 +254,19 @@ NvRmPrivAp20DfsClockConfigure( const NvRmDfsFrequencies* pMaxKHz, NvRmDfsFrequencies* pDfsKHz); +/** + * Gets DFS domains frequencies to be set for suspend (LP1) entry/exit. + * + * @param hRmDevice The RM device handle. + * @param TargetMv Targeted suspend core voltage in mV. + * @param pDfsKHz Pointer to a structure filled in by this function with + * output clock frequencies. + */ +void +NvRmPrivAp20DfsSuspendFreqGet( + NvRmDeviceHandle hRmDevice, + NvRmMilliVolts TargetMv, + NvRmDfsFrequencies* pDfsKHz); /** * Configures the sdio tap delay diff --git a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_power_dfs.h b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_power_dfs.h index c4424599a93c..13ead9968fed 100644 --- a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_power_dfs.h +++ b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_power_dfs.h @@ -227,6 +227,9 @@ extern "C" #define NVRM_AP20_LOW_CORE_MV (950) #define NVRM_AP20_LOW_CPU_MV (750) +/// Core voltage in suspend +#define NVRM_AP20_SUSPEND_CORE_MV (1000) + /*****************************************************************************/ /** 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 fa1f110f236c..c19998409856 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 @@ -2572,7 +2572,8 @@ void NvRmPrivDfsSuspend(NvOdmSocPowerState state) NvRmPrivAp15DfsVscaleFreqGet( pDfs->hRm, NVRM_AP15_SUSPEND_CORE_MV, &pDfs->SuspendKHz); else if (pDfs->hRm->ChipId.Id == 0x20) - pDfs->SuspendKHz = pDfs->LowCornerKHz; // TODO: AP20 suspend corner + NvRmPrivAp20DfsSuspendFreqGet( + pDfs->hRm, NVRM_AP20_SUSPEND_CORE_MV, &pDfs->SuspendKHz); else pDfs->SuspendKHz = pDfs->LowCornerKHz; // Low corner by default pDfs->SuspendKHz.Domains[0] = NvRmFreqMaximum; |