summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-03-01 14:51:46 -0800
committerGary King <gking@nvidia.com>2010-03-01 18:36:56 -0800
commited5c62e6e22b6dd379e2519cc5befbda86784e75 (patch)
tree8a1dbdd60c228907d9554fdfd1cc27aae5aedc06 /arch/arm
parent5db8fe51ef51627b751fe2c71c6b0a8ab2f49df3 (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')
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c70
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h13
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_power_dfs.h3
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_power_dfs.c3
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;