7 * Northbridge DCT support for Orochi
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/NB/OR)
12 * @e \$Revision: 60556 $ @e \$Date: 2011-10-17 20:19:58 -0600 (Mon, 17 Oct 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * ***************************************************************************
48 *----------------------------------------------------------------------------
51 *----------------------------------------------------------------------------
64 #include "OptionMemory.h" // need def for MEM_FEAT_BLOCK_NB
67 #include "cpuFamRegisters.h"
68 #include "GeneralServices.h"
69 #include "cpuFamilyTranslation.h"
70 #include "cpuCommonF15Utilities.h"
71 #include "F15PackageType.h"
77 #define FILECODE PROC_MEM_NB_OR_MNDCTOR_FILECODE
79 /*----------------------------------------------------------------------------
80 * DEFINITIONS AND MACROS
82 *----------------------------------------------------------------------------
85 #define MAX_RD_DQS_DLY 0x1F
87 /*----------------------------------------------------------------------------
88 * TYPEDEFS AND STRUCTURES
90 *----------------------------------------------------------------------------
93 /*----------------------------------------------------------------------------
94 * PROTOTYPES OF LOCAL FUNCTIONS
96 *----------------------------------------------------------------------------
100 MemNTotalSyncComponentsOr (
101 IN OUT MEM_NB_BLOCK *NBPtr
104 /*----------------------------------------------------------------------------
107 *----------------------------------------------------------------------------
110 extern BUILD_OPT_CFG UserOptions;
112 /* -----------------------------------------------------------------------------*/
116 * This function programs the memory controller with configuration parameters
119 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
121 * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
122 * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
123 * @return NBPtr->MCTPtr->ErrCode - Contains detailed AGESA_STATUS value
128 IN OUT MEM_NB_BLOCK *NBPtr
135 MEM_PARAMETER_STRUCT *RefPtr;
136 MEM_PS_BLOCK * PsPtr;
137 BOOLEAN ExtraAddrBits;
141 RefPtr = NBPtr->RefPtr;
142 MCTPtr = NBPtr->MCTPtr;
143 DCTPtr = NBPtr->DCTPtr;
144 PsPtr = NBPtr->PsPtr;
146 ExtraAddrBits = FALSE;
149 ROOD = DEFAULT_RD_ODT_OR;
151 // Check for Extra Address bit requirement for LRDIMMs
153 if (MCTPtr->Status[SbLrdimms]) {
154 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
155 if (PsPtr->LrdimmRowAddrBits[i] > 16) {
156 ExtraAddrBits = TRUE;
158 if (NBPtr->ChannelPtr->LrDimmRankMult[i] > 1) {
164 NumDimmslots = GetMaxDimmsPerChannel (RefPtr->PlatformMemoryConfiguration,
166 NBPtr->ChannelPtr->ChannelID);
168 //======================================================================
169 // Build Dram Config Lo Register Value
170 //======================================================================
172 // Disable Parity Prior to Dram init
174 MemNSetBitFieldNb (NBPtr, BFParEn, 0);
176 // LRDIMMS Extended Parity
178 MemNSetBitFieldNb (NBPtr, BFExtendedParityEn, 0);
182 MemNSetBitFieldNb (NBPtr, BFX4Dimm, NBPtr->ChannelPtr->DimmNibbleAccess & 0xF);
186 if (!(MCTPtr->Status[SbRegistered] || MCTPtr->Status[SbLrdimms])) {
187 MemNSetBitFieldNb (NBPtr, BFUnBuffDimm, 1);
192 if (MCTPtr->Status[SbEccDimms]) {
193 MemNSetBitFieldNb (NBPtr, BFDimmEccEn, 1);
196 // PendRefPayback, StatgRefEn, TStag[0:4]
198 MemNSetBitFieldNb (NBPtr, BFPendRefPaybackS3En, 1);
199 MemNSetBitFieldNb (NBPtr, BFStagRefEn, 1);
200 for (i = 0; i < 4; i++) {
201 MemNSetBitFieldNb (NBPtr, BFTstag0 + i, 0x14);
204 //======================================================================
205 // Build Dram Config Hi Register Value
206 //======================================================================
211 MemNSetBitFieldNb (NBPtr, BFMemClkFreq, MemNGetMemClkFreqIdUnb (NBPtr, DCTPtr->Timings.Speed));
213 // FourRankRDimm0 , FourRankRDimm1 ( Reset Values are 0)
215 //======================================================================
216 // Build Dram MRS Register Value (Not used for MRS command)
217 //======================================================================
219 // PchgPDModeSel - This is done here so that the value can be used by
222 if (NBPtr->IsSupported[PchgPDMode]) {
223 MemNSetBitFieldNb (NBPtr, BFPchgPDModeSel, 1);
225 MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 0);
227 //======================================================================
228 // Build Dram Config Misc Register Value
229 //======================================================================
232 // LRDIMMs CSMux45 and CSMux67
234 if (MCTPtr->Status[SbLrdimms]) {
235 if (NumDimmslots == 3) {
236 MemNSetBitFieldNb (NBPtr, BFCSMux45, 0);
237 MemNSetBitFieldNb (NBPtr, BFCSMux67, ExtraAddrBits ? 1 : 0);
238 } else if (NumDimmslots <= 2) {
239 MemNSetBitFieldNb (NBPtr, BFCSMux45, (PsPtr->LrdimmRowAddrBits[0] > 16) ? 1 : 0);
240 MemNSetBitFieldNb (NBPtr, BFCSMux67, (PsPtr->LrdimmRowAddrBits[1] > 16) ? 1 : 0);
246 MemNSetBitFieldNb (NBPtr, BFLrDimmMrsCtrl, RankMultEn ? 1 : 0);
250 MemNSetBitFieldNb (NBPtr, BFLrDimmEnhRefEn, RankMultEn ? 1 : 0);
254 MemNSetBitFieldNb (NBPtr, BFSubMemclkRegDly, (MCTPtr->Status[SbRegistered] || MCTPtr->Status[SbLrdimms])? 1 : 0);
255 //======================================================================
257 //======================================================================
262 MemNSetBitFieldNb (NBPtr, BFTrwtWB, 0x17);
263 MemNSetBitFieldNb (NBPtr, BFTrwtTO, 0x16);
264 MemNSetBitFieldNb (NBPtr, BFTwrrd, 0xB );
266 MemNSetBitFieldNb (NBPtr, BFTrdrdSdSc, 0xB);
267 MemNSetBitFieldNb (NBPtr, BFTrdrdSdDc, 0xB);
268 MemNSetBitFieldNb (NBPtr, BFTrdrdDd, 0xB);
270 MemNSetBitFieldNb (NBPtr, BFTwrwrSdSc, 0xB);
271 MemNSetBitFieldNb (NBPtr, BFTwrwrSdDc, 0xB);
272 MemNSetBitFieldNb (NBPtr, BFTwrwrDd, 0xB);
274 if (NBPtr->MCTPtr->Status[SbLrdimms]) {
275 ROOD = ROOD + (UINT8) (MemNCalBufDatDelaySkewOr (NBPtr, GetBufDatDlySkew));
277 MemNSetBitFieldNb (NBPtr, BFWrOdtOnDuration, DEFAULT_WR_ODT_OR);
278 MemNSetBitFieldNb (NBPtr, BFRdOdtOnDuration, ROOD);
279 MemNSetBitFieldNb (NBPtr, BFWrOdtTrnOnDly, 0);
281 MemNSetBitFieldNb (NBPtr, BFTmrd, (NBPtr->MCTPtr->Status[SbLrdimms] ? 6 : 4));
283 MemNSetBitFieldNb (NBPtr, BFFlushWrOnS3StpGnt, 1);
284 MemNSetBitFieldNb (NBPtr, BFFastSelfRefEntryDis, 0);
286 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
289 /* -----------------------------------------------------------------------------*/
293 * This function caps speed based on battery life check.
295 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
298 MemNCapSpeedBatteryLifeOr (
299 IN OUT MEM_NB_BLOCK *NBPtr
302 CONST UINT16 SupportedFreq[] = {
311 UINT32 FreqNumeratorInMHz;
318 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
320 FamilySpecificServices = NULL;
321 GetCpuServicesOfSocket (NBPtr->MCTPtr->SocketId, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &(NBPtr->MemPtr->StdHeader));
323 // Find the lowest supported NB Pstate
325 for (NbPs = 3; NbPs >= 0; NbPs--) {
326 if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
327 NBPtr->MemPtr->PlatFormConfig,
333 &(NBPtr->MemPtr->StdHeader))) {
334 NBFreq = FreqNumeratorInMHz / FreqDivisor;
341 // Pick Max MEMCLK that is less than or equal to (NCLK / 2)
342 DdrFreq = DDR800_FREQUENCY;
343 for (j = 0; j < GET_SIZE_OF (SupportedFreq); j++) {
344 if (NBFreq >= ((UINT32) 2 * SupportedFreq[j])) {
345 DdrFreq = SupportedFreq[j];
350 // Cap MemClk frequency to lowest NCLK frequency
351 if (NBPtr->DCTPtr->Timings.TargetSpeed > DdrFreq) {
352 NBPtr->DCTPtr->Timings.TargetSpeed = DdrFreq;
355 // Initialize NbPsCtlReg
356 NBPtr->NbPsCtlReg = 0;
359 /* -----------------------------------------------------------------------------*/
363 * This function retrieves the Max latency parameters
365 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
367 * @param[in] *MinDlyPtr - Pointer to variable to store the Minimum Delay value
368 * @param[in] *MaxDlyPtr - Pointer to variable to store the Maximum Delay value
369 * @param[in] *DlyBiasPtr - Pointer to variable to store Delay Bias value
370 * @param[in] MaxRcvEnDly - Maximum receiver enable delay value
374 MemNGetMaxLatParamsOr (
375 IN OUT MEM_NB_BLOCK *NBPtr,
376 IN UINT16 MaxRcvEnDly,
377 IN OUT UINT16 *MinDlyPtr,
378 IN OUT UINT16 *MaxDlyPtr,
379 IN OUT UINT16 *DlyBiasPtr
390 // Get all sync components BKDG steps 3,4,6,7
391 P = MemNTotalSyncComponentsOr (NBPtr);
393 // 8. P = P + CEIL(MAX(D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] +
394 // D18F2x9C_x0000_0[3:0]0[7:5]_dct[1:0][RdDqsTime] PCLKs))
395 P = P + (MaxRcvEnDly + 31) / 32;
397 // 10. T = T + 800 ps
400 // 11. N = (P/(MemClkFreq * 2) + T) * NclkFreq; Convert from PCLKs plus time to NCLKs.
401 MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
402 N = ((((P * MemClkPeriod + 1) / 2) + T) * NBPtr->NBClkFreq + 999999) / 1000000;
404 // 13. D18F2x210_dct[1:0]_nbp[3:0][MaxRdLatency] = CEIL(N) - 1
407 // Calculate a starting MaxRdLatency delay value with steps 5, 9, and 12 excluded
408 *MinDlyPtr = (UINT16) N;
412 // Left edge of MaxRdLat will be added with 1 NCLK and 3 PCLK
415 N += (((P * MemClkPeriod + 1) / 2) * NBPtr->NBClkFreq + 999999) / 1000000;
416 *DlyBiasPtr = (UINT16) N;
419 /* -----------------------------------------------------------------------------*/
423 * This function sets the maximum round-trip latency in the system from the processor to the DRAM
427 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
428 * @param[in] MaxRcvEnDly - Maximum receiver enable delay value
433 MemNSetMaxLatencyOr (
434 IN OUT MEM_NB_BLOCK *NBPtr,
435 IN UINT16 MaxRcvEnDly
443 AGESA_TESTPOINT (TpProcMemRcvrCalcLatency, &(NBPtr->MemPtr->StdHeader));
446 // Initial value for MaxRdLat used in training
450 if (MaxRcvEnDly != 0xFFFF) {
454 // Get all sync components BKDG steps 3,4,6,7
455 P = MemNTotalSyncComponentsOr (NBPtr);
460 // 8. P = P + CEIL(MAX(D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] +
461 // D18F2x9C_x0000_0[3:0]0[7:5]_dct[1:0][RdDqsTime] PCLKs))
462 P = P + ((MaxRcvEnDly + MAX_RD_DQS_DLY) + 31) / 32;
467 // 10. T = T + 800 ps
470 // 11. N = (P/(MemClkFreq * 2) + T) * NclkFreq; Convert from PCLKs plus time to NCLKs.
471 MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
472 N = ((((P * MemClkPeriod + 1) / 2) + T) * NBPtr->NBClkFreq + 999999) / 1000000;
474 // 12. N = N - 1. See step 9.
477 // 13. D18F2x210_dct[1:0]_nbp[3:0][MaxRdLatency] = CEIL(N) - 1
481 NBPtr->DCTPtr->Timings.MaxRdLat = (UINT16) N;
482 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRdLat: %03x\n", N);
483 MemNSetBitFieldNb (NBPtr, BFMaxLatency, N);
486 /*-----------------------------------------------------------------------------
489 * This function set MaxRdLat after HW receiver enable training is completed
491 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
492 * @param[in,out] OptParam - Optional parameter
495 * ----------------------------------------------------------------------------
498 MemNExitPhyAssistedTrainingOr (
499 IN OUT MEM_NB_BLOCK *NBPtr,
500 IN OUT VOID *OptParam
505 MEM_TECH_BLOCK *TechPtr;
507 TechPtr = NBPtr->TechPtr;
509 MemNReEnablePhyCompNb (NBPtr, NULL);
511 // Calculate Max Latency for both channels to prepare for position training
512 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
513 IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
514 NBPtr->SwitchDCT (NBPtr, Dct);
516 // For Orochi, we need to reset DisAutoRefresh and ZqcsInterval for
517 // Position training.
519 if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
520 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
521 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
524 if (TechPtr->FindMaxDlyForMaxRdLat (TechPtr, &ChipSel)) {
525 NBPtr->SetMaxLatency (NBPtr, TechPtr->MaxDlyForMaxRdLat);
529 return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
532 /*-----------------------------------------------------------------------------
534 * This function send control words after MEMCLK frequency change
536 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
537 * @param[in,out] OptParam - Optional parameter
540 * ----------------------------------------------------------------------------
543 MemNAfterMemClkFreqChgOr (
544 IN OUT MEM_NB_BLOCK *NBPtr,
545 IN OUT VOID *OptParam
549 MEM_TECH_BLOCK *TechPtr;
551 TechPtr = NBPtr->TechPtr;
553 // Reprogram the DIMMs' buffers right after MEMCLK frequency change
554 if (!(TechPtr->TechnologySpecificHook[LrdimmFreqChgCtrlWrd] (TechPtr, NULL))) {
555 if (NBPtr->MCTPtr->Status[SbRegistered]) {
556 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
557 MemNSwitchDCTNb (NBPtr, Dct);
558 if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
559 TechPtr->FreqChgCtrlWrd (TechPtr);
568 /*-----------------------------------------------------------------------------
570 * This function modifies CS tri-state bit map
572 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
573 * @param[in,out] CsTriBitmap - Bitmap of chipselects to be tristated
576 * ----------------------------------------------------------------------------
579 MemNBeforeSetCsTriOr (
580 IN OUT MEM_NB_BLOCK *NBPtr,
581 IN OUT VOID *CsTriBitmap
585 // The tri-state of CS[7:4] for LrDIMM should be determined by
586 // D18F2xA8_dct[1:0][CsMux45]/[CsMux67]
587 if (NBPtr->MCTPtr->Status[SbLrdimms]) {
588 if (MemNGetBitFieldNb (NBPtr, BFCSMux45) == 1) {
589 *(UINT8*) CsTriBitmap &= 0xCF;
591 if (MemNGetBitFieldNb (NBPtr, BFCSMux67) == 1) {
592 *(UINT8*) CsTriBitmap &= 0x3F;
598 /*----------------------------------------------------------------------------
601 *----------------------------------------------------------------------------
604 /* -----------------------------------------------------------------------------*/
608 * This function gets the total of sync components for Max Read Latency calculation
610 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
612 * @return Total in PCLKs
616 MemNTotalSyncComponentsOr (
617 IN OUT MEM_NB_BLOCK *NBPtr
624 // 3. If (D18F2x9C_x0000_0004_dct[1:0][AddrCmdSetup] = 0 & D18F2x9C_x0000_0004_dct[1:0][CsOdt-
625 // Setup] = 0 & D18F2x9C_x0000_0004_dct[1:0][CkeSetup] = 0)
628 if ((MemNGetBitFieldNb (NBPtr, BFAddrTmgControl) & 0x0202020) == 0) {
634 // 4. P = P + (8 - D18F2x210_dct[1:0]_nbp[3:0][RdPtrInit]) + 1
635 P = P + (8 - (UINT16) MemNGetBitFieldNb (NBPtr, BFRdPtrInit)) + 1;
637 // 6. If (D18F2xA8_dct[1:0][SubMemclkRegDly] = 0 & D18F2x90_dct[1:0][UnbuffDimm] = 0)
639 if ((MemNGetBitFieldNb (NBPtr, BFSubMemclkRegDly) == 0) && (MemNGetBitFieldNb (NBPtr, BFUnBuffDimm) == 0)) {
643 // 7. P = P + (2 * (D18F2x200_dct[1:0][Tcl] - 1 clocks))
644 P = P + (2 * (MemNGetBitFieldNb (NBPtr, BFTcl) - 1));
649 /* -----------------------------------------------------------------------------*/
653 * This function is used to calculate BufDatDelay and BufDatDelaySkew value.
655 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
656 * @param[in] GetDelay - Get either BufDatDly or BufDatDlySkew value
658 * @return BufDatDly or BufDatDlySkew value
661 MemNCalBufDatDelaySkewOr (
662 IN OUT MEM_NB_BLOCK *NBPtr,
673 UINT32 SmallestModuleDly;
674 UINT32 LargestModuleDly;
676 UINT32 BufDatDlySkew;
677 MEM_TECH_BLOCK *TechPtr;
680 TechPtr = NBPtr->TechPtr;
684 SmallestModuleDly = 0;
685 LargestModuleDly = 0;
691 SpdOffset = (UINT8) (2 * CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
693 for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) {
694 if (TechPtr->GetDimmSpdBuffer (TechPtr, &SpdBufferPtr, Dimm)) {
695 if ((SpdBufferPtr[90 + SpdOffset] & 0x7F) < (UINT8) MinModuleDly) {
696 MinModuleDly = SpdBufferPtr[90 + SpdOffset] & 0x7F;
699 if ((SpdBufferPtr[91 + SpdOffset] & 0x7F) > (UINT8) MaxModuleDly) {
700 MaxModuleDly = SpdBufferPtr[91 + SpdOffset] & 0x7F;
705 if (!(MinModuleDly >= 0x3C && MinModuleDly <= 0x58)) {
706 IDS_HDT_CONSOLE (MEM_FLOW, "\tMinModuleDly out of range (0x3C - 0x58): %02x\n", MinModuleDly);
708 if (!(MaxModuleDly >= 0x3C && MaxModuleDly <= 0x58)) {
709 IDS_HDT_CONSOLE (MEM_FLOW, "\tMaxModuleDly out of range (0x3C - 0x58): %02x\n", MaxModuleDly);
712 //Calculate BufDatDly
714 //SmallestModuleDelay = MinimumModuleDelay * .000125 us * 400 MHz * 0x40.
715 //MinimumModuleDelay is the minimum SPD module delay across all DIMMs on a channel.
717 SmallestModuleDly = (UINT32) (MinModuleDly * 125 * 400 * 0x40 / 1000000);
719 //SyncDelay = (F0RC2[AddrCmdPrelaunch] ? 0x30 - (2*F1RC12[QCAPrelaunchDelay]) : 0x20) + 0x10.
720 //SyncDelay is calculated from the SPD values of the MinimumModuleDelay DIMM.
722 TechPtr->GetDimmSpdBuffer (TechPtr, &SpdBufferPtr, i);
723 SyncDelay = (UINT8) ((((SpdBufferPtr[67] & 0x01) == 1) ? (0x30 - 2 * (SpdBufferPtr[70] & 0x07)) : 0x20) + 0x10);
725 //BufDatDelay = FLOOR((((SmallestModuleDelay - SynchDelay) * (MemClkFreq/400 MHz)) + SynchDelay)/0x40).
727 BufDatDly = (((SmallestModuleDly - SyncDelay) * NBPtr->DCTPtr->Timings.Speed / 400) + SyncDelay) / 0x40;
729 if (GetDelay == GetBufDatDly) {
733 //Calculate BufDatDlySkew
735 //LargestModuleDelay = MaximumModuleDelay * .000125 us * 400 MHz * 0x40.
736 //MaximumModuleDelay is the maximum SPD module delay across all DIMMs on a channel.
738 LargestModuleDly = (UINT32) (MaxModuleDly * 125 * 400 * 0x40 / 1000000);
740 //SyncDelay = (F0RC2[AddrCmdPrelaunch] ? 0x30 - (2*F1RC12[QCAPrelaunchDelay]) : 0x20) + 0x10.
741 //SyncDelay is calculated from the SPD values of the MaximumModuleDelay DIMM.
743 TechPtr->GetDimmSpdBuffer (TechPtr, &SpdBufferPtr, j);
744 SyncDelay = (UINT8) ((((SpdBufferPtr[67] & 0x01) == 1) ? (0x30 - 2 * (SpdBufferPtr[70] & 0x07)) : 0x20) + 0x10);
746 //BufDatDelaySkew = FLOOR((((LargestModuleDelay - SynchDelay) * (MemClkFreq/400 MHz)) + SynchDelay)/0x40) - BufDatDelay.
748 BufDatDlySkew = ((((((LargestModuleDly - SyncDelay) * NBPtr->DCTPtr->Timings.Speed + 200) / 400) + SyncDelay) - (BufDatDly * 0x40) + 0x20) / 0x40);
750 return BufDatDlySkew ;
752 /*-----------------------------------------------------------------------------
754 * This function Enables parity on both DCTs if Parity is supported.
756 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
757 * @param[in,out] *OptParam - Unused
760 * ----------------------------------------------------------------------------
763 MemNEnableParityAfterMemRstOr (
764 IN OUT MEM_NB_BLOCK *NBPtr,
765 IN OUT VOID *OptParam
769 MEM_PS_BLOCK * PsPtr;
772 MCTPtr = NBPtr->MCTPtr;
773 PsPtr = NBPtr->PsPtr;
775 if (NBPtr->MCTPtr->Status[SbParDimms]) {
777 // SbParDimms should be set for all DDR3 RDIMMS
778 // Cannot turn off ParEn for DDR3
780 MemNSetBitFieldNb (NBPtr, BFParEn, 1);
782 // LRDIMMS Extended Parity
784 if (MCTPtr->Status[SbLrdimms]) {
785 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
786 if (PsPtr->LrdimmRowAddrBits[i] > 16) {
787 MemNSetBitFieldNb (NBPtr, BFExtendedParityEn, 1);
796 /*-----------------------------------------------------------------------------
799 * This function calculates RdOdtTrnOnDly and RdOdtOnDuration when LrDimms
802 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
803 * @param[in,out] *OptParam - Not Used
805 * @return TRUE - always
806 * ----------------------------------------------------------------------------
809 MemNProgOdtControlOr (
810 IN OUT MEM_NB_BLOCK *NBPtr,
811 IN OUT VOID *OptParam
817 UINT8 RdOdtOnDuration;
819 DCTPtr = NBPtr->DCTPtr;
820 Tcwl = (UINT8) (DCTPtr->Timings.Speed / 133) + 2;
821 RdOdtTrnOnDly = (DCTPtr->Timings.CasL > Tcwl) ? (DCTPtr->Timings.CasL - Tcwl) : 0;
823 if (NBPtr->MCTPtr->Status[SbLrdimms]) {
824 RdOdtTrnOnDly = RdOdtTrnOnDly + (UINT8) MemNCalBufDatDelaySkewOr (NBPtr, GetBufDatDly);
825 RdOdtOnDuration = RdOdtOnDuration + (UINT8) MemNCalBufDatDelaySkewOr (NBPtr, GetBufDatDlySkew);
827 MemNSetBitFieldNb (NBPtr, BFRdOdtTrnOnDly, RdOdtTrnOnDly);
828 MemNSetBitFieldNb (NBPtr, BFRdOdtOnDuration, RdOdtOnDuration);
829 IDS_HDT_CONSOLE (MEM_FLOW,"\n\t\t\tRdOdtTrnOnDly = %x",RdOdtTrnOnDly);
830 IDS_HDT_CONSOLE (MEM_FLOW,"\n\t\t\tRdOdtOnDuration = %x\n",RdOdtOnDuration);
834 /* -----------------------------------------------------------------------------*/
838 * This is a general purpose function that executes before DRAM init
840 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
845 MemNBeforeDramInitOr (
846 IN OUT MEM_NB_BLOCK *NBPtr
851 for (Dct = 0; Dct < MAX_DCTS_PER_NODE_OR; Dct++) {
852 MemNSwitchDCTNb (NBPtr, Dct);
853 if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
855 // 2.10.6.6 DCT Training Specific Configuration
857 MemNSetBitFieldNb (NBPtr, BFAddrCmdTriEn, 0);
858 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
859 MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
860 MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0);
861 MemNSetBitFieldNb (NBPtr, BFDynPageCloseEn, 0);
862 MemNSetBitFieldNb (NBPtr, BFBankSwizzleMode, 0);
863 MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0);
864 MemNSetBitFieldNb (NBPtr, BFPowerDownEn, 0);
865 MemNSetBitFieldNb (NBPtr, BFDisSimulRdWr, 0);
866 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
867 MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 0);
868 MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 0);
869 MemNSetBitFieldNb (NBPtr, BFEnRxPadStandby, 0);
870 MemNSetBitFieldNb (NBPtr, BFBwCapEn, 0);
871 MemNSetBitFieldNb (NBPtr, BFODTSEn, 0);
872 MemNSetBitFieldNb (NBPtr, BFDctSelIntLvEn, 0);
873 MemNSetBitFieldNb (NBPtr, BFL3Scrub, 0);
874 MemNSetBitFieldNb (NBPtr, BFDramScrub, 0);
875 MemNSetBitFieldNb (NBPtr, BFScrubReDirEn, 0);
876 MemNSetBitFieldNb (NBPtr, BFL3ScrbRedirDis, 1);
881 /* -----------------------------------------------------------------------------*/
885 * This function releases the NB P-state force.
887 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
888 * @param[in,out] OptParam - Optional parameter
893 MemNReleaseNbPstateOr (
894 IN OUT MEM_NB_BLOCK *NBPtr,
895 IN OUT VOID *OptParam
898 // 6. Restore the initial D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0] values.
899 MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFF9FFF) | (NBPtr->NbPsCtlReg & 0x6000));
901 // 7. Restore the initial D18F5x170[NbPstateThreshold, NbPstateHi] values.
902 MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFFF13F) | (NBPtr->NbPsCtlReg & 0x0EC0));
907 /* -----------------------------------------------------------------------------*/
911 * This function Sets Power Down options and enables Power Down
913 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
915 * The following registers are set:
916 * BFPowerDownMode BFPrtlChPDEnhEn
917 * BFTxp BFAggrPDDelay
918 * BFTxpDll BFAggrPDEn
919 * BFPchgPDEnDelay BFPowerDownEn
921 * NOTE: Delay values must be set before turning on the associated Enable bit
925 IN OUT MEM_NB_BLOCK *NBPtr
930 CONST UINT32 PwrMngm1[] = {0, 0, 0x05050403, 0x05050403, 0x06060403, 0x07070504, 0x08080504, 0x0A0A0605, 0x0B0B0706};
935 if (NBPtr->RefPtr->EnablePowerDown) {
936 PackageType = LibAmdGetPackageType (&(NBPtr->MemPtr->StdHeader));
940 PowerDownMode = (UINT8) UserOptions.CfgPowerDownMode;
941 PowerDownMode = (!NBPtr->IsSupported[ChannelPDMode]) ? PowerDownMode : 0;
942 IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(NBPtr->MemPtr->StdHeader));
943 if (PowerDownMode == 1) {
944 MemNSetBitFieldNb (NBPtr, BFPowerDownMode, 1);
949 MemNSetTxpNb (NBPtr);
951 // PchgPDModeSel is set elswhere.
953 Tmod = (UINT8) MemNGetBitFieldNb (NBPtr, BFTmod);
955 // Partial Channel Power Down
957 MemNSetBitFieldNb (NBPtr, BFPrtlChPDDynDly, 2);
958 MemNSetBitFieldNb (NBPtr, BFPrtlChPDEnhEn, 1);
960 // Aggressive PowerDown
961 // PchgPDEnDelay: IF (D18F2xA8_dct[1:0][AggrPDEn]) THEN 1 ELSE 0 ENDIF.
963 MemNSetBitFieldNb (NBPtr, BFAggrPDDelay, 0);
964 if (PackageType != PACKAGE_TYPE_AM3r2) {
965 MemNSetBitFieldNb (NBPtr, BFAggrPDEn, 1);
966 MemNSetBitFieldNb (NBPtr, BFPchgPDEnDelay, 1);
969 // Program DRAM Power Management 1 register
970 Speed = NBPtr->DCTPtr->Timings.Speed;
971 i = (UINT8) ((Speed < DDR800_FREQUENCY) ? ((Speed / 66) - 3) : (Speed / 133));
972 ASSERT ((i > 1) && (i < sizeof (PwrMngm1)));
973 MemNSetBitFieldNb (NBPtr, BFDramPwrMngm1Reg, PwrMngm1[i]);