AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / 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: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
13  *
14  **/
15 /*****************************************************************************
16 *
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
19 *
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.
30 *
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.
41 *
42 * ***************************************************************************
43 *
44 */
45
46 /*
47  *----------------------------------------------------------------------------
48  *                                MODULES USED
49  *
50  *----------------------------------------------------------------------------
51  */
52
53 #include "AGESA.h"
54 #include "AdvancedApi.h"
55 #include "amdlib.h"
56 #include "Ids.h"
57 #include "OptionMemory.h"
58 #include "mm.h"
59 #include "mn.h"
60 #include "mu.h"
61 #include "PlatformMemoryConfiguration.h"
62 #include "merrhdl.h"
63 #include "Filecode.h"
64 CODE_GROUP (G1_PEICC)
65 RDATA_GROUP (G2_PEI)
66
67 #define FILECODE PROC_MEM_NB_MNFEAT_FILECODE
68 /*----------------------------------------------------------------------------
69  *                          DEFINITIONS AND MACROS
70  *
71  *----------------------------------------------------------------------------
72  */
73 #define MAX_CL_CONT_READ  32
74 #define MAX_CL_CONT_WRITE 32
75
76 /*----------------------------------------------------------------------------
77  *                           TYPEDEFS AND STRUCTURES
78  *
79  *----------------------------------------------------------------------------
80  */
81
82 /*----------------------------------------------------------------------------
83  *                        PROTOTYPES OF LOCAL FUNCTIONS
84  *
85  *----------------------------------------------------------------------------
86  */
87
88 VOID
89 STATIC
90 MemNContWritePatternNb (
91   IN OUT   MEM_NB_BLOCK *NBPtr,
92   IN       UINT32 Address,
93   IN       UINT8 Pattern[],
94   IN       UINT16 ClCount
95   );
96
97 VOID
98 STATIC
99 MemNContReadPatternNb (
100   IN OUT   MEM_NB_BLOCK *NBPtr,
101   IN       UINT8 Buffer[],
102   IN       UINT32 Address,
103   IN       UINT16 ClCount
104   );
105
106 VOID
107 STATIC
108 MemNGenHwRcvEnReadsNb (
109   IN OUT   MEM_NB_BLOCK *NBPtr,
110   IN       UINT32 Address
111   );
112
113 UINT16
114 STATIC
115 MemNCompareTestPatternClientNb (
116   IN OUT   MEM_NB_BLOCK *NBPtr,
117   IN       UINT8 Buffer[],
118   IN       UINT8 Pattern[],
119   IN       UINT16 ByteCount
120   );
121
122 UINT16
123 STATIC
124 MemNInsDlyCompareTestPatternClientNb (
125   IN OUT   MEM_NB_BLOCK *NBPtr,
126   IN       UINT8 Buffer[],
127   IN       UINT8 Pattern[],
128   IN       UINT16 ByteCount
129   );
130
131 VOID
132 STATIC
133 MemNContWritePatternClientNb (
134   IN OUT   MEM_NB_BLOCK *NBPtr,
135   IN       UINT32 Address,
136   IN       UINT8 Pattern[],
137   IN       UINT16 ClCount
138   );
139
140 VOID
141 STATIC
142 MemNContReadPatternClientNb (
143   IN OUT   MEM_NB_BLOCK *NBPtr,
144   IN       UINT8 Buffer[],
145   IN       UINT32 Address,
146   IN       UINT16 ClCount
147   );
148
149 VOID
150 STATIC
151 MemNGenHwRcvEnReadsClientNb (
152   IN OUT   MEM_NB_BLOCK *NBPtr,
153   IN       UINT32 Address
154   );
155
156 BOOLEAN
157 STATIC
158 MemNBeforeMemClrClientNb (
159   IN OUT   MEM_NB_BLOCK  *NBPtr,
160   IN       VOID *UnUsed
161   );
162
163 VOID
164 STATIC
165 MemNGenHwRcvEnReadsUnb (
166   IN OUT   MEM_NB_BLOCK *NBPtr,
167   IN       UINT32 Address
168   );
169
170 VOID
171 STATIC
172 MemNContReadPatternUnb (
173   IN OUT   MEM_NB_BLOCK *NBPtr,
174   IN       UINT8 Buffer[],
175   IN       UINT32 Address,
176   IN       UINT16 ClCount
177   );
178
179 VOID
180 STATIC
181 MemNContWritePatternUnb (
182   IN OUT   MEM_NB_BLOCK *NBPtr,
183   IN       UINT32 Address,
184   IN       UINT8 Pattern[],
185   IN       UINT16 ClCount
186   );
187
188 VOID
189 STATIC
190 MemNEnableInfiniteWritePatternUnb (
191   IN OUT   MEM_NB_BLOCK *NBPtr
192   );
193
194 VOID
195 STATIC
196 MemNDisableInfiniteWritePatternUnb (
197   IN OUT   MEM_NB_BLOCK *NBPtr
198   );
199
200 VOID
201 MemNInitCPGNb (
202   IN OUT   MEM_NB_BLOCK *NBPtr
203   );
204
205 VOID
206 MemNInitDqsTrainRcvrEnHwNb (
207   IN OUT   MEM_NB_BLOCK *NBPtr
208   );
209
210 VOID
211 MemNDisableDqsTrainRcvrEnHwNb (
212   IN OUT   MEM_NB_BLOCK *NBPtr
213   );
214
215 VOID
216 MemNInitCPGClientNb (
217   IN OUT   MEM_NB_BLOCK *NBPtr
218   );
219
220 VOID
221 MemNInitCPGUnb (
222   IN OUT   MEM_NB_BLOCK *NBPtr
223   );
224
225 /*----------------------------------------------------------------------------
226  *                            EXPORTED FUNCTIONS
227  *
228  *----------------------------------------------------------------------------
229  */
230
231 /* -----------------------------------------------------------------------------*/
232 /**
233  *
234  *      This function assigns read/write function pointers to CPG read/write modules.
235  *
236  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
237  *
238  */
239 VOID
240 MemNInitCPGNb (
241   IN OUT   MEM_NB_BLOCK *NBPtr
242   )
243 {
244   NBPtr->WritePattern = MemNContWritePatternNb;
245   NBPtr->ReadPattern = MemNContReadPatternNb;
246   NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
247 }
248
249 /* -----------------------------------------------------------------------------*/
250 /**
251  *
252  *   This function initializes member functions of HW Rx En Training.
253  *
254  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
255  *
256  */
257
258 VOID
259 MemNInitDqsTrainRcvrEnHwNb (
260   IN OUT   MEM_NB_BLOCK *NBPtr
261   )
262 {
263   NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
264 }
265 /* -----------------------------------------------------------------------------*/
266 /**
267  *
268  *   This function disables member functions of Hw Rx En Training.
269  *
270  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
271  *
272  */
273
274 VOID
275 MemNDisableDqsTrainRcvrEnHwNb (
276   IN OUT   MEM_NB_BLOCK *NBPtr
277   )
278 {
279   NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
280 }
281
282 /*----------------------------------------------------------------------------
283  *                              LOCAL FUNCTIONS
284  *
285  *----------------------------------------------------------------------------
286  */
287
288 /* -----------------------------------------------------------------------------*/
289 /**
290  *
291  *      This function writes 9 or 18 cache lines continuously using GH CPG engine
292  *
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
297  *
298  */
299 VOID
300 STATIC
301 MemNContWritePatternNb (
302   IN OUT   MEM_NB_BLOCK *NBPtr,
303   IN       UINT32 Address,
304   IN       UINT8 Pattern[],
305   IN       UINT16 ClCount
306   )
307 {
308   UINT16 ClDiff;
309   if (ClCount > MAX_CL_CONT_WRITE) {
310     ClDiff = ClCount - MAX_CL_CONT_WRITE;
311     ClCount = MAX_CL_CONT_WRITE;
312   } else {
313     ClDiff = 0;
314   }
315
316   // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
317   MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
318
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);
323
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) {}
328
329   // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
330   MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
331
332   if (ClDiff > 0) {
333     MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
334   }
335 }
336
337 /* -----------------------------------------------------------------------------*/
338 /**
339  *
340  *
341  *      This function reads 9 or 18 cache lines continuously using GH CPG engine
342  *
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
347  *
348  */
349
350 VOID
351 STATIC
352 MemNContReadPatternNb (
353   IN OUT   MEM_NB_BLOCK *NBPtr,
354   IN       UINT8 Buffer[],
355   IN       UINT32 Address,
356   IN       UINT16 ClCount
357   )
358 {
359   BOOLEAN DisAutoRefresh;
360   UINT16 ClDiff;
361   if (ClCount > MAX_CL_CONT_READ) {
362     ClDiff = ClCount - MAX_CL_CONT_READ;
363     ClCount = MAX_CL_CONT_READ;
364   } else {
365     ClDiff = 0;
366   }
367
368   Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
369
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
374   // is complete.
375
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);
383   } else {
384     DisAutoRefresh = TRUE;
385   }
386
387   MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
388
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);
392
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);
397
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);
409   }
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);
416
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);
422   }
423
424   if (ClDiff > 0) {
425     MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
426   }
427 }
428
429 /* -----------------------------------------------------------------------------*/
430 /**
431  *
432  *
433  *      This function generates a continuous burst of reads during HW RcvEn training.
434  *
435  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
436  *     @param[in]     Address - System Address [47:16]
437  *
438  */
439 VOID
440 STATIC
441 MemNGenHwRcvEnReadsNb (
442   IN OUT   MEM_NB_BLOCK *NBPtr,
443   IN       UINT32 Address
444   )
445 {
446   UINT8  TempBuffer[12 * 64];
447   UINT8  BurstCount;
448
449   for (BurstCount = 0; BurstCount < 10; BurstCount++) {
450     NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
451     NBPtr->FlushPattern (NBPtr, Address, 12);
452   }
453 }
454
455 /* -----------------------------------------------------------------------------*/
456 /**
457  *
458  *      This function writes cache lines continuously using TCB CPG engine
459  *
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
464  *
465  */
466 VOID
467 STATIC
468 MemNContWritePatternClientNb (
469   IN OUT   MEM_NB_BLOCK *NBPtr,
470   IN       UINT32 Address,
471   IN       UINT8 Pattern[],
472   IN       UINT16 ClCount
473   )
474 {
475   UINT32 PatternHash;
476   UINT32 *DwordPtr;
477   UINT16 i;
478   UINT16 j;
479   UINT16 Multiplier;
480
481   Multiplier = 1;
482
483   // 1. Program D18F2x1C0[WrDramTrainMode]=1.
484   MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
485
486   PatternHash = ClCount << 24;
487   for (i = 0; i < 3; i ++) {
488     PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
489   }
490   if (NBPtr->CPGInit != PatternHash) {
491
492     if (ClCount == 3) {
493       // Double pattern length for MaxRdLat training
494       Multiplier = 2;
495     }
496
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);
500
501     // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
502     MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
503
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]);
509       }
510     }
511
512     NBPtr->CPGInit = PatternHash;
513   }
514
515   // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
516   MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
517
518   // 6. Program the DRAM training address
519   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
520   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
521
522   // 7. Program D18F2x1C0[WrTrainGo]=1.
523   MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
524
525   // 8. Wait for D18F2x1C0[WrTrainGo]=0.
526   while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
527
528   // 9. Program D18F2x1C0[WrDramTrainMode]=0.
529   MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
530 }
531
532 /* -----------------------------------------------------------------------------*/
533 /**
534  *
535  *
536  *      This function reads cache lines continuously using TCB CPG engine
537  *
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
542  *
543  */
544
545 VOID
546 STATIC
547 MemNContReadPatternClientNb (
548   IN OUT   MEM_NB_BLOCK *NBPtr,
549   IN       UINT8 Buffer[],
550   IN       UINT32 Address,
551   IN       UINT16 ClCount
552   )
553 {
554   UINT16 Multiplier;
555
556   Multiplier = 1;
557   if (ClCount == 3) {
558     // Double pattern length for MaxRdLat training
559     Multiplier = 2;
560   }
561
562   // 1. Program D18F2x1C0[RdDramTrainMode]=1.
563   MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
564
565   // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
566   MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
567
568   // 3. Program the DRAM training address as follows:
569   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
570   MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
571
572   // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
573   MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
574
575   // 5. Program D18F2x1C0[RdTrainGo]=1.
576   MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
577
578   // 6. Wait for D18F2x1C0[RdTrainGo]=0.
579   while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
580
581   // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
582   // This step will be accomplished in Compare routine.
583
584   // 8. Program D18F2x1C0[RdDramTrainMode]=0.
585   MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
586 }
587
588 /* -----------------------------------------------------------------------------*/
589 /**
590  *
591  *
592  *      This function generates a continuous burst of reads during HW RcvEn training.
593  *
594  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
595  *     @param[in]     Address - System Address [47:16]
596  *
597  */
598 VOID
599 STATIC
600 MemNGenHwRcvEnReadsClientNb (
601   IN OUT   MEM_NB_BLOCK *NBPtr,
602   IN       UINT32 Address
603   )
604 {
605   UINT8  TempBuffer[64];
606   UINT8  Count;
607
608   for (Count = 0; Count < 3; Count++) {
609     NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
610   }
611 }
612
613 /* -----------------------------------------------------------------------------*/
614 /**
615  *
616  *      This function assigns read/write function pointers to CPG read/write modules.
617  *
618  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
619  *
620  */
621 VOID
622 MemNInitCPGClientNb (
623   IN OUT   MEM_NB_BLOCK *NBPtr
624   )
625 {
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;
633   NBPtr->CPGInit = 0;
634 }
635
636 /* -----------------------------------------------------------------------------*/
637 /**
638  *
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)
641  *
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
646  *
647  *     @return  PASS - Bitmap of results of comparison
648  */
649
650 UINT16
651 STATIC
652 MemNCompareTestPatternClientNb (
653   IN OUT   MEM_NB_BLOCK *NBPtr,
654   IN       UINT8 Buffer[],
655   IN       UINT8 Pattern[],
656   IN       UINT16 ByteCount
657   )
658 {
659   return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts));
660 }
661
662 /*-----------------------------------------------------------------------------*/
663 /**
664  *
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)
667  *
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
672  *
673  *     @retval  Bitmap of results of comparison
674  */
675 UINT16
676 STATIC
677 MemNInsDlyCompareTestPatternClientNb (
678   IN OUT   MEM_NB_BLOCK *NBPtr,
679   IN       UINT8 Buffer[],
680   IN       UINT8 Pattern[],
681   IN       UINT16 ByteCount
682   )
683 {
684   return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
685 }
686
687 /* -----------------------------------------------------------------------------*/
688 /**
689  *
690  *      This function calculates RcvEn seed value for each rank
691  *
692  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
693  *
694  */
695 VOID
696 MemNPrepareRcvrEnDlySeedNb (
697   IN OUT   MEM_NB_BLOCK  *NBPtr
698   )
699 {
700   MEM_TECH_BLOCK *TechPtr;
701   CH_DEF_STRUCT *ChannelPtr;
702   DIE_STRUCT *MCTPtr;
703   UINT16 SeedTotal;
704   UINT16 SeedFine;
705   UINT16 SeedGross;
706   UINT16 SeedPreGross;
707   UINT16 SeedTotalPreScaling;
708   UINT8  ByteLane;
709   UINT16 Speed;
710   UINT16 PlatEst;
711   UINT8 ChipSel;
712   UINT8 Pass;
713   UINT16 *PlatEstSeed;
714   UINT16 SeedValue[9];
715   UINT16 SeedTtl[9];
716   UINT16 SeedPre[9];
717
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;
725
726   for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
727     TechPtr->Bytelane = ByteLane;
728     if (Pass == 1) {
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.
734       PlatEst = 0x3B;
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;
739     } else {
740       // For Pass2
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];
746       }
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);
752     }
753     SeedTtl[ByteLane] = SeedTotal;
754
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:
762
763     if ((SeedGross & 0x1) != 0) {
764       //if SeedGross is odd
765       SeedPreGross = 1;
766     } else {
767       //if SeedGross is even
768       SeedPreGross = 2;
769     }
770     // (SeedGross - SeedPreGross)
771     TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
772
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.
775
776     NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
777     SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
778
779     // 202688: Program seed value to RcvEnDly also.
780     NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
781   }
782
783   IDS_HDT_CONSOLE_DEBUG_CODE (
784     if (Pass == 1) {
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]);
788       }
789       IDS_HDT_CONSOLE (MEM_FLOW, "\n");
790     }
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]);
794     }
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]);
798     }
799     IDS_HDT_CONSOLE (MEM_FLOW, "\n");
800   );
801
802   NBPtr->FamilySpecificHook[RegAccessFence] (NBPtr, NULL);
803 }
804
805 /* -----------------------------------------------------------------------------*/
806 /**
807  *
808  *  Waits specified number of MEMCLKs
809  *      @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
810  *      @param[in] MemClkCount - Number of MEMCLKs
811  *
812  * ----------------------------------------------------------------------------
813  */
814 VOID
815 MemNWaitXMemClksNb (
816   IN OUT   MEM_NB_BLOCK  *NBPtr,
817   IN       UINT32 MemClkCount
818   )
819 {
820   MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
821 }
822
823 /* -----------------------------------------------------------------------------*/
824 /**
825  *
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
829  *
830  * ----------------------------------------------------------------------------
831  */
832 BOOLEAN
833 STATIC
834 MemNBeforeMemClrClientNb (
835   IN OUT   MEM_NB_BLOCK  *NBPtr,
836   IN       VOID *UnUsed
837   )
838 {
839   UINT8 Pattern[64];
840   UINT8 i;
841
842   for (i = 0; i < 64; i++) {
843     Pattern[i] = 0;
844   }
845
846   MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
847   MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
848   return TRUE;
849 }
850
851 /* -----------------------------------------------------------------------------*/
852 /**
853  *
854  *   This function uses the PRBS generator in the DCT to send a DDR Activate command
855  *
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]
860  *
861  */
862
863 VOID
864 MemNRrwActivateCmd (
865   IN OUT   MEM_NB_BLOCK *NBPtr,
866   IN       UINT8 ChipSelect,
867   IN       UINT8 Bank,
868   IN       UINT32 RowAddress
869   )
870 {
871   // Set Chip select
872   MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
873   // Set Bank Address
874   MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
875   // Set Row Address
876   MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
877   // Send the command
878   MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
879   // Wait for command complete
880   MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
881   // Wait 75 MEMCLKs
882   NBPtr->WaitXMemClks (NBPtr, 75);
883 }
884
885 /* -----------------------------------------------------------------------------*/
886 /**
887  *
888  *   This function uses the PRBS generator in the DCT to send a DDR Precharge
889  *     or Precharge All command
890  *
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
894  *
895  *
896  */
897
898 VOID
899 MemNRrwPrechargeCmd (
900   IN OUT   MEM_NB_BLOCK *NBPtr,
901   IN       UINT8 ChipSelect,
902   IN       UINT8 Bank
903   )
904 {
905   // Wait 25 MEMCLKs
906   NBPtr->WaitXMemClks (NBPtr, 25);
907   // Set Chip select
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) );
912   } else {
913     // Clear Row Address, bit 10
914     NBPtr->SetBitField (NBPtr, BFCmdAddress,  NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
915     // Set Bank Address
916     NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
917   }
918   // Send the command
919   NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
920   // Wait for command complete
921   NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
922   // Wait 25 MEMCLKs
923   NBPtr->WaitXMemClks (NBPtr, 25);
924 }
925 /* -----------------------------------------------------------------------------*/
926 /**
927  *
928  *
929  *      This function generates a continuous burst of reads for HW RcvEn
930  *        training using the Unified Northbridge Reliable Read/Write Engine.
931  *
932  *     @param[in,out] NBPtr   - Pointer to the MEM_NB_BLOCK
933  *     @param[in]     Address - Unused by this function
934  *
935  */
936 VOID
937 STATIC
938 MemNGenHwRcvEnReadsUnb (
939   IN OUT   MEM_NB_BLOCK *NBPtr,
940   IN       UINT32 Address
941   )
942 {
943   VOID  *DummyPtr;
944   DummyPtr = NULL;
945   //
946   // Issue Stream of Reads from the Target Rank
947   //
948   NBPtr->ReadPattern (NBPtr, DummyPtr, 0, NBPtr->TechPtr->PatternLength);
949 }
950
951 /* -----------------------------------------------------------------------------*/
952 /**
953  *
954  *     This function generates a continuous stream of reads from DRAM using the
955  *       Unified Northbridge Reliable Read/Write Engine.
956  *
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
961  *
962  *     Assumptions:
963  *
964  *
965  *
966  */
967
968 VOID
969 STATIC
970 MemNContReadPatternUnb (
971   IN OUT   MEM_NB_BLOCK *NBPtr,
972   IN       UINT8 Buffer[],
973   IN       UINT32 Address,
974   IN       UINT16 ClCount
975   )
976 {
977   MEM_TECH_BLOCK *TechPtr;
978   RRW_SETTINGS *Rrw;
979   UINT8 CmdTgt;
980   UINT8 ChipSel;
981
982   TechPtr = NBPtr->TechPtr;
983   Rrw = &NBPtr->RrwSettings;
984
985   ChipSel = TechPtr->ChipSel;
986   CmdTgt = Rrw->CmdTgt;
987   //
988   // Wait for RRW Engine to be ready and turn it on
989   //
990   NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
991   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
992   //
993   // Depending upon the Cmd Target, send Row Activate and set Chipselect
994   //   for the Row or Rows that will be used
995   //
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);
1001   }
1002   // Set Comparison Masks
1003   NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
1004   NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
1005   //
1006   // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
1007   //
1008   NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
1009   //
1010   // Program the PRBS Seed
1011   //
1012   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1013   //
1014   // Set the Command Count
1015   //
1016   NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1017   //
1018   // Program the Bubble Count and CmdStreamLen
1019   //
1020   NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1021   NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1022   NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1023   //
1024   // Program the Starting Address
1025   //
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);
1031   }
1032   //
1033   // Reset All Errors and Disable StopOnErr
1034   //
1035   NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1036   NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
1037   //
1038   // Program the CmdTarget
1039   //
1040   NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1041   //
1042   // Set CmdType to read
1043   //
1044   NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1045   //
1046   // Start the Commands
1047   //
1048   AGESA_TESTPOINT (TpProcMemContinPatternGenRead, &(NBPtr->MemPtr->StdHeader));
1049   NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1050   //
1051   // Commands have started, wait for the reads to complete then clear the command
1052   //
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);
1056   //
1057   // Send the Precharge All Command
1058   //
1059   MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1060   //
1061   // Turn Off the RRW Engine
1062   //
1063   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1064 }
1065
1066 /* -----------------------------------------------------------------------------*/
1067 /**
1068  *
1069  *     This function generates a continuous stream of writes to DRAM using the
1070  *       Unified Northbridge Reliable Read/Write Engine.
1071  *
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
1076  *
1077  */
1078
1079 VOID
1080 STATIC
1081 MemNContWritePatternUnb (
1082   IN OUT   MEM_NB_BLOCK *NBPtr,
1083   IN       UINT32 Address,
1084   IN       UINT8 Pattern[],
1085   IN       UINT16 ClCount
1086   )
1087 {
1088   MEM_TECH_BLOCK *TechPtr;
1089   RRW_SETTINGS *Rrw;
1090   UINT8 CmdTgt;
1091   UINT8 ChipSel;
1092
1093   TechPtr = NBPtr->TechPtr;
1094   Rrw = &NBPtr->RrwSettings;
1095
1096   ChipSel = TechPtr->ChipSel;
1097   CmdTgt = Rrw->CmdTgt;
1098   //
1099   // Wait for RRW Engine to be ready and turn it on
1100   //
1101   NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1102   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1103   //
1104   // Depending upon the Cmd Target, send Row Activate and set Chipselect
1105   //   for the Row or Rows that will be used
1106   //
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);
1112   }
1113   //
1114   // Program the PRBS Seed
1115   //
1116   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1117   //
1118   // Set the Command Count
1119   //
1120   NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1121   //
1122   // Program the Bubble Count and CmdStreamLen
1123   //
1124   NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1125   NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1126   NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1127   //
1128   // Program the Starting Address
1129   //
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);
1135   }
1136   //
1137   // Program the CmdTarget
1138   //
1139   NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1140   //
1141   // Set CmdType to Write
1142   //
1143   NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1144   //
1145   // Start the Commands
1146   //
1147   AGESA_TESTPOINT (TpProcMemContinPatternGenWrite, &(NBPtr->MemPtr->StdHeader));
1148   NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1149   //
1150   // Commands have started, wait for the writes to complete then clear the command
1151   //
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);
1156   //
1157   // Send the Precharge All Command
1158   //
1159   MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1160   //
1161   // Turn Off the RRW Engine
1162   //
1163   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1164 }
1165
1166 /* -----------------------------------------------------------------------------*/
1167 /**
1168  *
1169  *       This function checks the Error status bits for comparison results
1170  *
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
1175  *
1176  *     @return  PASS - Bitmap of results of comparison
1177  */
1178
1179 UINT16
1180 STATIC
1181 MemNCompareTestPatternUnb (
1182   IN OUT   MEM_NB_BLOCK *NBPtr,
1183   IN       UINT8 Buffer[],
1184   IN       UINT8 Pattern[],
1185   IN       UINT16 ByteCount
1186   )
1187 {
1188
1189
1190   UINT16 i;
1191   UINT16 Pass;
1192   UINT8 ChipSel;
1193   UINT8 ColumnCount;
1194   UINT8* FailingBitMaskPtr;
1195   UINT8 FailingBitMask[9];
1196   UINT32 NibbleErrSts;
1197
1198   ChipSel = NBPtr->TechPtr->ChipSel;
1199   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1200   // Calculate Failing Bitmask pointer
1201   FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
1202
1203   //
1204   // Get Failing bit data
1205   //
1206   *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
1207   *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
1208   FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
1209
1210   Pass = 0x0000;
1211   //
1212   // Get Comparison Results - Convert Nibble Masks to Byte Masks
1213   //
1214   NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1215
1216   for (i = 0; i < ColumnCount ; i++) {
1217     Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
1218     NibbleErrSts >>= 2;
1219     FailingBitMaskPtr[i] = FailingBitMask[i];
1220   }
1221   Pass = ~Pass;
1222   return Pass;
1223 }
1224
1225 /*-----------------------------------------------------------------------------*/
1226 /**
1227  *
1228  *       This function checks the Error status bits for offset comparison results
1229  *
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
1234  *
1235  *     @retval  Bitmap of results of comparison
1236  */
1237 UINT16
1238 STATIC
1239 MemNInsDlyCompareTestPatternUnb (
1240   IN OUT   MEM_NB_BLOCK *NBPtr,
1241   IN       UINT8 Buffer[],
1242   IN       UINT8 Pattern[],
1243   IN       UINT16 ByteCount
1244   )
1245 {
1246   UINT16 i;
1247   UINT16 Pass;
1248   UINT8 ColumnCount;
1249   UINT32 NibbleErr180Sts;
1250
1251   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1252   Pass = 0x0000;
1253   //
1254   // Get Comparison Results - Convert Nibble Masks to Byte Masks
1255   //
1256   NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1257
1258   for (i = 0; i < ColumnCount ; i++) {
1259     Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
1260     NibbleErr180Sts >>= 2;
1261   }
1262   Pass = ~Pass;
1263
1264   return Pass;
1265 }
1266
1267 /* -----------------------------------------------------------------------------*/
1268 /**
1269  *
1270  *      This function assigns read/write function pointers to CPG read/write modules.
1271  *
1272  *     @param[in,out] NBPtr  - Pointer to the MEM_NB_BLOCK
1273  *
1274  */
1275 VOID
1276 MemNInitCPGUnb (
1277   IN OUT   MEM_NB_BLOCK *NBPtr
1278   )
1279 {
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;
1291   NBPtr->CPGInit = 0;
1292 }
1293 /* -----------------------------------------------------------------------------*/
1294 /**
1295  *
1296  *     This function generates a continuous stream of writes infinite writes to DRAM using the
1297  *       Unified Northbridge Reliable Read/Write Engine.
1298  *
1299  *     @param[in,out] NBPtr   - Pointer to the MEM_NB_BLOCK
1300  *
1301  */
1302
1303 VOID
1304 STATIC
1305 MemNEnableInfiniteWritePatternUnb (
1306   IN OUT   MEM_NB_BLOCK *NBPtr
1307   )
1308 {
1309   UINT8 ByteLane;
1310   UINT32 WrDatValue;
1311   UINT32 WrDqsValue;
1312   MEM_TECH_BLOCK *TechPtr;
1313   RRW_SETTINGS *Rrw;
1314   UINT8 CmdTgt;
1315   UINT8 ChipSel;
1316   TechPtr = NBPtr->TechPtr;
1317   Rrw = &NBPtr->RrwSettings;
1318   ChipSel = TechPtr->ChipSel;
1319   CmdTgt = Rrw->CmdTgt;
1320
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);
1326   } else {
1327     NBPtr->OrigDisAutoRefreshState = TRUE;
1328   }
1329
1330   //
1331   // Enable I/O Skew mode
1332   //
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);
1340   }
1341   NBPtr->SetBitField (NBPtr, BFReserved00A, 0x0001);
1342
1343
1344   //
1345   // Enable PRBS
1346   //
1347
1348   //
1349   // Wait for RRW Engine to be ready and turn it on
1350   //
1351   NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1352   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1353   //
1354   // Depending upon the Cmd Target, send Row Activate and set Chipselect
1355   //   for the Row or Rows that will be used
1356   //
1357   MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1358   NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1359   //
1360   // Program the PRBS Seed
1361   //
1362   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1363   //
1364   // Set the Command Count
1365   //
1366   NBPtr->SetBitField (NBPtr, BFCmdCount, 0);
1367   //
1368   // Program the Bubble Count and CmdStreamLen
1369   //
1370   NBPtr->SetBitField (NBPtr, BFReserved007, 0);
1371   NBPtr->SetBitField (NBPtr, BFReserved008, 0);
1372   NBPtr->SetBitField (NBPtr, BFReserved006, 1);
1373   //
1374   // Program the Starting Address
1375   //
1376   NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1377   NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1378   //
1379   // Program the CmdTarget
1380   //
1381   NBPtr->SetBitField (NBPtr, BFCmdTgt, CMD_TGT_A);
1382   //
1383   // Set CmdType to write
1384   //
1385   NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1386   //
1387   // Start the Commands
1388   //
1389   NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1390 }
1391
1392 /* -----------------------------------------------------------------------------*/
1393 /**
1394  *
1395  *     This function disables the infinite stream of writes to DRAM using the
1396  *       Unified Northbridge Reliable Read/Write Engine.
1397  *
1398  *     @param[in,out] NBPtr   - Pointer to the MEM_NB_BLOCK
1399  *
1400  */
1401
1402 VOID
1403 STATIC
1404 MemNDisableInfiniteWritePatternUnb (
1405   IN OUT   MEM_NB_BLOCK *NBPtr
1406   )
1407 {
1408   UINT8 ByteLane;
1409   UINT32 WrDatValue;
1410   UINT32 WrDqsValue;
1411   //
1412   // Disable PRBS
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);
1417   //
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);
1426   }
1427   NBPtr->SetBitField (NBPtr, BFReserved00A, 0x0000);
1428   //
1429   // Turn Off the RRW Engine
1430   //
1431   MemNRrwPrechargeCmd (NBPtr, NBPtr->TechPtr->ChipSel, PRECHARGE_ALL_BANKS);
1432   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1433   //
1434   // Restore DisAutoRefresh and ZQCals to original state
1435   //
1436   if (!NBPtr->OrigDisAutoRefreshState) {
1437     MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
1438     MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
1439   }
1440
1441 }
1442 /*-----------------------------------------------------------------------------*/
1443 /**
1444  *
1445  *       This function checks the 180 Error status bits for RD DQS training
1446  *
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,
1451  *
1452  *     @retval  Bitmap of results of comparison
1453  */
1454 UINT32
1455 MemN180CompareRdDqs__PatternUnb (
1456   IN OUT   MEM_NB_BLOCK *NBPtr,
1457   IN       UINT8 Buffer[],
1458   IN       UINT8 Pattern[],
1459   IN       UINT16 ByteCount
1460   )
1461 {
1462   return NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1463 }
1464
1465
1466 /* -----------------------------------------------------------------------------*/
1467 /**
1468  *
1469  *       This function checks the In Phase Error status bits for comparison results for RDDQS training
1470  *
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
1475  *
1476  *     @return  PASS - Bitmap of results of comparison
1477  */
1478
1479 UINT32
1480 MemNInPhaseCompareRdDqs__PatternUnb (
1481   IN OUT   MEM_NB_BLOCK *NBPtr,
1482   IN       UINT8 Buffer[],
1483   IN       UINT8 Pattern[],
1484   IN       UINT16 ByteCount
1485   )
1486 {
1487   return NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1488 }
1489 /* -----------------------------------------------------------------------------*/
1490 /**
1491  *
1492  *       This function starts the Victim for RdDqs Training Continuous Writes
1493  *
1494  *     @param[in,out]   *NBPtr    - Pointer to the MEM_NB_BLOCK
1495  *     @param[in]       SeedCount  -  Seed count
1496  */
1497 VOID
1498 MemNStartRdDqs__VictimContinuousWritesUnb (
1499   IN OUT   MEM_NB_BLOCK *NBPtr,
1500   IN       UINT8 SeedCount
1501   )
1502 {
1503   // Program the PRBS Seed
1504   NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, NBPtr->GetPrbs__RdDqsSeed (NBPtr, SeedCount));
1505   //
1506   // Enable continuous writes on the victim channels
1507   //
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);
1515   //
1516   // Enable continuous reads on the victim channels
1517   //
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);
1526   //}
1527   NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1528 }
1529 /* -----------------------------------------------------------------------------*/
1530 /**
1531  *
1532  *       This function Initializes the Victim chipSelects for RdDqs Training Continuous Writes
1533  *
1534  *     @param[in,out]   *NBPtr    - Pointer to the MEM_NB_BLOCK
1535  */
1536 VOID
1537 MemNInitializeRdDqs__VictimChipSelContinuousWritesUnb (
1538   IN OUT   MEM_NB_BLOCK *NBPtr
1539   )
1540 {
1541   NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, NBPtr->TechPtr->ChipSel);
1542   NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, NBPtr->TechPtr->ChipSel);
1543   NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1544 }
1545 /* -----------------------------------------------------------------------------*/
1546 /**
1547  *
1548  *       This function finalizes the Victim for RdDqs Training
1549  *
1550  *     @param[in,out]   *NBPtr    - Pointer to the MEM_NB_BLOCK
1551  */
1552 VOID
1553 MemNFinalizeRdDqs__VictimContinuousWritesUnb  (
1554   IN OUT   MEM_NB_BLOCK *NBPtr
1555   )
1556 {
1557   UINT8 InitialCS;
1558   UINT8 ChipSel;
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) {
1564       continue;
1565     }
1566     NBPtr->TechPtr->ChipSel = ChipSel;
1567     // Send the Precharge All Command
1568     MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1569   }
1570   // Turn Off the RRW Engine
1571   NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1572 }
1573 /* -----------------------------------------------------------------------------*/
1574 /**
1575  *
1576  *       This function Initializes the Victim for RdDqs Training
1577  *
1578  *     @param[in,out]   *NBPtr    - Pointer to the MEM_NB_BLOCK
1579  */
1580 VOID
1581 MemNInitializeRdDqs__VictimContinuousWritesUnb (
1582   IN OUT   MEM_NB_BLOCK *NBPtr
1583   )
1584 {
1585   RRW_SETTINGS *Rrw;
1586   UINT8 InitialCS;
1587   UINT8 ChipSel;
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) {
1611       continue;
1612     }
1613     NBPtr->TechPtr->ChipSel = ChipSel;
1614     // Set Chip select
1615     MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << NBPtr->TechPtr->ChipSel));
1616     // Set Bank Address
1617     MemNSetBitFieldNb (NBPtr, BFCmdBank, Rrw->TgtBankAddressA);
1618     // Set Row Address
1619     MemNSetBitFieldNb (NBPtr, BFCmdAddress, Rrw->TgtRowAddressA);
1620     // Send the command
1621     MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
1622     // Wait for command complete
1623     MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
1624     // Set Chip select
1625     MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << NBPtr->TechPtr->ChipSel));
1626     // Set Bank Address
1627     MemNSetBitFieldNb (NBPtr, BFCmdBank, Rrw->TgtBankAddressB);
1628     // Set Row Address
1629     MemNSetBitFieldNb (NBPtr, BFCmdAddress, Rrw->TgtRowAddressB);
1630     // Send the command
1631     MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
1632     // Wait for command complete
1633     MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
1634   }
1635   NBPtr->SetBitField (NBPtr, BFReserved003, 1);
1636 }
1637 /* -----------------------------------------------------------------------------*/
1638 /**
1639  *
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
1643  *
1644  *     @return    Prbs Seed
1645  *
1646  */
1647
1648 UINT32
1649 MemNGetPrbs__RdDqsSeedUnb (
1650   IN OUT   MEM_NB_BLOCK *NBPtr,
1651   IN       UINT8 SeedCount
1652   )
1653 {
1654   UINT32 PrbsSeed;
1655   ASSERT (SeedCount <= (NBPtr->MaxSeedCount - 1))
1656   PrbsSeed = ((UINT32)0x7ea05 << SeedCount) & 0x7FFFF;
1657   ASSERT (PrbsSeed != 0);
1658   return PrbsSeed;
1659 }
1660
1661 /* -----------------------------------------------------------------------------*/
1662 /**
1663  *
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
1669  *
1670  */
1671 VOID
1672 MemNAgressorContinuousWritesUnb (
1673   IN OUT   MEM_NB_BLOCK *NBPtr,
1674   IN       UINT8 SeedCount,
1675   IN       BOOLEAN TurnOnInfinite
1676   )
1677 {
1678   UINT8  CurrChipSel;
1679   UINT8  CurrDct;
1680   UINT8  Dct;
1681   UINT32 Address;
1682   UINT8  Die;
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;
1695           } else {
1696             SkipContinuous = FALSE;
1697           }
1698         } else {
1699           SkipContinuous = FALSE;
1700         }
1701         // Enable/Disable continuous on aggressors
1702         if (SkipContinuous == FALSE) {
1703           if (Die == NBPtr->Node) {
1704             TargetNBPtr = NBPtr;
1705           } else {
1706             ASSERT (NBPtr->AdjacentDieNBPtr != NULL);
1707             TargetNBPtr = NBPtr->AdjacentDieNBPtr;
1708           }
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);
1719             } else {
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];
1725               } else {
1726                 TargetNBPtr->CurrentAggressorCSTarget[Dct] = TargetNBPtr->CurrentAggressorCSTarget[Dct] + TargetNBPtr->CSPerDelay (TargetNBPtr);
1727               }
1728             }
1729           }
1730         }
1731       }
1732     }
1733   }
1734   // Restore Node, DCT and ChipSel
1735   NBPtr->TechPtr->ChipSel = CurrChipSel;
1736   NBPtr->SwitchDCT (NBPtr, CurrDct);
1737 }