0779531ac4cd5b6a1978890dfda82cc10035ae76
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / Mem / NB / mnfeat.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mnfeat.c
6  *
7  * Common Northbridge features
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/NB)
12  * @e \$Revision: 38442 $ @e \$Date: 2010-09-24 06:39:57 +0800 (Fri, 24 Sep 2010) $
13  *
14  **/
15 /*
16  *****************************************************************************
17  *
18  * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
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.
31  * 
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.
42  * 
43  * ***************************************************************************
44  *
45  */
46
47 /*
48  *----------------------------------------------------------------------------
49  *                                MODULES USED
50  *
51  *----------------------------------------------------------------------------
52  */
53
54 #include "AGESA.h"
55 #include "AdvancedApi.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "OptionMemory.h"
59 #include "mm.h"
60 #include "mn.h"
61 #include "mu.h"
62 #include "PlatformMemoryConfiguration.h"
63 #include "merrhdl.h"
64 #include "Filecode.h"
65 CODE_GROUP (G1_PEICC)
66 RDATA_GROUP (G1_PEICC)
67
68 #define FILECODE PROC_MEM_NB_MNFEAT_FILECODE
69 /*----------------------------------------------------------------------------
70  *                          DEFINITIONS AND MACROS
71  *
72  *----------------------------------------------------------------------------
73  */
74 #define MAX_CL_CONT_READ  32
75 #define MAX_CL_CONT_WRITE 32
76
77 /*----------------------------------------------------------------------------
78  *                           TYPEDEFS AND STRUCTURES
79  *
80  *----------------------------------------------------------------------------
81  */
82
83 /*----------------------------------------------------------------------------
84  *                        PROTOTYPES OF LOCAL FUNCTIONS
85  *
86  *----------------------------------------------------------------------------
87  */
88
89 VOID
90 STATIC
91 MemNContWritePatternNb (
92   IN OUT   MEM_NB_BLOCK *NBPtr,
93   IN       UINT32 Address,
94   IN       UINT8 Pattern[],
95   IN       UINT16 ClCount
96   );
97
98 VOID
99 STATIC
100 MemNContReadPatternNb (
101   IN OUT   MEM_NB_BLOCK *NBPtr,
102   IN       UINT8 Buffer[],
103   IN       UINT32 Address,
104   IN       UINT16 ClCount
105   );
106
107 VOID
108 STATIC
109 MemNGenHwRcvEnReadsNb (
110   IN OUT   MEM_NB_BLOCK *NBPtr,
111   IN       UINT32 Address
112   );
113
114 UINT16
115 STATIC
116 MemNCompareTestPatternClientNb (
117   IN OUT   MEM_NB_BLOCK *NBPtr,
118   IN       UINT8 Buffer[],
119   IN       UINT8 Pattern[],
120   IN       UINT16 ByteCount
121   );
122
123 UINT16
124 STATIC
125 MemNInsDlyCompareTestPatternClientNb (
126   IN OUT   MEM_NB_BLOCK *NBPtr,
127   IN       UINT8 Buffer[],
128   IN       UINT8 Pattern[],
129   IN       UINT16 ByteCount
130   );
131
132 VOID
133 STATIC
134 MemNContWritePatternClientNb (
135   IN OUT   MEM_NB_BLOCK *NBPtr,
136   IN       UINT32 Address,
137   IN       UINT8 Pattern[],
138   IN       UINT16 ClCount
139   );
140
141 VOID
142 STATIC
143 MemNContReadPatternClientNb (
144   IN OUT   MEM_NB_BLOCK *NBPtr,
145   IN       UINT8 Buffer[],
146   IN       UINT32 Address,
147   IN       UINT16 ClCount
148   );
149
150 VOID
151 STATIC
152 MemNGenHwRcvEnReadsClientNb (
153   IN OUT   MEM_NB_BLOCK *NBPtr,
154   IN       UINT32 Address
155   );
156
157 BOOLEAN
158 STATIC
159 MemNBeforeMemClrClientNb (
160   IN OUT   MEM_NB_BLOCK  *NBPtr,
161   IN       VOID *UnUsed
162   );
163
164 VOID
165 STATIC
166 MemNGenHwRcvEnReadsUnb (
167   IN OUT   MEM_NB_BLOCK *NBPtr,
168   IN       UINT32 Address
169   );
170
171 VOID
172 STATIC
173 MemNRrwActivateCmd (
174   IN OUT   MEM_NB_BLOCK *NBPtr,
175   IN       UINT8 ChipSelect,
176   IN       UINT8 Bank,
177   IN       UINT32 RowAddress
178   );
179
180 VOID
181 STATIC
182 MemNRrwPrechargeCmd (
183   IN OUT   MEM_NB_BLOCK *NBPtr,
184   IN       UINT8 ChipSelect,
185   IN       UINT8 Bank
186   );
187
188 VOID
189 STATIC
190 MemNContReadPatternUnb (
191   IN OUT   MEM_NB_BLOCK *NBPtr,
192   IN       UINT8 Buffer[],
193   IN       UINT32 Address,
194   IN       UINT16 ClCount
195   );
196
197 VOID
198 STATIC
199 MemNContWritePatternUnb (
200   IN OUT   MEM_NB_BLOCK *NBPtr,
201   IN       UINT32 Address,
202   IN       UINT8 Pattern[],
203   IN       UINT16 ClCount
204   );
205
206 /*----------------------------------------------------------------------------
207  *                            EXPORTED FUNCTIONS
208  *
209  *----------------------------------------------------------------------------
210  */
211
212 /* -----------------------------------------------------------------------------*/
213 /**
214  *
215  *      This function assigns read/write function pointers to CPG read/write modules.
216  *
217  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
218  *
219  */
220 VOID
221 MemNInitCPGNb (
222   IN OUT   MEM_NB_BLOCK *NBPtr
223   )
224 {
225   NBPtr->WritePattern = MemNContWritePatternNb;
226   NBPtr->ReadPattern = MemNContReadPatternNb;
227   NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
228 }
229
230 /* -----------------------------------------------------------------------------*/
231 /**
232  *
233  *   This function initializes member functions of HW Rx En Training.
234  *
235  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
236  *
237  */
238
239 VOID
240 MemNInitDqsTrainRcvrEnHwNb (
241   IN OUT   MEM_NB_BLOCK *NBPtr
242   )
243 {
244   NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
245 }
246 /* -----------------------------------------------------------------------------*/
247 /**
248  *
249  *   This function disables member functions of Hw Rx En Training.
250  *
251  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
252  *
253  */
254
255 VOID
256 MemNDisableDqsTrainRcvrEnHwNb (
257   IN OUT   MEM_NB_BLOCK *NBPtr
258   )
259 {
260   NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
261 }
262
263 /*----------------------------------------------------------------------------
264  *                              LOCAL FUNCTIONS
265  *
266  *----------------------------------------------------------------------------
267  */
268
269 /* -----------------------------------------------------------------------------*/
270 /**
271  *
272  *      This function writes 9 or 18 cache lines continuously using GH CPG engine
273  *
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
278  *
279  */
280 VOID
281 STATIC
282 MemNContWritePatternNb (
283   IN OUT   MEM_NB_BLOCK *NBPtr,
284   IN       UINT32 Address,
285   IN       UINT8 Pattern[],
286   IN       UINT16 ClCount
287   )
288 {
289   UINT16 ClDiff;
290   if (ClCount > MAX_CL_CONT_WRITE) {
291     ClDiff = ClCount - MAX_CL_CONT_WRITE;
292     ClCount = MAX_CL_CONT_WRITE;
293   } else {
294     ClDiff = 0;
295   }
296
297   // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
298   MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
299
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);
304
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) {}
309
310   // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
311   MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
312
313   if (ClDiff > 0) {
314     MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
315   }
316 }
317
318 /* -----------------------------------------------------------------------------*/
319 /**
320  *
321  *
322  *      This function reads 9 or 18 cache lines continuously using GH CPG engine
323  *
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
328  *
329  */
330
331 VOID
332 STATIC
333 MemNContReadPatternNb (
334   IN OUT   MEM_NB_BLOCK *NBPtr,
335   IN       UINT8 Buffer[],
336   IN       UINT32 Address,
337   IN       UINT16 ClCount
338   )
339 {
340   BOOLEAN DisAutoRefresh;
341   UINT16 ClDiff;
342   if (ClCount > MAX_CL_CONT_READ) {
343     ClDiff = ClCount - MAX_CL_CONT_READ;
344     ClCount = MAX_CL_CONT_READ;
345   } else {
346     ClDiff = 0;
347   }
348
349   Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
350
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
355   // is complete.
356
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);
364   } else {
365     DisAutoRefresh = TRUE;
366   }
367
368   MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
369
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);
373
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);
378
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);
390   }
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);
397
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);
403   }
404
405   if (ClDiff > 0) {
406     MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
407   }
408 }
409
410 /* -----------------------------------------------------------------------------*/
411 /**
412  *
413  *
414  *      This function generates a continuous burst of reads during HW RcvEn training.
415  *
416  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
417  *     @param[in]     Address - System Address [47:16]
418  *
419  */
420 VOID
421 STATIC
422 MemNGenHwRcvEnReadsNb (
423   IN OUT   MEM_NB_BLOCK *NBPtr,
424   IN       UINT32 Address
425   )
426 {
427   UINT8  TempBuffer[12 * 64];
428   UINT8  BurstCount;
429
430   for (BurstCount = 0; BurstCount < 10; BurstCount++) {
431     NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
432     NBPtr->FlushPattern (NBPtr, Address, 12);
433   }
434 }
435
436 /* -----------------------------------------------------------------------------*/
437 /**
438  *
439  *      This function writes cache lines continuously using TCB CPG engine
440  *
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
445  *
446  */
447 VOID
448 STATIC
449 MemNContWritePatternClientNb (
450   IN OUT   MEM_NB_BLOCK *NBPtr,
451   IN       UINT32 Address,
452   IN       UINT8 Pattern[],
453   IN       UINT16 ClCount
454   )
455 {
456   UINT32 PatternHash;
457   UINT32 *DwordPtr;
458   UINT16 i;
459   UINT16 j;
460   UINT16 Multiplier;
461
462   Multiplier = 1;
463
464   // 1. Program D18F2x1C0[WrDramTrainMode]=1.
465   MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
466
467   PatternHash = ClCount << 24;
468   for (i = 0; i < 3; i ++) {
469     PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
470   }
471   if (NBPtr->CPGInit != PatternHash) {
472
473     if (ClCount == 3) {
474       // Double pattern length for MaxRdLat training
475       Multiplier = 2;
476     }
477
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);
481
482     // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
483     MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
484
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]);
490       }
491     }
492
493     NBPtr->CPGInit = PatternHash;
494   }
495
496   // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
497   MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
498
499   // 6. Program the DRAM training address
500   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
501   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
502
503   // 7. Program D18F2x1C0[WrTrainGo]=1.
504   MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
505
506   // 8. Wait for D18F2x1C0[WrTrainGo]=0.
507   while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
508
509   // 9. Program D18F2x1C0[WrDramTrainMode]=0.
510   MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
511 }
512
513 /* -----------------------------------------------------------------------------*/
514 /**
515  *
516  *
517  *      This function reads cache lines continuously using TCB CPG engine
518  *
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
523  *
524  */
525
526 VOID
527 STATIC
528 MemNContReadPatternClientNb (
529   IN OUT   MEM_NB_BLOCK *NBPtr,
530   IN       UINT8 Buffer[],
531   IN       UINT32 Address,
532   IN       UINT16 ClCount
533   )
534 {
535   UINT16 Multiplier;
536
537   Multiplier = 1;
538   if (ClCount == 3) {
539     // Double pattern length for MaxRdLat training
540     Multiplier = 2;
541   }
542
543   // 1. Program D18F2x1C0[RdDramTrainMode]=1.
544   MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
545
546   // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
547   MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
548
549   // 3. Program the DRAM training address as follows:
550   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
551   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
552
553   // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
554   MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
555
556   // 5. Program D18F2x1C0[RdTrainGo]=1.
557   MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
558
559   // 6. Wait for D18F2x1C0[RdTrainGo]=0.
560   while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
561
562   // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
563   // This step will be accomplished in Compare routine.
564
565   // 8. Program D18F2x1C0[RdDramTrainMode]=0.
566   MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
567 }
568
569 /* -----------------------------------------------------------------------------*/
570 /**
571  *
572  *
573  *      This function generates a continuous burst of reads during HW RcvEn training.
574  *
575  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
576  *     @param[in]     Address - System Address [47:16]
577  *
578  */
579 VOID
580 STATIC
581 MemNGenHwRcvEnReadsClientNb (
582   IN OUT   MEM_NB_BLOCK *NBPtr,
583   IN       UINT32 Address
584   )
585 {
586   UINT8  TempBuffer[64];
587   UINT8  Count;
588
589   for (Count = 0; Count < 3; Count++) {
590     NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
591   }
592 }
593
594 /* -----------------------------------------------------------------------------*/
595 /**
596  *
597  *      This function assigns read/write function pointers to CPG read/write modules.
598  *
599  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
600  *
601  */
602 VOID
603 MemNInitCPGClientNb (
604   IN OUT   MEM_NB_BLOCK *NBPtr
605   )
606 {
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;
614   NBPtr->CPGInit = 0;
615 }
616
617 /* -----------------------------------------------------------------------------*/
618 /**
619  *
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)
622  *
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
627  *
628  *     @return  PASS - Bitmap of results of comparison
629  */
630
631 UINT16
632 STATIC
633 MemNCompareTestPatternClientNb (
634   IN OUT   MEM_NB_BLOCK *NBPtr,
635   IN       UINT8 Buffer[],
636   IN       UINT8 Pattern[],
637   IN       UINT16 ByteCount
638   )
639 {
640   return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts));
641 }
642
643 /*-----------------------------------------------------------------------------*/
644 /**
645  *
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)
648  *
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
653  *
654  *     @retval  Bitmap of results of comparison
655  */
656 UINT16
657 STATIC
658 MemNInsDlyCompareTestPatternClientNb (
659   IN OUT   MEM_NB_BLOCK *NBPtr,
660   IN       UINT8 Buffer[],
661   IN       UINT8 Pattern[],
662   IN       UINT16 ByteCount
663   )
664 {
665   return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
666 }
667
668 /* -----------------------------------------------------------------------------*/
669 /**
670  *
671  *      This function calculates RcvEn seed value for each rank
672  *
673  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
674  *
675  */
676 VOID
677 MemNPrepareRcvrEnDlySeedNb (
678   IN OUT   MEM_NB_BLOCK  *NBPtr
679   )
680 {
681   MEM_TECH_BLOCK *TechPtr;
682   CH_DEF_STRUCT *ChannelPtr;
683   DIE_STRUCT *MCTPtr;
684   UINT16 SeedTotal;
685   UINT16 SeedFine;
686   UINT16 SeedGross;
687   UINT16 SeedPreGross;
688   UINT16 SeedTotalPreScaling;
689   UINT8  ByteLane;
690   UINT16 Speed;
691   UINT16 PlatEst;
692   UINT8 ChipSel;
693   UINT8 Pass;
694   UINT16 *PlatEstSeed;
695   UINT16 SeedValue[9];
696   UINT16 SeedTtl[9];
697   UINT16 SeedPre[9];
698
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;
706
707   for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
708     TechPtr->Bytelane = ByteLane;
709     if (Pass == 1) {
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.
714       PlatEst = 0x3B;
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;
719     } else {
720       // For Pass2
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];
726       }
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);
731     }
732     SeedTtl[ByteLane] = SeedTotal;
733
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:
741
742     if ((SeedGross & 0x1) != 0) {
743       //if SeedGross is odd
744       SeedPreGross = 1;
745     } else {
746       //if SeedGross is even
747       SeedPreGross = 2;
748     }
749     // (SeedGross - SeedPreGross)
750     TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
751
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.
754
755     NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
756     SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
757
758     // 202688: Program seed value to RcvEnDly also.
759     NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
760   }
761
762   IDS_HDT_CONSOLE_DEBUG_CODE (
763     if (Pass == 1) {
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]);
767       }
768       IDS_HDT_CONSOLE (MEM_FLOW, "\n");
769     }
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]);
773     }
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]);
777     }
778     IDS_HDT_CONSOLE (MEM_FLOW, "\n");
779   );
780 }
781
782 /* -----------------------------------------------------------------------------*/
783 /**
784  *
785  *  Waits specified number of MEMCLKs
786  *      @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
787  *      @param[in] MemClkCount - Number of MEMCLKs
788  *
789  * ----------------------------------------------------------------------------
790  */
791 VOID
792 MemNWaitXMemClksNb (
793   IN OUT   MEM_NB_BLOCK  *NBPtr,
794   IN       UINT32 MemClkCount
795   )
796 {
797   MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
798 }
799
800 /* -----------------------------------------------------------------------------*/
801 /**
802  *
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
806  *
807  * ----------------------------------------------------------------------------
808  */
809 BOOLEAN
810 STATIC
811 MemNBeforeMemClrClientNb (
812   IN OUT   MEM_NB_BLOCK  *NBPtr,
813   IN       VOID *UnUsed
814   )
815 {
816   UINT8 Pattern[64];
817   UINT8 i;
818
819   for (i = 0; i < 64; i++) {
820     Pattern[i] = 0;
821   }
822
823   MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
824   MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
825   return TRUE;
826 }
827
828 /* -----------------------------------------------------------------------------*/
829 /**
830  *
831  *   This function uses the PRBS generator in the DCT to send a DDR Activate command
832  *
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]
837  *
838  */
839
840 VOID
841 STATIC
842 MemNRrwActivateCmd (
843   IN OUT   MEM_NB_BLOCK *NBPtr,
844   IN       UINT8 ChipSelect,
845   IN       UINT8 Bank,
846   IN       UINT32 RowAddress
847   )
848 {
849   // Set Chip select
850   MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
851   // Set Bank Address
852   MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
853   // Set Row Address
854   MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
855   // Send the command
856   MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
857   // Wait for command complete
858   MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
859   // Wait 75 MEMCLKs
860   NBPtr->WaitXMemClks (NBPtr, 75);
861 }
862
863 /* -----------------------------------------------------------------------------*/
864 /**
865  *
866  *   This function uses the PRBS generator in the DCT to send a DDR Precharge
867  *     or Precharge All command
868  *
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
872  *
873  *
874  */
875
876 VOID
877 STATIC
878 MemNRrwPrechargeCmd (
879   IN OUT   MEM_NB_BLOCK *NBPtr,
880   IN       UINT8 ChipSelect,
881   IN       UINT8 Bank
882   )
883 {
884   // Wait 25 MEMCLKs
885   NBPtr->WaitXMemClks (NBPtr, 25);
886   // Set Chip select
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) );
891   } else {
892     // Clear Row Address, bit 10
893     NBPtr->SetBitField (NBPtr, BFCmdAddress,  NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
894     // Set Bank Address
895     NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
896   }
897   // Send the command
898   NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
899   // Wait for command complete
900   NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
901   // Wait 25 MEMCLKs
902   NBPtr->WaitXMemClks (NBPtr, 25);
903 }
904 /* -----------------------------------------------------------------------------*/
905 /**
906  *
907  *
908  *      This function generates a continuous burst of reads for HW RcvEn
909  *        training using the Unified Northbridge Reliable Read/Write Engine.
910  *
911  *     @param[in,out] NBPtr   - Pointer to the MEM_NB_BLOCK
912  *     @param[in]     Address - Unused by this function
913  *
914  */
915 VOID
916 STATIC
917 MemNGenHwRcvEnReadsUnb (
918   IN OUT   MEM_NB_BLOCK *NBPtr,
919   IN       UINT32 Address
920   )
921 {
922   VOID  *DummyPtr;
923   DummyPtr = NULL;
924   //
925   // Issue Stream of Reads from the Target Rank
926   //
927   NBPtr->ReadPattern (NBPtr, DummyPtr, NULL, NBPtr->TechPtr->PatternLength);
928 }
929
930 /* -----------------------------------------------------------------------------*/
931 /**
932  *
933  *     This function generates a continuous stream of reads from DRAM using the
934  *       Unified Northbridge Reliable Read/Write Engine.
935  *
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
940  *
941  *     Assumptions:
942  *
943  *
944  *
945  */
946
947 VOID
948 STATIC
949 MemNContReadPatternUnb (
950   IN OUT   MEM_NB_BLOCK *NBPtr,
951   IN       UINT8 Buffer[],
952   IN       UINT32 Address,
953   IN       UINT16 ClCount
954   )
955 {
956   MEM_TECH_BLOCK *TechPtr;
957   RRW_SETTINGS *Rrw;
958   UINT8 CmdTgt;
959   UINT8 ChipSel;
960
961   TechPtr = NBPtr->TechPtr;
962   Rrw = &NBPtr->RrwSettings;
963
964   ChipSel = TechPtr->ChipSel;
965   CmdTgt = Rrw->CmdTgt;
966   //
967   // Wait for RRW Engine to be ready and turn it on
968   //
969   NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
970   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
971   //
972   // Depending upon the Cmd Target, send Row Activate and set Chipselect
973   //   for the Row or Rows that will be used
974   //
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);
980   }
981   // Set Comparison Masks
982   NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
983   NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
984   //
985   // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
986   //
987   NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
988   //
989   // Program the PRBS Seed
990   //
991   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
992   //
993   // Set the Command Count
994   //
995   NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
996   //
997   // Program the Bubble Count and CmdStreamLen
998   //
999   NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1000   NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1001   NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1002   //
1003   // Program the Starting Address
1004   //
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);
1010   }
1011   //
1012   // Reset All Errors and Disable StopOnErr
1013   //
1014   NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1015   NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
1016   //
1017   // Program the CmdTarget
1018   //
1019   NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1020   //
1021   // Set CmdType to read
1022   //
1023   NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1024   //
1025   // Start the Commands
1026   //
1027   NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1028   //
1029   // Commands have started, wait for the reads to complete then clear the command
1030   //
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);
1034   //
1035   // Send the Precharge All Command
1036   //
1037   MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1038   //
1039   // Turn Off the RRW Engine
1040   //
1041   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1042 }
1043
1044 /* -----------------------------------------------------------------------------*/
1045 /**
1046  *
1047  *     This function generates a continuous stream of writes to DRAM using the
1048  *       Unified Northbridge Reliable Read/Write Engine.
1049  *
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
1054  *
1055  */
1056
1057 VOID
1058 STATIC
1059 MemNContWritePatternUnb (
1060   IN OUT   MEM_NB_BLOCK *NBPtr,
1061   IN       UINT32 Address,
1062   IN       UINT8 Pattern[],
1063   IN       UINT16 ClCount
1064   )
1065 {
1066   MEM_TECH_BLOCK *TechPtr;
1067   RRW_SETTINGS *Rrw;
1068   UINT8 CmdTgt;
1069   UINT8 ChipSel;
1070
1071   TechPtr = NBPtr->TechPtr;
1072   Rrw = &NBPtr->RrwSettings;
1073
1074   ChipSel = TechPtr->ChipSel;
1075   CmdTgt = Rrw->CmdTgt;
1076   //
1077   // Wait for RRW Engine to be ready and turn it on
1078   //
1079   NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1080   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1081
1082   //
1083   // Depending upon the Cmd Target, send Row Activate and set Chipselect
1084   //   for the Row or Rows that will be used
1085   //
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);
1091   }
1092   //
1093   // Program the PRBS Seed
1094   //
1095   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1096   //
1097   // Set the Command Count
1098   //
1099   NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1100   //
1101   // Program the Bubble Count and CmdStreamLen
1102   //
1103   NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1104   NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1105   NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1106   //
1107   // Program the Starting Address
1108   //
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);
1114   }
1115   //
1116   // Program the CmdTarget
1117   //
1118   NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1119   //
1120   // Set CmdType to read
1121   //
1122   NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1123   //
1124   // Start the Commands
1125   //
1126   NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1127   //
1128   // Commands have started, wait for the writes to complete then clear the command
1129   //
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);
1133   //
1134   // Send the Precharge All Command
1135   //
1136   MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1137   //
1138   // Turn Off the RRW Engine
1139   //
1140   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1141 }
1142
1143 /* -----------------------------------------------------------------------------*/
1144 /**
1145  *
1146  *       This function checks the Error status bits for comparison results
1147  *
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
1152  *
1153  *     @return  PASS - Bitmap of results of comparison
1154  */
1155
1156 UINT16
1157 STATIC
1158 MemNCompareTestPatternUnb (
1159   IN OUT   MEM_NB_BLOCK *NBPtr,
1160   IN       UINT8 Buffer[],
1161   IN       UINT8 Pattern[],
1162   IN       UINT16 ByteCount
1163   )
1164 {
1165
1166
1167   UINT16 i;
1168   UINT16 Pass;
1169   UINT8 ChipSel;
1170   UINT8 ColumnCount;
1171   UINT8* FailingBitMaskPtr;
1172   UINT8 FailingBitMask[9];
1173   UINT32 NibbleErrSts;
1174
1175   ChipSel = NBPtr->TechPtr->ChipSel;
1176   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1177   // Calculate Failing Bitmask pointer
1178   FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
1179
1180   //
1181   // Get Failing bit data
1182   //
1183   *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
1184   *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
1185   FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
1186
1187   Pass = 0x0000;
1188   //
1189   // Get Comparison Results - Convert Nibble Masks to Byte Masks
1190   //
1191   NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1192
1193   for (i = 0; i < ColumnCount ; i++) {
1194     Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
1195     NibbleErrSts >>= 2;
1196     FailingBitMaskPtr[i] = FailingBitMask[i];
1197   }
1198   Pass = ~Pass;
1199   return Pass;
1200 }
1201
1202 /*-----------------------------------------------------------------------------*/
1203 /**
1204  *
1205  *       This function checks the Error status bits for offset comparison results
1206  *
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
1211  *
1212  *     @retval  Bitmap of results of comparison
1213  */
1214 UINT16
1215 STATIC
1216 MemNInsDlyCompareTestPatternUnb (
1217   IN OUT   MEM_NB_BLOCK *NBPtr,
1218   IN       UINT8 Buffer[],
1219   IN       UINT8 Pattern[],
1220   IN       UINT16 ByteCount
1221   )
1222 {
1223   UINT16 i;
1224   UINT16 Pass;
1225   UINT8 ColumnCount;
1226   UINT32 NibbleErr180Sts;
1227
1228   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1229   Pass = 0x0000;
1230   //
1231   // Get Comparison Results - Convert Nibble Masks to Byte Masks
1232   //
1233   NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1234
1235   for (i = 0; i < ColumnCount ; i++) {
1236     Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
1237     NibbleErr180Sts >>= 2;
1238   }
1239   Pass = ~Pass;
1240
1241   return Pass;
1242 }
1243
1244 /* -----------------------------------------------------------------------------*/
1245 /**
1246  *
1247  *      This function assigns read/write function pointers to CPG read/write modules.
1248  *
1249  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
1250  *
1251  */
1252 VOID
1253 MemNInitCPGUnb (
1254   IN OUT   MEM_NB_BLOCK *NBPtr
1255   )
1256 {
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;
1266   NBPtr->CPGInit = 0;
1267 }
1268