7 * Common Northbridge features
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/NB)
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 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 * ***************************************************************************
47 *----------------------------------------------------------------------------
50 *----------------------------------------------------------------------------
54 #include "AdvancedApi.h"
57 #include "OptionMemory.h"
61 #include "PlatformMemoryConfiguration.h"
67 #define FILECODE PROC_MEM_NB_MNFEAT_FILECODE
68 /*----------------------------------------------------------------------------
69 * DEFINITIONS AND MACROS
71 *----------------------------------------------------------------------------
73 #define MAX_CL_CONT_READ 32
74 #define MAX_CL_CONT_WRITE 32
76 /*----------------------------------------------------------------------------
77 * TYPEDEFS AND STRUCTURES
79 *----------------------------------------------------------------------------
82 /*----------------------------------------------------------------------------
83 * PROTOTYPES OF LOCAL FUNCTIONS
85 *----------------------------------------------------------------------------
90 MemNContWritePatternNb (
91 IN OUT MEM_NB_BLOCK *NBPtr,
99 MemNContReadPatternNb (
100 IN OUT MEM_NB_BLOCK *NBPtr,
108 MemNGenHwRcvEnReadsNb (
109 IN OUT MEM_NB_BLOCK *NBPtr,
115 MemNCompareTestPatternClientNb (
116 IN OUT MEM_NB_BLOCK *NBPtr,
124 MemNInsDlyCompareTestPatternClientNb (
125 IN OUT MEM_NB_BLOCK *NBPtr,
133 MemNContWritePatternClientNb (
134 IN OUT MEM_NB_BLOCK *NBPtr,
142 MemNContReadPatternClientNb (
143 IN OUT MEM_NB_BLOCK *NBPtr,
151 MemNGenHwRcvEnReadsClientNb (
152 IN OUT MEM_NB_BLOCK *NBPtr,
158 MemNBeforeMemClrClientNb (
159 IN OUT MEM_NB_BLOCK *NBPtr,
165 MemNGenHwRcvEnReadsUnb (
166 IN OUT MEM_NB_BLOCK *NBPtr,
172 MemNContReadPatternUnb (
173 IN OUT MEM_NB_BLOCK *NBPtr,
181 MemNContWritePatternUnb (
182 IN OUT MEM_NB_BLOCK *NBPtr,
190 MemNEnableInfiniteWritePatternUnb (
191 IN OUT MEM_NB_BLOCK *NBPtr
196 MemNDisableInfiniteWritePatternUnb (
197 IN OUT MEM_NB_BLOCK *NBPtr
202 IN OUT MEM_NB_BLOCK *NBPtr
206 MemNInitDqsTrainRcvrEnHwNb (
207 IN OUT MEM_NB_BLOCK *NBPtr
211 MemNDisableDqsTrainRcvrEnHwNb (
212 IN OUT MEM_NB_BLOCK *NBPtr
216 MemNInitCPGClientNb (
217 IN OUT MEM_NB_BLOCK *NBPtr
222 IN OUT MEM_NB_BLOCK *NBPtr
225 /*----------------------------------------------------------------------------
228 *----------------------------------------------------------------------------
231 /* -----------------------------------------------------------------------------*/
234 * This function assigns read/write function pointers to CPG read/write modules.
236 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
241 IN OUT MEM_NB_BLOCK *NBPtr
244 NBPtr->WritePattern = MemNContWritePatternNb;
245 NBPtr->ReadPattern = MemNContReadPatternNb;
246 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
249 /* -----------------------------------------------------------------------------*/
252 * This function initializes member functions of HW Rx En Training.
254 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
259 MemNInitDqsTrainRcvrEnHwNb (
260 IN OUT MEM_NB_BLOCK *NBPtr
263 NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
265 /* -----------------------------------------------------------------------------*/
268 * This function disables member functions of Hw Rx En Training.
270 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
275 MemNDisableDqsTrainRcvrEnHwNb (
276 IN OUT MEM_NB_BLOCK *NBPtr
279 NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
282 /*----------------------------------------------------------------------------
285 *----------------------------------------------------------------------------
288 /* -----------------------------------------------------------------------------*/
291 * This function writes 9 or 18 cache lines continuously using GH CPG engine
293 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
294 * @param[in] Pattern - Array of bytes that will be written to DRAM
295 * @param[in] Address - System Address [47:16]
296 * @param[in] ClCount - Number of cache lines
301 MemNContWritePatternNb (
302 IN OUT MEM_NB_BLOCK *NBPtr,
309 if (ClCount > MAX_CL_CONT_WRITE) {
310 ClDiff = ClCount - MAX_CL_CONT_WRITE;
311 ClCount = MAX_CL_CONT_WRITE;
316 // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
317 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
319 // Issue the stream of writes. When F2x11C[MctWrLimit] is reached (or when F2x11C[FlushWr] is set
320 // again), all the writes are written to DRAM.
321 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
322 MemUWriteCachelines (Address, Pattern, ClCount);
324 // Flush out prior writes by setting F2x11C[FlushWr].
325 MemNSetBitFieldNb (NBPtr, BFFlushWr, 1);
326 // Wait for F2x11C[FlushWr] to clear, indicating prior writes have been flushed.
327 while (MemNGetBitFieldNb (NBPtr, BFFlushWr) != 0) {}
329 // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
330 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
333 MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
337 /* -----------------------------------------------------------------------------*/
341 * This function reads 9 or 18 cache lines continuously using GH CPG engine
343 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
344 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
345 * @param[in] Address - System Address [47:16]
346 * @param[in] ClCount - Number of cache lines
352 MemNContReadPatternNb (
353 IN OUT MEM_NB_BLOCK *NBPtr,
359 BOOLEAN DisAutoRefresh;
361 if (ClCount > MAX_CL_CONT_READ) {
362 ClDiff = ClCount - MAX_CL_CONT_READ;
363 ClCount = MAX_CL_CONT_READ;
368 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
370 // 1. BIOS ensures that the only accesses outstanding to the MCT are training reads.
371 // 2. If F2x[1, 0]90[BurstLength32]=1, then BIOS ensures that the DCTs and DRAMs are configured for 64
372 // byte bursts (8-beat burst length). This requires that BIOS issue MRS commands to the devices
373 // to change to an 8-beat burst length and then to restore the desired burst length after training
376 if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
377 DisAutoRefresh = FALSE;
378 // 3. BIOS programs F2x[1, 0]90[ForceAutoPchg] = 0 and F2x[1, 0]8C[DisAutoRefresh] = 1.
379 // 4. If necessary, BIOS programs F2x[1, 0]78[EarlyArbEn] = 1 at this time. See register description.
380 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
381 // MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0); // ForceAutoPchg is 0 by default.
382 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
384 DisAutoRefresh = TRUE;
387 MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
389 // 5. BIOS sets F2x11C[MctPrefReqLimit] to the number of training reads (Ntrain) it wishes to generate in the
390 // training sequence.
391 MemNSetBitFieldNb (NBPtr, BFMctPrefReqLimit, ClCount - 1);
393 // 6. BIOS sets F2x11C[PrefDramTrainMode] bit.
394 // 7. The act of setting F2x11C[PrefDramTrainMode] causes the MCT to flush out the prefetch stride predictor
395 // table (removing any existing prefetch stride patterns).
396 MemNSetBitFieldNb (NBPtr, BFPrefDramTrainMode, 1);
398 // 8. BIOS issues an SFENCE (or other serializing instruction) to ensure that the prior write completes.
399 // 9. For revision C and earlier processors, BIOS generates two training reads. For revision D processors BIOS
400 // generates three training reads. Three are required to detect the stride with DCQ buddy enabled. These must
401 // be to consecutive cache lines (i.e. 64 bytes apart) and must not cross a naturally aligned 4 Kbyte boundary.
402 // 10. These reads set up a stride pattern which is detected by the prefetcher. The prefetcher then continues to
403 // issue prefetches until F2x11C[MctPrefReqLimit] is reached, at which point the MCT clears
404 // F2x11C[PrefDramTrainMode].
405 MemUDummyCLRead (Address);
406 MemUDummyCLRead (Address + 0x40);
407 if (NBPtr->IsSupported[CheckDummyCLRead]) {
408 MemUDummyCLRead (Address + 0x80);
410 // 11. BIOS issues the remaining (Ntrain - 2 for revisions C and earlier or Ntrain - 3 for revision D) reads after
411 // checking that F2x11C[PrefDramTrainMode] is cleared. These reads must be to consecutive cache lines
412 // (i.e., 64 bytes apart) and must not cross a naturally aligned 4KB boundary. These reads hit the prefetches
413 // and read the data from the prefetch buffer.
414 while (MemNGetBitFieldNb (NBPtr, BFPrefDramTrainMode) != 0) {}
415 MemUReadCachelines (Buffer, Address, ClCount);
417 // 14. BIOS restores the target values for F2x[1, 0]90[ForceAutoPchg], F2x[1, 0]8C[DisAutoRefresh] and
418 // F2x[1, 0]90[BurstLength32].
419 if (!DisAutoRefresh) {
420 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
421 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
425 MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
429 /* -----------------------------------------------------------------------------*/
433 * This function generates a continuous burst of reads during HW RcvEn training.
435 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
436 * @param[in] Address - System Address [47:16]
441 MemNGenHwRcvEnReadsNb (
442 IN OUT MEM_NB_BLOCK *NBPtr,
446 UINT8 TempBuffer[12 * 64];
449 for (BurstCount = 0; BurstCount < 10; BurstCount++) {
450 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
451 NBPtr->FlushPattern (NBPtr, Address, 12);
455 /* -----------------------------------------------------------------------------*/
458 * This function writes cache lines continuously using TCB CPG engine
460 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
461 * @param[in] Pattern - Array of bytes that will be written to DRAM
462 * @param[in] Address - System Address [47:16]
463 * @param[in] ClCount - Number of cache lines
468 MemNContWritePatternClientNb (
469 IN OUT MEM_NB_BLOCK *NBPtr,
483 // 1. Program D18F2x1C0[WrDramTrainMode]=1.
484 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
486 PatternHash = ClCount << 24;
487 for (i = 0; i < 3; i ++) {
488 PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
490 if (NBPtr->CPGInit != PatternHash) {
493 // Double pattern length for MaxRdLat training
497 // If write training buffer has not been initialized, initialize it
498 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
499 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
501 // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
502 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
504 // 4. Successively write each dword of the training pattern to D18F2x1D4.
505 DwordPtr = (UINT32 *) Pattern;
506 for (j = 0; j < Multiplier; j++) {
507 for (i = 0; i < (ClCount * 16); i++) {
508 MemNSetBitFieldNb (NBPtr, BFWrTrainBufDat, DwordPtr[i]);
512 NBPtr->CPGInit = PatternHash;
515 // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
516 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
518 // 6. Program the DRAM training address
519 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
520 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
522 // 7. Program D18F2x1C0[WrTrainGo]=1.
523 MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
525 // 8. Wait for D18F2x1C0[WrTrainGo]=0.
526 while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
528 // 9. Program D18F2x1C0[WrDramTrainMode]=0.
529 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
532 /* -----------------------------------------------------------------------------*/
536 * This function reads cache lines continuously using TCB CPG engine
538 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
539 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
540 * @param[in] Address - System Address [47:16]
541 * @param[in] ClCount - Number of cache lines
547 MemNContReadPatternClientNb (
548 IN OUT MEM_NB_BLOCK *NBPtr,
558 // Double pattern length for MaxRdLat training
562 // 1. Program D18F2x1C0[RdDramTrainMode]=1.
563 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
565 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
566 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
568 // 3. Program the DRAM training address as follows:
569 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
570 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
572 // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
573 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
575 // 5. Program D18F2x1C0[RdTrainGo]=1.
576 MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
578 // 6. Wait for D18F2x1C0[RdTrainGo]=0.
579 while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
581 // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
582 // This step will be accomplished in Compare routine.
584 // 8. Program D18F2x1C0[RdDramTrainMode]=0.
585 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
588 /* -----------------------------------------------------------------------------*/
592 * This function generates a continuous burst of reads during HW RcvEn training.
594 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
595 * @param[in] Address - System Address [47:16]
600 MemNGenHwRcvEnReadsClientNb (
601 IN OUT MEM_NB_BLOCK *NBPtr,
605 UINT8 TempBuffer[64];
608 for (Count = 0; Count < 3; Count++) {
609 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
613 /* -----------------------------------------------------------------------------*/
616 * This function assigns read/write function pointers to CPG read/write modules.
618 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
622 MemNInitCPGClientNb (
623 IN OUT MEM_NB_BLOCK *NBPtr
626 NBPtr->WritePattern = MemNContWritePatternClientNb;
627 NBPtr->ReadPattern = MemNContReadPatternClientNb;
628 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsClientNb;
629 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
630 NBPtr->CompareTestPattern = MemNCompareTestPatternClientNb;
631 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternClientNb;
632 NBPtr->FamilySpecificHook[BeforeMemClr] = MemNBeforeMemClrClientNb;
636 /* -----------------------------------------------------------------------------*/
639 * This function compares test pattern with data in buffer and
640 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
642 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
643 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
644 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
645 * @param[in] ByteCount - Byte count
647 * @return PASS - Bitmap of results of comparison
652 MemNCompareTestPatternClientNb (
653 IN OUT MEM_NB_BLOCK *NBPtr,
659 return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts));
662 /*-----------------------------------------------------------------------------*/
665 * This function compares test pattern with data in buffer and
666 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
668 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
669 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
670 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
671 * @param[in] ByteCount - Byte count
673 * @retval Bitmap of results of comparison
677 MemNInsDlyCompareTestPatternClientNb (
678 IN OUT MEM_NB_BLOCK *NBPtr,
684 return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
687 /* -----------------------------------------------------------------------------*/
690 * This function calculates RcvEn seed value for each rank
692 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
696 MemNPrepareRcvrEnDlySeedNb (
697 IN OUT MEM_NB_BLOCK *NBPtr
700 MEM_TECH_BLOCK *TechPtr;
701 CH_DEF_STRUCT *ChannelPtr;
707 UINT16 SeedTotalPreScaling;
718 TechPtr = NBPtr->TechPtr;
719 MCTPtr = NBPtr->MCTPtr;
720 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
721 Speed = NBPtr->DCTPtr->Timings.Speed;
722 SeedTotalPreScaling = 0;
723 ChipSel = TechPtr->ChipSel;
724 Pass = TechPtr->Pass;
726 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
727 TechPtr->Bytelane = ByteLane;
729 // Get platform override seed
730 PlatEstSeed = (UINT16 *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, MCTPtr->SocketId, ChannelPtr->ChannelID, ChipSel >> 1,
731 &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
732 // For Pass1, BIOS starts with the delay value obtained from the first pass of write
733 // levelization training that was done in DDR3 Training and add a delay value of 3Bh.
735 NBPtr->FamilySpecificHook[OverrideRcvEnSeed] (NBPtr, &PlatEst);
736 PlatEst = ((PlatEstSeed != NULL) ? PlatEstSeed[ByteLane] : PlatEst);
737 SeedTotal = ChannelPtr->WrDqsDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane] + PlatEst;
738 SeedValue[ByteLane] = PlatEst;
741 // SeedTotalPreScaling = (the total delay values in D18F2x[1,0]9C_x0000_00[24:10] from pass 1 of
742 // DQS receiver enable training) - 20h. Subtract 1UI to get back to preamble left edge.
743 if (((ChipSel & 1) == 0) && NBPtr->FamilySpecificHook[TrainingNibbleZero] (NBPtr, &ChipSel)) {
744 // Save Seed for odd CS SeedTotalPreScaling RxEn Value
745 TechPtr->PrevPassRcvEnDly[ByteLane] = ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane];
747 NBPtr->FamilySpecificHook[OverridePrevPassRcvEnDly] (NBPtr, &TechPtr->PrevPassRcvEnDly[ByteLane]);
748 SeedTotalPreScaling = TechPtr->PrevPassRcvEnDly[ByteLane] - 0x20;
749 // SeedTotal = SeedTotalPreScaling*target frequency/lowest supported frequency.
750 SeedTotal = (UINT16) (((UINT32) SeedTotalPreScaling * Speed) / TechPtr->PrevSpeed);
751 NBPtr->FamilySpecificHook[OverrideRcvEnSeedPassN] (NBPtr, &SeedTotal);
753 SeedTtl[ByteLane] = SeedTotal;
755 // SeedGross = SeedTotal DIV 32.
756 SeedGross = SeedTotal >> 5;
757 // SeedFine = SeedTotal MOD 32.
758 SeedFine = SeedTotal & 0x1F;
759 // Next, determine the gross component of SeedTotal. SeedGrossPass1=SeedTotal DIV 32.
760 // Then, determine the fine delay component of SeedTotal. SeedFinePass1=SeedTotal MOD 32.
761 // Use SeedGrossPass1 to determine SeedPreGrossPass1:
763 if ((SeedGross & 0x1) != 0) {
764 //if SeedGross is odd
767 //if SeedGross is even
770 // (SeedGross - SeedPreGross)
771 TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
773 //BIOS programs registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 with SeedPreGrossPass1
774 //and SeedFinePass1 from the preceding steps.
776 NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
777 SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
779 // 202688: Program seed value to RcvEnDly also.
780 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
783 IDS_HDT_CONSOLE_DEBUG_CODE (
785 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
786 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
787 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedValue[ByteLane]);
789 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
791 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedTotal: ");
792 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
793 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
795 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
796 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
797 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
799 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
802 NBPtr->FamilySpecificHook[RegAccessFence] (NBPtr, NULL);
805 /* -----------------------------------------------------------------------------*/
808 * Waits specified number of MEMCLKs
809 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
810 * @param[in] MemClkCount - Number of MEMCLKs
812 * ----------------------------------------------------------------------------
816 IN OUT MEM_NB_BLOCK *NBPtr,
817 IN UINT32 MemClkCount
820 MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
823 /* -----------------------------------------------------------------------------*/
826 * Issues dummy TCB write read to zero out CL that is used for MemClr
827 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
828 * @param[in,out] *UnUsed - unused
830 * ----------------------------------------------------------------------------
834 MemNBeforeMemClrClientNb (
835 IN OUT MEM_NB_BLOCK *NBPtr,
842 for (i = 0; i < 64; i++) {
846 MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
847 MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
851 /* -----------------------------------------------------------------------------*/
854 * This function uses the PRBS generator in the DCT to send a DDR Activate command
856 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
857 * @param[in] ChipSelect - Chip select 0-7
858 * @param[in] Bank - Bank Address 0-7
859 * @param[in] RowAddress - Row Address [17:0]
865 IN OUT MEM_NB_BLOCK *NBPtr,
872 MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
874 MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
876 MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
878 MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
879 // Wait for command complete
880 MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
882 NBPtr->WaitXMemClks (NBPtr, 75);
885 /* -----------------------------------------------------------------------------*/
888 * This function uses the PRBS generator in the DCT to send a DDR Precharge
889 * or Precharge All command
891 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
892 * @param[in] ChipSelect - Chip select 0-7
893 * @param[in] Bank - Bank Address 0-7, PRECHARGE_ALL_BANKS = Precharge All
899 MemNRrwPrechargeCmd (
900 IN OUT MEM_NB_BLOCK *NBPtr,
906 NBPtr->WaitXMemClks (NBPtr, 25);
908 NBPtr->SetBitField (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
909 if (Bank == PRECHARGE_ALL_BANKS) {
910 // Set Row Address, bit 10
911 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) | (1 << 10) );
913 // Clear Row Address, bit 10
914 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
916 NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
919 NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
920 // Wait for command complete
921 NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
923 NBPtr->WaitXMemClks (NBPtr, 25);
925 /* -----------------------------------------------------------------------------*/
929 * This function generates a continuous burst of reads for HW RcvEn
930 * training using the Unified Northbridge Reliable Read/Write Engine.
932 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
933 * @param[in] Address - Unused by this function
938 MemNGenHwRcvEnReadsUnb (
939 IN OUT MEM_NB_BLOCK *NBPtr,
946 // Issue Stream of Reads from the Target Rank
948 NBPtr->ReadPattern (NBPtr, DummyPtr, 0, NBPtr->TechPtr->PatternLength);
951 /* -----------------------------------------------------------------------------*/
954 * This function generates a continuous stream of reads from DRAM using the
955 * Unified Northbridge Reliable Read/Write Engine.
957 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
958 * @param[in,out] Buffer - Unused by this function
959 * @param[in] Address - Unused by this function
960 * @param[in] ClCount - Number of cache lines to read
970 MemNContReadPatternUnb (
971 IN OUT MEM_NB_BLOCK *NBPtr,
977 MEM_TECH_BLOCK *TechPtr;
982 TechPtr = NBPtr->TechPtr;
983 Rrw = &NBPtr->RrwSettings;
985 ChipSel = TechPtr->ChipSel;
986 CmdTgt = Rrw->CmdTgt;
988 // Wait for RRW Engine to be ready and turn it on
990 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
991 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
993 // Depending upon the Cmd Target, send Row Activate and set Chipselect
994 // for the Row or Rows that will be used
996 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
997 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
998 if (CmdTgt == CMD_TGT_AB) {
999 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
1000 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
1002 // Set Comparison Masks
1003 NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
1004 NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
1006 // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
1008 NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
1010 // Program the PRBS Seed
1012 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1014 // Set the Command Count
1016 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1018 // Program the Bubble Count and CmdStreamLen
1020 NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1021 NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1022 NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1024 // Program the Starting Address
1026 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1027 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1028 if (CmdTgt == CMD_TGT_AB) {
1029 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1030 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1033 // Reset All Errors and Disable StopOnErr
1035 NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1036 NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
1038 // Program the CmdTarget
1040 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1042 // Set CmdType to read
1044 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1046 // Start the Commands
1048 AGESA_TESTPOINT (TpProcMemContinPatternGenRead, &(NBPtr->MemPtr->StdHeader));
1049 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1051 // Commands have started, wait for the reads to complete then clear the command
1053 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1054 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1055 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1057 // Send the Precharge All Command
1059 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1061 // Turn Off the RRW Engine
1063 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1066 /* -----------------------------------------------------------------------------*/
1069 * This function generates a continuous stream of writes to DRAM using the
1070 * Unified Northbridge Reliable Read/Write Engine.
1072 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1073 * @param[in,out] Address - Unused by this function
1074 * @param[in] Pattern - Unused by this function
1075 * @param[in] ClCount - Number of cache lines to write
1081 MemNContWritePatternUnb (
1082 IN OUT MEM_NB_BLOCK *NBPtr,
1088 MEM_TECH_BLOCK *TechPtr;
1093 TechPtr = NBPtr->TechPtr;
1094 Rrw = &NBPtr->RrwSettings;
1096 ChipSel = TechPtr->ChipSel;
1097 CmdTgt = Rrw->CmdTgt;
1099 // Wait for RRW Engine to be ready and turn it on
1101 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1102 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1104 // Depending upon the Cmd Target, send Row Activate and set Chipselect
1105 // for the Row or Rows that will be used
1107 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1108 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1109 if (CmdTgt == CMD_TGT_AB) {
1110 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
1111 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
1114 // Program the PRBS Seed
1116 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1118 // Set the Command Count
1120 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1122 // Program the Bubble Count and CmdStreamLen
1124 NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1125 NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1126 NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1128 // Program the Starting Address
1130 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1131 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1132 if (CmdTgt == CMD_TGT_AB) {
1133 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1134 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1137 // Program the CmdTarget
1139 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1141 // Set CmdType to Write
1143 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1145 // Start the Commands
1147 AGESA_TESTPOINT (TpProcMemContinPatternGenWrite, &(NBPtr->MemPtr->StdHeader));
1148 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1150 // Commands have started, wait for the writes to complete then clear the command
1152 // Wait for TestStatus = 1 and CmdSendInProg = 0.
1153 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1154 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1155 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1157 // Send the Precharge All Command
1159 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1161 // Turn Off the RRW Engine
1163 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1166 /* -----------------------------------------------------------------------------*/
1169 * This function checks the Error status bits for comparison results
1171 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1172 * @param[in] Buffer[] - Not used in this implementation
1173 * @param[in] Pattern[] - Not used in this implementation
1174 * @param[in] ByteCount - Not used in this implementation
1176 * @return PASS - Bitmap of results of comparison
1181 MemNCompareTestPatternUnb (
1182 IN OUT MEM_NB_BLOCK *NBPtr,
1194 UINT8* FailingBitMaskPtr;
1195 UINT8 FailingBitMask[9];
1196 UINT32 NibbleErrSts;
1198 ChipSel = NBPtr->TechPtr->ChipSel;
1199 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1200 // Calculate Failing Bitmask pointer
1201 FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
1204 // Get Failing bit data
1206 *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
1207 *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
1208 FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
1212 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1214 NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1216 for (i = 0; i < ColumnCount ; i++) {
1217 Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
1219 FailingBitMaskPtr[i] = FailingBitMask[i];
1225 /*-----------------------------------------------------------------------------*/
1228 * This function checks the Error status bits for offset comparison results
1230 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1231 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
1232 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
1233 * @param[in] ByteCount - Byte count
1235 * @retval Bitmap of results of comparison
1239 MemNInsDlyCompareTestPatternUnb (
1240 IN OUT MEM_NB_BLOCK *NBPtr,
1249 UINT32 NibbleErr180Sts;
1251 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1254 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1256 NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1258 for (i = 0; i < ColumnCount ; i++) {
1259 Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
1260 NibbleErr180Sts >>= 2;
1267 /* -----------------------------------------------------------------------------*/
1270 * This function assigns read/write function pointers to CPG read/write modules.
1272 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1277 IN OUT MEM_NB_BLOCK *NBPtr
1280 NBPtr->WritePattern = MemNContWritePatternUnb;
1281 NBPtr->ReadPattern = MemNContReadPatternUnb;
1282 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsUnb;
1283 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
1284 NBPtr->TrainingPatternInit = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1285 NBPtr->TrainingPatternFinalize = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1286 NBPtr->CompareTestPattern = MemNCompareTestPatternUnb;
1287 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternUnb;
1288 NBPtr->FamilySpecificHook[SetupHwTrainingEngine] = MemNSetupHwTrainingEngineUnb;
1289 NBPtr->EnableInfiniteWritePattern = MemNEnableInfiniteWritePatternUnb;
1290 NBPtr->DisableInfiniteWritePattern = MemNDisableInfiniteWritePatternUnb;
1293 /* -----------------------------------------------------------------------------*/
1296 * This function generates a continuous stream of writes infinite writes to DRAM using the
1297 * Unified Northbridge Reliable Read/Write Engine.
1299 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1305 MemNEnableInfiniteWritePatternUnb (
1306 IN OUT MEM_NB_BLOCK *NBPtr
1312 MEM_TECH_BLOCK *TechPtr;
1316 TechPtr = NBPtr->TechPtr;
1317 Rrw = &NBPtr->RrwSettings;
1318 ChipSel = TechPtr->ChipSel;
1319 CmdTgt = Rrw->CmdTgt;
1321 // Ensure that DisAutoRefresh and ZqCals are disabled during the use of RRWM
1322 if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
1323 NBPtr->OrigDisAutoRefreshState = FALSE;
1324 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
1325 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
1327 NBPtr->OrigDisAutoRefreshState = TRUE;
1331 // Enable I/O Skew mode
1333 for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8) ; ByteLane++) {
1334 //Move WrDQS settings from current DIMM to DIMM 0
1335 WrDqsValue = NBPtr->ChannelPtr->WrDqsDlys[(NBPtr->TechPtr->ChipSel >> 1) * NBPtr->TechPtr->DlyTableWidth () + ByteLane];
1336 NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (0, ByteLane), (UINT16)WrDqsValue);
1337 //Move WrDat settings from current DIMM to DIMM 0
1338 WrDatValue = NBPtr->ChannelPtr->WrDatDlys[(NBPtr->TechPtr->ChipSel >> 1) * NBPtr->TechPtr->DlyTableWidth () + ByteLane];
1339 NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (0, ByteLane), (UINT16)WrDatValue);
1341 NBPtr->SetBitField (NBPtr, BFReserved00A, 0x0001);
1349 // Wait for RRW Engine to be ready and turn it on
1351 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1352 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1354 // Depending upon the Cmd Target, send Row Activate and set Chipselect
1355 // for the Row or Rows that will be used
1357 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1358 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1360 // Program the PRBS Seed
1362 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1364 // Set the Command Count
1366 NBPtr->SetBitField (NBPtr, BFCmdCount, 0);
1368 // Program the Bubble Count and CmdStreamLen
1370 NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1371 NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1372 NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1374 // Program the Starting Address
1376 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1377 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1379 // Program the CmdTarget
1381 NBPtr->SetBitField (NBPtr, BFCmdTgt, CMD_TGT_A);
1383 // Set CmdType to write
1385 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1387 // Start the Commands
1389 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1392 /* -----------------------------------------------------------------------------*/
1395 * This function disables the infinite stream of writes to DRAM using the
1396 * Unified Northbridge Reliable Read/Write Engine.
1398 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1404 MemNDisableInfiniteWritePatternUnb (
1405 IN OUT MEM_NB_BLOCK *NBPtr
1413 NBPtr->SetBitField (NBPtr, BFCmdCount, 1);
1414 //Wait for TestStatus = 1 and CmdSendInProg = 0
1415 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1416 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1418 // Disable I/O Skew Mode
1419 for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8) ; ByteLane++) {
1420 //Move WrDqs settings from DIMM 0 from saved area back to register
1421 WrDqsValue = NBPtr->ChannelPtr->WrDqsDlys[0 * NBPtr->TechPtr->DlyTableWidth () + ByteLane];
1422 NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (0, ByteLane), (UINT16)WrDqsValue);
1423 //Move WrDat settings from DIMM 0 from saved area back to register
1424 WrDatValue = NBPtr->ChannelPtr->WrDatDlys[0 * NBPtr->TechPtr->DlyTableWidth () + ByteLane];
1425 NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (0, ByteLane), (UINT16)WrDatValue);
1427 NBPtr->SetBitField (NBPtr, BFReserved00A, 0x0000);
1429 // Turn Off the RRW Engine
1431 MemNRrwPrechargeCmd (NBPtr, NBPtr->TechPtr->ChipSel, PRECHARGE_ALL_BANKS);
1432 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1434 // Restore DisAutoRefresh and ZQCals to original state
1436 if (!NBPtr->OrigDisAutoRefreshState) {
1437 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
1438 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
1442 /*-----------------------------------------------------------------------------*/
1445 * This function checks the 180 Error status bits for RD DQS training
1447 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1448 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
1449 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
1450 * @param[in] ByteCount - Byte count,
1452 * @retval Bitmap of results of comparison
1455 MemN180CompareRdDqs__PatternUnb (
1456 IN OUT MEM_NB_BLOCK *NBPtr,
1462 return NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1466 /* -----------------------------------------------------------------------------*/
1469 * This function checks the In Phase Error status bits for comparison results for RDDQS training
1471 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1472 * @param[in] Buffer[] - Not used in this implementation
1473 * @param[in] Pattern[] - Not used in this implementation
1474 * @param[in] ByteCount - Not used in this implementation
1476 * @return PASS - Bitmap of results of comparison
1480 MemNInPhaseCompareRdDqs__PatternUnb (
1481 IN OUT MEM_NB_BLOCK *NBPtr,
1487 return NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1489 /* -----------------------------------------------------------------------------*/
1492 * This function starts the Victim for RdDqs Training Continuous Writes
1494 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1495 * @param[in] SeedCount - Seed count
1498 MemNStartRdDqs__VictimContinuousWritesUnb (
1499 IN OUT MEM_NB_BLOCK *NBPtr,
1503 // Program the PRBS Seed
1504 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, NBPtr->GetPrbs__RdDqsSeed (NBPtr, SeedCount));
1506 // Enable continuous writes on the victim channels
1508 // Set the Command Count
1509 NBPtr->SetBitField (NBPtr, BFCmdCount, 256);
1510 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1511 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1512 // Wait for TestStatus = 1 and CmdSendInProg = 0.
1513 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1514 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1516 // Enable continuous reads on the victim channels
1518 // Set the Command Count
1519 ASSERT (NBPtr->MaxAggressorDimms[NBPtr->Dct] != 0);
1520 NBPtr->SetBitField (NBPtr, BFCmdCount, (25600 / NBPtr->MaxAggressorDimms[NBPtr->Dct]));
1521 // Reset All Errors and Disable StopOnErr
1522 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1523 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1524 // Wait for TestStatus = 1 and CmdSendInProg = 0
1525 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1527 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1529 /* -----------------------------------------------------------------------------*/
1532 * This function Initializes the Victim chipSelects for RdDqs Training Continuous Writes
1534 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1537 MemNInitializeRdDqs__VictimChipSelContinuousWritesUnb (
1538 IN OUT MEM_NB_BLOCK *NBPtr
1541 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, NBPtr->TechPtr->ChipSel);
1542 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, NBPtr->TechPtr->ChipSel);
1543 NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1545 /* -----------------------------------------------------------------------------*/
1548 * This function finalizes the Victim for RdDqs Training
1550 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1553 MemNFinalizeRdDqs__VictimContinuousWritesUnb (
1554 IN OUT MEM_NB_BLOCK *NBPtr
1559 InitialCS = NBPtr->TechPtr->ChipSel;
1560 NBPtr->SetBitField (NBPtr, BFReserved003, 0);
1561 for (ChipSel = InitialCS; ChipSel < (InitialCS + 2); ChipSel++) {
1562 // Ensure that Odd and Even CS are trained
1563 if ((NBPtr->DCTPtr->Timings.CsEnabled & ((UINT16) 1 << ChipSel)) == 0) {
1566 NBPtr->TechPtr->ChipSel = ChipSel;
1567 // Send the Precharge All Command
1568 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1570 // Turn Off the RRW Engine
1571 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1573 /* -----------------------------------------------------------------------------*/
1576 * This function Initializes the Victim for RdDqs Training
1578 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1581 MemNInitializeRdDqs__VictimContinuousWritesUnb (
1582 IN OUT MEM_NB_BLOCK *NBPtr
1588 InitialCS = NBPtr->TechPtr->ChipSel;
1589 Rrw = &NBPtr->RrwSettings;
1590 // Program the Bubble Count and CmdStreamLen
1591 NBPtr->SetBitField (NBPtr, BFReserved007, 32);
1592 NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1593 NBPtr->SetBitField (NBPtr, BFReserved006, 63);
1594 // Set Comparison Masks
1595 NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
1596 NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
1597 // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
1598 NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
1599 // Program the Starting Address
1600 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1601 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1602 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1603 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1604 NBPtr->SetBitField (NBPtr, BFCmdTgt, CMD_TGT_AB);
1605 // Wait for RRW Engine to be ready and turn it on
1606 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1607 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1608 for (ChipSel = InitialCS; ChipSel < (InitialCS + 2); ChipSel++) {
1609 // Ensure that Odd and Even CS are trained
1610 if ((NBPtr->DCTPtr->Timings.CsEnabled & ((UINT16) 1 << ChipSel)) == 0) {
1613 NBPtr->TechPtr->ChipSel = ChipSel;
1615 MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << NBPtr->TechPtr->ChipSel));
1617 MemNSetBitFieldNb (NBPtr, BFCmdBank, Rrw->TgtBankAddressA);
1619 MemNSetBitFieldNb (NBPtr, BFCmdAddress, Rrw->TgtRowAddressA);
1621 MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
1622 // Wait for command complete
1623 MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
1625 MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << NBPtr->TechPtr->ChipSel));
1627 MemNSetBitFieldNb (NBPtr, BFCmdBank, Rrw->TgtBankAddressB);
1629 MemNSetBitFieldNb (NBPtr, BFCmdAddress, Rrw->TgtRowAddressB);
1631 MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
1632 // Wait for command complete
1633 MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
1635 NBPtr->SetBitField (NBPtr, BFReserved003, 1);
1637 /* -----------------------------------------------------------------------------*/
1640 * This function enables continuous writes on unused channels
1641 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1642 * @param[in] *SeedCount - seed index
1649 MemNGetPrbs__RdDqsSeedUnb (
1650 IN OUT MEM_NB_BLOCK *NBPtr,
1655 ASSERT (SeedCount <= (NBPtr->MaxSeedCount - 1))
1656 PrbsSeed = ((UINT32)0x7ea05 << SeedCount) & 0x7FFFF;
1657 ASSERT (PrbsSeed != 0);
1661 /* -----------------------------------------------------------------------------*/
1664 * This function enables/disables continuous writes on unused agressor channels
1665 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1666 * @param[in] SeedCount - Seed count
1667 * @param[in] TurnOnInfinite - TRUE - Enable Infinite Mode
1668 * TurnOnInfinite - FALSE - Disable Infinite Mode
1672 MemNAgressorContinuousWritesUnb (
1673 IN OUT MEM_NB_BLOCK *NBPtr,
1675 IN BOOLEAN TurnOnInfinite
1683 MEM_NB_BLOCK *TargetNBPtr;
1684 BOOLEAN SkipContinuous;
1685 CurrDct = NBPtr->Dct;
1686 CurrChipSel = NBPtr->TechPtr->ChipSel;
1687 SkipContinuous = FALSE;
1688 for (Die = 0; Die < NBPtr->NodeCount; Die++) {
1689 if (NBPtr->DieEnabled[Die]) {
1690 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
1691 // Make sure that we are not targeting current DCT, current Node
1692 if (Die == NBPtr->Node) {
1693 if (CurrDct == Dct) {
1694 SkipContinuous = TRUE;
1696 SkipContinuous = FALSE;
1699 SkipContinuous = FALSE;
1701 // Enable/Disable continuous on aggressors
1702 if (SkipContinuous == FALSE) {
1703 if (Die == NBPtr->Node) {
1704 TargetNBPtr = NBPtr;
1706 ASSERT (NBPtr->AdjacentDieNBPtr != NULL);
1707 TargetNBPtr = NBPtr->AdjacentDieNBPtr;
1709 // All context switched at this point
1710 TargetNBPtr->SwitchDCT (TargetNBPtr, Dct);
1711 if (TargetNBPtr->DCTPtr->Timings.DctMemSize != 0) {
1712 // Set Targets for agressors
1713 TargetNBPtr->TechPtr->ChipSel = TargetNBPtr->CurrentAggressorCSTarget[Dct];
1714 TargetNBPtr->GetSysAddr (TargetNBPtr, TargetNBPtr->TechPtr->ChipSel, &Address);
1715 TargetNBPtr->RrwSettings.DataPrbsSeed = TargetNBPtr->GetPrbs__RdDqsSeed (TargetNBPtr, 0);
1716 if (TurnOnInfinite) {
1717 // Enable continuous writes on aggressor channels
1718 TargetNBPtr->EnableInfiniteWritePattern (TargetNBPtr);
1720 // Disable continous writes on aggressor channels
1721 TargetNBPtr->DisableInfiniteWritePattern (TargetNBPtr);
1722 // Set the next target CS for aggressor channel
1723 if (TargetNBPtr->CurrentAggressorCSTarget[Dct] == TargetNBPtr->MaxAggressorCSEnabled[Dct]) {
1724 TargetNBPtr->CurrentAggressorCSTarget[Dct] = TargetNBPtr->InitialAggressorCSTarget[Dct];
1726 TargetNBPtr->CurrentAggressorCSTarget[Dct] = TargetNBPtr->CurrentAggressorCSTarget[Dct] + TargetNBPtr->CSPerDelay (TargetNBPtr);
1734 // Restore Node, DCT and ChipSel
1735 NBPtr->TechPtr->ChipSel = CurrChipSel;
1736 NBPtr->SwitchDCT (NBPtr, CurrDct);