diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clock_config.c | 55 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h | 8 |
2 files changed, 61 insertions, 2 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 3a7a7bb7b921..740c5527c7d8 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 @@ -146,6 +146,8 @@ static const NvU32 s_EmcTimingRegAddrRev20[] = EMC_CFG_CLKTRIM_2_0, /* CFG_CLKTRIM_2 */ }; +#define EMC_CFG_DIG_DLL_INDEX (37) + // Sorted list of timing parameters for discrete set of EMC frequencies used // by DFS; entry 0 specifies timing parameters for PLLM0 output frequency. static NvRmAp20EmcTimingConfig @@ -318,10 +320,49 @@ static NvRmFreqKHz Ap20CpuToEmcRatio(NvRmFreqKHz Emc2xKHz) #endif } +static NvU32 Ap20EmcDigDllUpdate( + NvRmDeviceHandle hRmDevice, + NvRmFreqKHz PllM0KHz, + NvRmFreqKHz PllP0KHz, + NvRmFreqKHz Emc2xKHz, + NvU32 OdmDigDll) +{ + NvU32 mult, offset, d; + NvU32 dqsib = NvRmPrivGetEmcDqsibOffset(hRmDevice); + NV_ASSERT(PllP0KHz < PllM0KHz); + + /* Equation to determine digital dll override value based on dqsib + * characterization data: + * d = b - (m * (Emc2xMHz - PllP0MHz) / 2 / 100)), if Emc2xMHz > PllP0MHz + * d = b if Emc2xMHz <= PllP0Mhz + * Dqsib value packs 2 pairs of slope m/offset b settings. One pair ("high + * m, b") is applied only when undivided PLLM0 is used as a clock source. + * The other ("low m, b") is applied to all other clock sources. + */ + if (Emc2xKHz < PllM0KHz) + { + mult = NV_DRF_VAL(EMC, DIG_DLL_OVERRIDE, LOW_KHZ_MULT, dqsib); + offset = NV_DRF_VAL(EMC, DIG_DLL_OVERRIDE, LOW_KHZ_OFFS, dqsib); + } + else + { + mult = NV_DRF_VAL(EMC, DIG_DLL_OVERRIDE, HIGH_KHZ_MULT, dqsib); + offset = NV_DRF_VAL(EMC, DIG_DLL_OVERRIDE, HIGH_KHZ_OFFS, dqsib); + } + if (Emc2xKHz < PllP0KHz) + Emc2xKHz = PllP0KHz; + + d = ((Emc2xKHz - PllP0KHz) + 500) / 1000; + d = offset - (mult * d + 100) / 200; + d = NV_FLD_SET_DRF_NUM(EMC, CFG_DIG_DLL, CFG_DLL_OVERRIDE_VAL, + d, OdmDigDll); + return d; +} + static void Ap20EmcConfigInit(NvRmDeviceHandle hRmDevice) { NvRmFreqKHz Emc2xKHz, SourceKHz; - NvU32 i, j, k, Source, ConfigurationsCount, UndividedIndex; + NvU32 i, j, k, Source, ConfigurationsCount, UndividedIndex, dll; NvU32 Revision = 0; NvRmFreqKHz PllM0KHz = NvRmPrivGetClockSourceFreq(NvRmClockSource_PllM0); @@ -421,6 +462,13 @@ static void Ap20EmcConfigInit(NvRmDeviceHandle hRmDevice) UndividedIndex; s_Ap20EmcConfigSortedTable[i].Emc2xKHz = Emc2xKHz; + // Update digital dll settings + dll = pEmcConfigurations[j].EmcTimingParameters[ + EMC_CFG_DIG_DLL_INDEX]; + s_Ap20EmcConfigSortedTable[i].EmcDigDll = + Ap20EmcDigDllUpdate(hRmDevice, PllM0KHz, PllP0KHz, + Emc2xKHz, dll); + /* * The undivided table entry specifies parameters for * EMC2xKHz = SourceKHz; the EMC divisor field is set to @@ -492,7 +540,10 @@ Ap20EmcTimingSet( for (i = 0; i < s_Ap20EmcConfig.EmcTimingRegNum; i++) { - d = pEmcConfig->pOdmEmcConfig->EmcTimingParameters[i]; + if (i == EMC_CFG_DIG_DLL_INDEX) + d = pEmcConfig->EmcDigDll; + else + d = pEmcConfig->pOdmEmcConfig->EmcTimingParameters[i]; a = (((NvU32)(s_pEmcBaseReg)) + s_Ap20EmcConfig.pEmcTimingReg[i]); NV_WRITE32(a, d); } 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 f86b63d7bf1a..7fc8d645b85f 100644 --- a/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h +++ b/arch/arm/mach-tegra/nvrm/core/ap20/ap20rm_clocks.h @@ -101,8 +101,16 @@ typedef struct NvRmAp20EmcTimingConfigRec NvU32 Emc2xDivisor; NvU32 Emc2xUndividedIndex; NvRmFreqKHz CpuLimitKHz; + NvU32 EmcDigDll; } NvRmAp20EmcTimingConfig; +// Digital DLL override equation parameters within packed dqsib +// characterization data +#define EMC_DIG_DLL_OVERRIDE_0_LOW_KHZ_MULT_RANGE 7:0 +#define EMC_DIG_DLL_OVERRIDE_0_LOW_KHZ_OFFS_RANGE 15:8 +#define EMC_DIG_DLL_OVERRIDE_0_HIGH_KHZ_MULT_RANGE 23:16 +#define EMC_DIG_DLL_OVERRIDE_0_HIGH_KHZ_OFFS_RANGE 31:24 + /*****************************************************************************/ /** |