7 * Common Northbridge features
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/NB)
12 * @e \$Revision: 38442 $ @e \$Date: 2010-09-24 06:39:57 +0800 (Fri, 24 Sep 2010) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * ***************************************************************************
48 *----------------------------------------------------------------------------
51 *----------------------------------------------------------------------------
55 #include "AdvancedApi.h"
58 #include "OptionMemory.h"
62 #include "PlatformMemoryConfiguration.h"
66 RDATA_GROUP (G1_PEICC)
68 #define FILECODE PROC_MEM_NB_MNFEAT_FILECODE
69 /*----------------------------------------------------------------------------
70 * DEFINITIONS AND MACROS
72 *----------------------------------------------------------------------------
74 #define MAX_CL_CONT_READ 32
75 #define MAX_CL_CONT_WRITE 32
77 /*----------------------------------------------------------------------------
78 * TYPEDEFS AND STRUCTURES
80 *----------------------------------------------------------------------------
83 /*----------------------------------------------------------------------------
84 * PROTOTYPES OF LOCAL FUNCTIONS
86 *----------------------------------------------------------------------------
91 MemNContWritePatternNb (
92 IN OUT MEM_NB_BLOCK *NBPtr,
100 MemNContReadPatternNb (
101 IN OUT MEM_NB_BLOCK *NBPtr,
109 MemNGenHwRcvEnReadsNb (
110 IN OUT MEM_NB_BLOCK *NBPtr,
116 MemNCompareTestPatternClientNb (
117 IN OUT MEM_NB_BLOCK *NBPtr,
125 MemNInsDlyCompareTestPatternClientNb (
126 IN OUT MEM_NB_BLOCK *NBPtr,
134 MemNContWritePatternClientNb (
135 IN OUT MEM_NB_BLOCK *NBPtr,
143 MemNContReadPatternClientNb (
144 IN OUT MEM_NB_BLOCK *NBPtr,
152 MemNGenHwRcvEnReadsClientNb (
153 IN OUT MEM_NB_BLOCK *NBPtr,
159 MemNBeforeMemClrClientNb (
160 IN OUT MEM_NB_BLOCK *NBPtr,
166 MemNGenHwRcvEnReadsUnb (
167 IN OUT MEM_NB_BLOCK *NBPtr,
174 IN OUT MEM_NB_BLOCK *NBPtr,
182 MemNRrwPrechargeCmd (
183 IN OUT MEM_NB_BLOCK *NBPtr,
190 MemNContReadPatternUnb (
191 IN OUT MEM_NB_BLOCK *NBPtr,
199 MemNContWritePatternUnb (
200 IN OUT MEM_NB_BLOCK *NBPtr,
206 /*----------------------------------------------------------------------------
209 *----------------------------------------------------------------------------
212 /* -----------------------------------------------------------------------------*/
215 * This function assigns read/write function pointers to CPG read/write modules.
217 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
222 IN OUT MEM_NB_BLOCK *NBPtr
225 NBPtr->WritePattern = MemNContWritePatternNb;
226 NBPtr->ReadPattern = MemNContReadPatternNb;
227 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
230 /* -----------------------------------------------------------------------------*/
233 * This function initializes member functions of HW Rx En Training.
235 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
240 MemNInitDqsTrainRcvrEnHwNb (
241 IN OUT MEM_NB_BLOCK *NBPtr
244 NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
246 /* -----------------------------------------------------------------------------*/
249 * This function disables member functions of Hw Rx En Training.
251 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
256 MemNDisableDqsTrainRcvrEnHwNb (
257 IN OUT MEM_NB_BLOCK *NBPtr
260 NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
263 /*----------------------------------------------------------------------------
266 *----------------------------------------------------------------------------
269 /* -----------------------------------------------------------------------------*/
272 * This function writes 9 or 18 cache lines continuously using GH CPG engine
274 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
275 * @param[in] Pattern - Array of bytes that will be written to DRAM
276 * @param[in] Address - System Address [47:16]
277 * @param[in] ClCount - Number of cache lines
282 MemNContWritePatternNb (
283 IN OUT MEM_NB_BLOCK *NBPtr,
290 if (ClCount > MAX_CL_CONT_WRITE) {
291 ClDiff = ClCount - MAX_CL_CONT_WRITE;
292 ClCount = MAX_CL_CONT_WRITE;
297 // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
298 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
300 // Issue the stream of writes. When F2x11C[MctWrLimit] is reached (or when F2x11C[FlushWr] is set
301 // again), all the writes are written to DRAM.
302 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
303 MemUWriteCachelines (Address, Pattern, ClCount);
305 // Flush out prior writes by setting F2x11C[FlushWr].
306 MemNSetBitFieldNb (NBPtr, BFFlushWr, 1);
307 // Wait for F2x11C[FlushWr] to clear, indicating prior writes have been flushed.
308 while (MemNGetBitFieldNb (NBPtr, BFFlushWr) != 0) {}
310 // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
311 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
314 MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
318 /* -----------------------------------------------------------------------------*/
322 * This function reads 9 or 18 cache lines continuously using GH CPG engine
324 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
325 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
326 * @param[in] Address - System Address [47:16]
327 * @param[in] ClCount - Number of cache lines
333 MemNContReadPatternNb (
334 IN OUT MEM_NB_BLOCK *NBPtr,
340 BOOLEAN DisAutoRefresh;
342 if (ClCount > MAX_CL_CONT_READ) {
343 ClDiff = ClCount - MAX_CL_CONT_READ;
344 ClCount = MAX_CL_CONT_READ;
349 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
351 // 1. BIOS ensures that the only accesses outstanding to the MCT are training reads.
352 // 2. If F2x[1, 0]90[BurstLength32]=1, then BIOS ensures that the DCTs and DRAMs are configured for 64
353 // byte bursts (8-beat burst length). This requires that BIOS issue MRS commands to the devices
354 // to change to an 8-beat burst length and then to restore the desired burst length after training
357 if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
358 DisAutoRefresh = FALSE;
359 // 3. BIOS programs F2x[1, 0]90[ForceAutoPchg] = 0 and F2x[1, 0]8C[DisAutoRefresh] = 1.
360 // 4. If necessary, BIOS programs F2x[1, 0]78[EarlyArbEn] = 1 at this time. See register description.
361 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
362 // MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0); // ForceAutoPchg is 0 by default.
363 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
365 DisAutoRefresh = TRUE;
368 MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
370 // 5. BIOS sets F2x11C[MctPrefReqLimit] to the number of training reads (Ntrain) it wishes to generate in the
371 // training sequence.
372 MemNSetBitFieldNb (NBPtr, BFMctPrefReqLimit, ClCount - 1);
374 // 6. BIOS sets F2x11C[PrefDramTrainMode] bit.
375 // 7. The act of setting F2x11C[PrefDramTrainMode] causes the MCT to flush out the prefetch stride predictor
376 // table (removing any existing prefetch stride patterns).
377 MemNSetBitFieldNb (NBPtr, BFPrefDramTrainMode, 1);
379 // 8. BIOS issues an SFENCE (or other serializing instruction) to ensure that the prior write completes.
380 // 9. For revision C and earlier processors, BIOS generates two training reads. For revision D processors BIOS
381 // generates three training reads. Three are required to detect the stride with DCQ buddy enabled. These must
382 // be to consecutive cache lines (i.e. 64 bytes apart) and must not cross a naturally aligned 4 Kbyte boundary.
383 // 10. These reads set up a stride pattern which is detected by the prefetcher. The prefetcher then continues to
384 // issue prefetches until F2x11C[MctPrefReqLimit] is reached, at which point the MCT clears
385 // F2x11C[PrefDramTrainMode].
386 MemUDummyCLRead (Address);
387 MemUDummyCLRead (Address + 0x40);
388 if (NBPtr->IsSupported[CheckDummyCLRead]) {
389 MemUDummyCLRead (Address + 0x80);
391 // 11. BIOS issues the remaining (Ntrain - 2 for revisions C and earlier or Ntrain - 3 for revision D) reads after
392 // checking that F2x11C[PrefDramTrainMode] is cleared. These reads must be to consecutive cache lines
393 // (i.e., 64 bytes apart) and must not cross a naturally aligned 4KB boundary. These reads hit the prefetches
394 // and read the data from the prefetch buffer.
395 while (MemNGetBitFieldNb (NBPtr, BFPrefDramTrainMode) != 0) {}
396 MemUReadCachelines (Buffer, Address, ClCount);
398 // 14. BIOS restores the target values for F2x[1, 0]90[ForceAutoPchg], F2x[1, 0]8C[DisAutoRefresh] and
399 // F2x[1, 0]90[BurstLength32].
400 if (!DisAutoRefresh) {
401 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
402 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
406 MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
410 /* -----------------------------------------------------------------------------*/
414 * This function generates a continuous burst of reads during HW RcvEn training.
416 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
417 * @param[in] Address - System Address [47:16]
422 MemNGenHwRcvEnReadsNb (
423 IN OUT MEM_NB_BLOCK *NBPtr,
427 UINT8 TempBuffer[12 * 64];
430 for (BurstCount = 0; BurstCount < 10; BurstCount++) {
431 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
432 NBPtr->FlushPattern (NBPtr, Address, 12);
436 /* -----------------------------------------------------------------------------*/
439 * This function writes cache lines continuously using TCB CPG engine
441 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
442 * @param[in] Pattern - Array of bytes that will be written to DRAM
443 * @param[in] Address - System Address [47:16]
444 * @param[in] ClCount - Number of cache lines
449 MemNContWritePatternClientNb (
450 IN OUT MEM_NB_BLOCK *NBPtr,
464 // 1. Program D18F2x1C0[WrDramTrainMode]=1.
465 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
467 PatternHash = ClCount << 24;
468 for (i = 0; i < 3; i ++) {
469 PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
471 if (NBPtr->CPGInit != PatternHash) {
474 // Double pattern length for MaxRdLat training
478 // If write training buffer has not been initialized, initialize it
479 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
480 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
482 // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
483 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
485 // 4. Successively write each dword of the training pattern to D18F2x1D4.
486 DwordPtr = (UINT32 *) Pattern;
487 for (j = 0; j < Multiplier; j++) {
488 for (i = 0; i < (ClCount * 16); i++) {
489 MemNSetBitFieldNb (NBPtr, BFWrTrainBufDat, DwordPtr[i]);
493 NBPtr->CPGInit = PatternHash;
496 // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
497 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
499 // 6. Program the DRAM training address
500 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
501 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
503 // 7. Program D18F2x1C0[WrTrainGo]=1.
504 MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
506 // 8. Wait for D18F2x1C0[WrTrainGo]=0.
507 while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
509 // 9. Program D18F2x1C0[WrDramTrainMode]=0.
510 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
513 /* -----------------------------------------------------------------------------*/
517 * This function reads cache lines continuously using TCB CPG engine
519 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
520 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
521 * @param[in] Address - System Address [47:16]
522 * @param[in] ClCount - Number of cache lines
528 MemNContReadPatternClientNb (
529 IN OUT MEM_NB_BLOCK *NBPtr,
539 // Double pattern length for MaxRdLat training
543 // 1. Program D18F2x1C0[RdDramTrainMode]=1.
544 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
546 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
547 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
549 // 3. Program the DRAM training address as follows:
550 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
551 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
553 // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
554 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
556 // 5. Program D18F2x1C0[RdTrainGo]=1.
557 MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
559 // 6. Wait for D18F2x1C0[RdTrainGo]=0.
560 while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
562 // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
563 // This step will be accomplished in Compare routine.
565 // 8. Program D18F2x1C0[RdDramTrainMode]=0.
566 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
569 /* -----------------------------------------------------------------------------*/
573 * This function generates a continuous burst of reads during HW RcvEn training.
575 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
576 * @param[in] Address - System Address [47:16]
581 MemNGenHwRcvEnReadsClientNb (
582 IN OUT MEM_NB_BLOCK *NBPtr,
586 UINT8 TempBuffer[64];
589 for (Count = 0; Count < 3; Count++) {
590 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
594 /* -----------------------------------------------------------------------------*/
597 * This function assigns read/write function pointers to CPG read/write modules.
599 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
603 MemNInitCPGClientNb (
604 IN OUT MEM_NB_BLOCK *NBPtr
607 NBPtr->WritePattern = MemNContWritePatternClientNb;
608 NBPtr->ReadPattern = MemNContReadPatternClientNb;
609 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsClientNb;
610 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
611 NBPtr->CompareTestPattern = MemNCompareTestPatternClientNb;
612 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternClientNb;
613 NBPtr->FamilySpecificHook[BeforeMemClr] = MemNBeforeMemClrClientNb;
617 /* -----------------------------------------------------------------------------*/
620 * This function compares test pattern with data in buffer and
621 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
623 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
624 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
625 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
626 * @param[in] ByteCount - Byte count
628 * @return PASS - Bitmap of results of comparison
633 MemNCompareTestPatternClientNb (
634 IN OUT MEM_NB_BLOCK *NBPtr,
640 return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts));
643 /*-----------------------------------------------------------------------------*/
646 * This function compares test pattern with data in buffer and
647 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
649 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
650 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
651 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
652 * @param[in] ByteCount - Byte count
654 * @retval Bitmap of results of comparison
658 MemNInsDlyCompareTestPatternClientNb (
659 IN OUT MEM_NB_BLOCK *NBPtr,
665 return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
668 /* -----------------------------------------------------------------------------*/
671 * This function calculates RcvEn seed value for each rank
673 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
677 MemNPrepareRcvrEnDlySeedNb (
678 IN OUT MEM_NB_BLOCK *NBPtr
681 MEM_TECH_BLOCK *TechPtr;
682 CH_DEF_STRUCT *ChannelPtr;
688 UINT16 SeedTotalPreScaling;
699 TechPtr = NBPtr->TechPtr;
700 MCTPtr = NBPtr->MCTPtr;
701 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
702 Speed = NBPtr->DCTPtr->Timings.Speed;
703 SeedTotalPreScaling = 0;
704 ChipSel = TechPtr->ChipSel;
705 Pass = TechPtr->Pass;
707 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
708 TechPtr->Bytelane = ByteLane;
710 // Get platform override seed
711 PlatEstSeed = (UINT16 *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, MCTPtr->SocketId, ChannelPtr->ChannelID);
712 // For Pass1, BIOS starts with the delay value obtained from the first pass of write
713 // levelization training that was done in DDR3 Training and add a delay value of 3Bh.
715 NBPtr->FamilySpecificHook[OverrideRcvEnSeed] (NBPtr, &PlatEst);
716 PlatEst = ((PlatEstSeed != NULL) ? PlatEstSeed[ByteLane] : PlatEst);
717 SeedTotal = ChannelPtr->WrDqsDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane] + PlatEst;
718 SeedValue[ByteLane] = PlatEst;
721 // SeedTotalPreScaling = (the total delay values in D18F2x[1,0]9C_x0000_00[24:10] from pass 1 of
722 // DQS receiver enable training) - 20h. Subtract 1UI to get back to preamble left edge.
723 if ((ChipSel & 1) == 0) {
724 // Save Seed for odd CS SeedTotalPreScaling RxEn Value
725 TechPtr->PrevPassRcvEnDly[ByteLane] = ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane];
727 SeedTotalPreScaling = TechPtr->PrevPassRcvEnDly[ByteLane] - 0x20;
728 // SeedTotal = SeedTotalPreScaling*target frequency/lowest supported frequency.
729 SeedTotal = (UINT16) (((UINT32) SeedTotalPreScaling * Speed) / TechPtr->PrevSpeed);
730 NBPtr->FamilySpecificHook[OverrideRcvEnSeedPassN] (NBPtr, &SeedTotal);
732 SeedTtl[ByteLane] = SeedTotal;
734 // SeedGross = SeedTotal DIV 32.
735 SeedGross = SeedTotal >> 5;
736 // SeedFine = SeedTotal MOD 32.
737 SeedFine = SeedTotal & 0x1F;
738 // Next, determine the gross component of SeedTotal. SeedGrossPass1=SeedTotal DIV 32.
739 // Then, determine the fine delay component of SeedTotal. SeedFinePass1=SeedTotal MOD 32.
740 // Use SeedGrossPass1 to determine SeedPreGrossPass1:
742 if ((SeedGross & 0x1) != 0) {
743 //if SeedGross is odd
746 //if SeedGross is even
749 // (SeedGross - SeedPreGross)
750 TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
752 //BIOS programs registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 with SeedPreGrossPass1
753 //and SeedFinePass1 from the preceding steps.
755 NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
756 SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
758 // 202688: Program seed value to RcvEnDly also.
759 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
762 IDS_HDT_CONSOLE_DEBUG_CODE (
764 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
765 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
766 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedValue[ByteLane]);
768 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
770 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedTotal: ");
771 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
772 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
774 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
775 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
776 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
778 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
782 /* -----------------------------------------------------------------------------*/
785 * Waits specified number of MEMCLKs
786 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
787 * @param[in] MemClkCount - Number of MEMCLKs
789 * ----------------------------------------------------------------------------
793 IN OUT MEM_NB_BLOCK *NBPtr,
794 IN UINT32 MemClkCount
797 MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
800 /* -----------------------------------------------------------------------------*/
803 * Issues dummy TCB write read to zero out CL that is used for MemClr
804 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
805 * @param[in,out] *UnUsed - unused
807 * ----------------------------------------------------------------------------
811 MemNBeforeMemClrClientNb (
812 IN OUT MEM_NB_BLOCK *NBPtr,
819 for (i = 0; i < 64; i++) {
823 MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
824 MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
828 /* -----------------------------------------------------------------------------*/
831 * This function uses the PRBS generator in the DCT to send a DDR Activate command
833 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
834 * @param[in] ChipSelect - Chip select 0-7
835 * @param[in] Bank - Bank Address 0-7
836 * @param[in] RowAddress - Row Address [17:0]
843 IN OUT MEM_NB_BLOCK *NBPtr,
850 MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
852 MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
854 MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
856 MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
857 // Wait for command complete
858 MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
860 NBPtr->WaitXMemClks (NBPtr, 75);
863 /* -----------------------------------------------------------------------------*/
866 * This function uses the PRBS generator in the DCT to send a DDR Precharge
867 * or Precharge All command
869 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
870 * @param[in] ChipSelect - Chip select 0-7
871 * @param[in] Bank - Bank Address 0-7, PRECHARGE_ALL_BANKS = Precharge All
878 MemNRrwPrechargeCmd (
879 IN OUT MEM_NB_BLOCK *NBPtr,
885 NBPtr->WaitXMemClks (NBPtr, 25);
887 NBPtr->SetBitField (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
888 if (Bank == PRECHARGE_ALL_BANKS) {
889 // Set Row Address, bit 10
890 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) | (1 << 10) );
892 // Clear Row Address, bit 10
893 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
895 NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
898 NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
899 // Wait for command complete
900 NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
902 NBPtr->WaitXMemClks (NBPtr, 25);
904 /* -----------------------------------------------------------------------------*/
908 * This function generates a continuous burst of reads for HW RcvEn
909 * training using the Unified Northbridge Reliable Read/Write Engine.
911 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
912 * @param[in] Address - Unused by this function
917 MemNGenHwRcvEnReadsUnb (
918 IN OUT MEM_NB_BLOCK *NBPtr,
925 // Issue Stream of Reads from the Target Rank
927 NBPtr->ReadPattern (NBPtr, DummyPtr, NULL, NBPtr->TechPtr->PatternLength);
930 /* -----------------------------------------------------------------------------*/
933 * This function generates a continuous stream of reads from DRAM using the
934 * Unified Northbridge Reliable Read/Write Engine.
936 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
937 * @param[in,out] Buffer - Unused by this function
938 * @param[in] Address - Unused by this function
939 * @param[in] ClCount - Number of cache lines to read
949 MemNContReadPatternUnb (
950 IN OUT MEM_NB_BLOCK *NBPtr,
956 MEM_TECH_BLOCK *TechPtr;
961 TechPtr = NBPtr->TechPtr;
962 Rrw = &NBPtr->RrwSettings;
964 ChipSel = TechPtr->ChipSel;
965 CmdTgt = Rrw->CmdTgt;
967 // Wait for RRW Engine to be ready and turn it on
969 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
970 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
972 // Depending upon the Cmd Target, send Row Activate and set Chipselect
973 // for the Row or Rows that will be used
975 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
976 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
977 if (CmdTgt == CMD_TGT_AB) {
978 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
979 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
981 // Set Comparison Masks
982 NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
983 NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
985 // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
987 NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
989 // Program the PRBS Seed
991 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
993 // Set the Command Count
995 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
997 // Program the Bubble Count and CmdStreamLen
999 NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1000 NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1001 NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1003 // Program the Starting Address
1005 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1006 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1007 if (CmdTgt == CMD_TGT_AB) {
1008 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1009 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1012 // Reset All Errors and Disable StopOnErr
1014 NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1015 NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
1017 // Program the CmdTarget
1019 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1021 // Set CmdType to read
1023 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1025 // Start the Commands
1027 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1029 // Commands have started, wait for the reads to complete then clear the command
1031 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1032 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1033 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1035 // Send the Precharge All Command
1037 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1039 // Turn Off the RRW Engine
1041 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1044 /* -----------------------------------------------------------------------------*/
1047 * This function generates a continuous stream of writes to DRAM using the
1048 * Unified Northbridge Reliable Read/Write Engine.
1050 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1051 * @param[in,out] Address - Unused by this function
1052 * @param[in] Pattern - Unused by this function
1053 * @param[in] ClCount - Number of cache lines to write
1059 MemNContWritePatternUnb (
1060 IN OUT MEM_NB_BLOCK *NBPtr,
1066 MEM_TECH_BLOCK *TechPtr;
1071 TechPtr = NBPtr->TechPtr;
1072 Rrw = &NBPtr->RrwSettings;
1074 ChipSel = TechPtr->ChipSel;
1075 CmdTgt = Rrw->CmdTgt;
1077 // Wait for RRW Engine to be ready and turn it on
1079 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1080 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1083 // Depending upon the Cmd Target, send Row Activate and set Chipselect
1084 // for the Row or Rows that will be used
1086 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1087 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1088 if (CmdTgt == CMD_TGT_AB) {
1089 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
1090 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
1093 // Program the PRBS Seed
1095 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1097 // Set the Command Count
1099 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1101 // Program the Bubble Count and CmdStreamLen
1103 NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1104 NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1105 NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1107 // Program the Starting Address
1109 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1110 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1111 if (CmdTgt == CMD_TGT_AB) {
1112 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1113 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1116 // Program the CmdTarget
1118 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1120 // Set CmdType to read
1122 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1124 // Start the Commands
1126 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1128 // Commands have started, wait for the writes to complete then clear the command
1130 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1131 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1132 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1134 // Send the Precharge All Command
1136 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1138 // Turn Off the RRW Engine
1140 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1143 /* -----------------------------------------------------------------------------*/
1146 * This function checks the Error status bits for comparison results
1148 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1149 * @param[in] Buffer[] - Not used in this implementation
1150 * @param[in] Pattern[] - Not used in this implementation
1151 * @param[in] ByteCount - Not used in this implementation
1153 * @return PASS - Bitmap of results of comparison
1158 MemNCompareTestPatternUnb (
1159 IN OUT MEM_NB_BLOCK *NBPtr,
1171 UINT8* FailingBitMaskPtr;
1172 UINT8 FailingBitMask[9];
1173 UINT32 NibbleErrSts;
1175 ChipSel = NBPtr->TechPtr->ChipSel;
1176 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1177 // Calculate Failing Bitmask pointer
1178 FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
1181 // Get Failing bit data
1183 *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
1184 *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
1185 FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
1189 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1191 NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1193 for (i = 0; i < ColumnCount ; i++) {
1194 Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
1196 FailingBitMaskPtr[i] = FailingBitMask[i];
1202 /*-----------------------------------------------------------------------------*/
1205 * This function checks the Error status bits for offset comparison results
1207 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1208 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
1209 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
1210 * @param[in] ByteCount - Byte count
1212 * @retval Bitmap of results of comparison
1216 MemNInsDlyCompareTestPatternUnb (
1217 IN OUT MEM_NB_BLOCK *NBPtr,
1226 UINT32 NibbleErr180Sts;
1228 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1231 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1233 NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1235 for (i = 0; i < ColumnCount ; i++) {
1236 Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
1237 NibbleErr180Sts >>= 2;
1244 /* -----------------------------------------------------------------------------*/
1247 * This function assigns read/write function pointers to CPG read/write modules.
1249 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1254 IN OUT MEM_NB_BLOCK *NBPtr
1257 NBPtr->WritePattern = MemNContWritePatternUnb;
1258 NBPtr->ReadPattern = MemNContReadPatternUnb;
1259 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsUnb;
1260 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
1261 NBPtr->TrainingPatternInit = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1262 NBPtr->TrainingPatternFinalize = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1263 NBPtr->CompareTestPattern = MemNCompareTestPatternUnb;
1264 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternUnb;
1265 NBPtr->FamilySpecificHook[SetupHwTrainingEngine] = MemNSetupHwTrainingEngineUnb;