blob: 0bec48161c39ec8c7aacc47389230e5b4f7c4ff7 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $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.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * 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.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * 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.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
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"
65CODE_GROUP (G1_PEICC)
66RDATA_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
89VOID
efdesign9884cbce22011-08-04 12:09:17 -060090MemNInitCPGNb (
91 IN OUT MEM_NB_BLOCK *NBPtr
92 );
93
94VOID
95MemNInitDqsTrainRcvrEnHwNb (
96 IN OUT MEM_NB_BLOCK *NBPtr
97 );
98
99VOID
100MemNDisableDqsTrainRcvrEnHwNb (
101 IN OUT MEM_NB_BLOCK *NBPtr
102 );
103
104VOID
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000105STATIC
106MemNContWritePatternNb (
107 IN OUT MEM_NB_BLOCK *NBPtr,
108 IN UINT32 Address,
109 IN UINT8 Pattern[],
110 IN UINT16 ClCount
111 );
112
113VOID
114STATIC
115MemNContReadPatternNb (
116 IN OUT MEM_NB_BLOCK *NBPtr,
117 IN UINT8 Buffer[],
118 IN UINT32 Address,
119 IN UINT16 ClCount
120 );
121
122VOID
123STATIC
124MemNGenHwRcvEnReadsNb (
125 IN OUT MEM_NB_BLOCK *NBPtr,
126 IN UINT32 Address
127 );
128
129UINT16
130STATIC
131MemNCompareTestPatternClientNb (
132 IN OUT MEM_NB_BLOCK *NBPtr,
133 IN UINT8 Buffer[],
134 IN UINT8 Pattern[],
135 IN UINT16 ByteCount
136 );
137
138UINT16
139STATIC
140MemNInsDlyCompareTestPatternClientNb (
141 IN OUT MEM_NB_BLOCK *NBPtr,
142 IN UINT8 Buffer[],
143 IN UINT8 Pattern[],
144 IN UINT16 ByteCount
145 );
146
147VOID
148STATIC
149MemNContWritePatternClientNb (
150 IN OUT MEM_NB_BLOCK *NBPtr,
151 IN UINT32 Address,
152 IN UINT8 Pattern[],
153 IN UINT16 ClCount
154 );
155
156VOID
157STATIC
158MemNContReadPatternClientNb (
159 IN OUT MEM_NB_BLOCK *NBPtr,
160 IN UINT8 Buffer[],
161 IN UINT32 Address,
162 IN UINT16 ClCount
163 );
164
165VOID
166STATIC
167MemNGenHwRcvEnReadsClientNb (
168 IN OUT MEM_NB_BLOCK *NBPtr,
169 IN UINT32 Address
170 );
171
172BOOLEAN
173STATIC
174MemNBeforeMemClrClientNb (
175 IN OUT MEM_NB_BLOCK *NBPtr,
176 IN VOID *UnUsed
177 );
178
179VOID
180STATIC
181MemNGenHwRcvEnReadsUnb (
182 IN OUT MEM_NB_BLOCK *NBPtr,
183 IN UINT32 Address
184 );
185
186VOID
187STATIC
188MemNRrwActivateCmd (
189 IN OUT MEM_NB_BLOCK *NBPtr,
190 IN UINT8 ChipSelect,
191 IN UINT8 Bank,
192 IN UINT32 RowAddress
193 );
194
195VOID
196STATIC
197MemNRrwPrechargeCmd (
198 IN OUT MEM_NB_BLOCK *NBPtr,
199 IN UINT8 ChipSelect,
200 IN UINT8 Bank
201 );
202
203VOID
204STATIC
205MemNContReadPatternUnb (
206 IN OUT MEM_NB_BLOCK *NBPtr,
207 IN UINT8 Buffer[],
208 IN UINT32 Address,
209 IN UINT16 ClCount
210 );
211
212VOID
213STATIC
214MemNContWritePatternUnb (
215 IN OUT MEM_NB_BLOCK *NBPtr,
216 IN UINT32 Address,
217 IN UINT8 Pattern[],
218 IN UINT16 ClCount
219 );
220
efdesign9884cbce22011-08-04 12:09:17 -0600221VOID
222MemNInitCPGClientNb (
223 IN OUT MEM_NB_BLOCK *NBPtr
224 );
225
226VOID
227MemNInitCPGUnb (
228 IN OUT MEM_NB_BLOCK *NBPtr
229 );
230
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000231/*----------------------------------------------------------------------------
232 * EXPORTED FUNCTIONS
233 *
234 *----------------------------------------------------------------------------
235 */
236
237/* -----------------------------------------------------------------------------*/
238/**
239 *
240 * This function assigns read/write function pointers to CPG read/write modules.
241 *
242 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
243 *
244 */
245VOID
246MemNInitCPGNb (
247 IN OUT MEM_NB_BLOCK *NBPtr
248 )
249{
250 NBPtr->WritePattern = MemNContWritePatternNb;
251 NBPtr->ReadPattern = MemNContReadPatternNb;
252 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
253}
254
255/* -----------------------------------------------------------------------------*/
256/**
257 *
258 * This function initializes member functions of HW Rx En Training.
259 *
260 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
261 *
262 */
263
264VOID
265MemNInitDqsTrainRcvrEnHwNb (
266 IN OUT MEM_NB_BLOCK *NBPtr
267 )
268{
269 NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
270}
271/* -----------------------------------------------------------------------------*/
272/**
273 *
274 * This function disables member functions of Hw Rx En Training.
275 *
276 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
277 *
278 */
279
280VOID
281MemNDisableDqsTrainRcvrEnHwNb (
282 IN OUT MEM_NB_BLOCK *NBPtr
283 )
284{
285 NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
286}
287
288/*----------------------------------------------------------------------------
289 * LOCAL FUNCTIONS
290 *
291 *----------------------------------------------------------------------------
292 */
293
294/* -----------------------------------------------------------------------------*/
295/**
296 *
297 * This function writes 9 or 18 cache lines continuously using GH CPG engine
298 *
299 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
300 * @param[in] Pattern - Array of bytes that will be written to DRAM
301 * @param[in] Address - System Address [47:16]
302 * @param[in] ClCount - Number of cache lines
303 *
304 */
305VOID
306STATIC
307MemNContWritePatternNb (
308 IN OUT MEM_NB_BLOCK *NBPtr,
309 IN UINT32 Address,
310 IN UINT8 Pattern[],
311 IN UINT16 ClCount
312 )
313{
314 UINT16 ClDiff;
315 if (ClCount > MAX_CL_CONT_WRITE) {
316 ClDiff = ClCount - MAX_CL_CONT_WRITE;
317 ClCount = MAX_CL_CONT_WRITE;
318 } else {
319 ClDiff = 0;
320 }
321
322 // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
323 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
324
325 // Issue the stream of writes. When F2x11C[MctWrLimit] is reached (or when F2x11C[FlushWr] is set
326 // again), all the writes are written to DRAM.
327 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
328 MemUWriteCachelines (Address, Pattern, ClCount);
329
330 // Flush out prior writes by setting F2x11C[FlushWr].
331 MemNSetBitFieldNb (NBPtr, BFFlushWr, 1);
332 // Wait for F2x11C[FlushWr] to clear, indicating prior writes have been flushed.
333 while (MemNGetBitFieldNb (NBPtr, BFFlushWr) != 0) {}
334
335 // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
336 MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
337
338 if (ClDiff > 0) {
339 MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
340 }
341}
342
343/* -----------------------------------------------------------------------------*/
344/**
345 *
346 *
347 * This function reads 9 or 18 cache lines continuously using GH CPG engine
348 *
349 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
350 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
351 * @param[in] Address - System Address [47:16]
352 * @param[in] ClCount - Number of cache lines
353 *
354 */
355
356VOID
357STATIC
358MemNContReadPatternNb (
359 IN OUT MEM_NB_BLOCK *NBPtr,
360 IN UINT8 Buffer[],
361 IN UINT32 Address,
362 IN UINT16 ClCount
363 )
364{
365 BOOLEAN DisAutoRefresh;
366 UINT16 ClDiff;
367 if (ClCount > MAX_CL_CONT_READ) {
368 ClDiff = ClCount - MAX_CL_CONT_READ;
369 ClCount = MAX_CL_CONT_READ;
370 } else {
371 ClDiff = 0;
372 }
373
374 Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
375
376 // 1. BIOS ensures that the only accesses outstanding to the MCT are training reads.
377 // 2. If F2x[1, 0]90[BurstLength32]=1, then BIOS ensures that the DCTs and DRAMs are configured for 64
378 // byte bursts (8-beat burst length). This requires that BIOS issue MRS commands to the devices
379 // to change to an 8-beat burst length and then to restore the desired burst length after training
380 // is complete.
381
382 if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
383 DisAutoRefresh = FALSE;
384 // 3. BIOS programs F2x[1, 0]90[ForceAutoPchg] = 0 and F2x[1, 0]8C[DisAutoRefresh] = 1.
385 // 4. If necessary, BIOS programs F2x[1, 0]78[EarlyArbEn] = 1 at this time. See register description.
386 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
387 // MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0); // ForceAutoPchg is 0 by default.
388 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
389 } else {
390 DisAutoRefresh = TRUE;
391 }
392
393 MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
394
395 // 5. BIOS sets F2x11C[MctPrefReqLimit] to the number of training reads (Ntrain) it wishes to generate in the
396 // training sequence.
397 MemNSetBitFieldNb (NBPtr, BFMctPrefReqLimit, ClCount - 1);
398
399 // 6. BIOS sets F2x11C[PrefDramTrainMode] bit.
400 // 7. The act of setting F2x11C[PrefDramTrainMode] causes the MCT to flush out the prefetch stride predictor
401 // table (removing any existing prefetch stride patterns).
402 MemNSetBitFieldNb (NBPtr, BFPrefDramTrainMode, 1);
403
404 // 8. BIOS issues an SFENCE (or other serializing instruction) to ensure that the prior write completes.
405 // 9. For revision C and earlier processors, BIOS generates two training reads. For revision D processors BIOS
406 // generates three training reads. Three are required to detect the stride with DCQ buddy enabled. These must
407 // be to consecutive cache lines (i.e. 64 bytes apart) and must not cross a naturally aligned 4 Kbyte boundary.
408 // 10. These reads set up a stride pattern which is detected by the prefetcher. The prefetcher then continues to
409 // issue prefetches until F2x11C[MctPrefReqLimit] is reached, at which point the MCT clears
410 // F2x11C[PrefDramTrainMode].
411 MemUDummyCLRead (Address);
412 MemUDummyCLRead (Address + 0x40);
413 if (NBPtr->IsSupported[CheckDummyCLRead]) {
414 MemUDummyCLRead (Address + 0x80);
415 }
416 // 11. BIOS issues the remaining (Ntrain - 2 for revisions C and earlier or Ntrain - 3 for revision D) reads after
417 // checking that F2x11C[PrefDramTrainMode] is cleared. These reads must be to consecutive cache lines
418 // (i.e., 64 bytes apart) and must not cross a naturally aligned 4KB boundary. These reads hit the prefetches
419 // and read the data from the prefetch buffer.
420 while (MemNGetBitFieldNb (NBPtr, BFPrefDramTrainMode) != 0) {}
421 MemUReadCachelines (Buffer, Address, ClCount);
422
423 // 14. BIOS restores the target values for F2x[1, 0]90[ForceAutoPchg], F2x[1, 0]8C[DisAutoRefresh] and
424 // F2x[1, 0]90[BurstLength32].
425 if (!DisAutoRefresh) {
426 MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
427 MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
428 }
429
430 if (ClDiff > 0) {
431 MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
432 }
433}
434
435/* -----------------------------------------------------------------------------*/
436/**
437 *
438 *
439 * This function generates a continuous burst of reads during HW RcvEn training.
440 *
441 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
442 * @param[in] Address - System Address [47:16]
443 *
444 */
445VOID
446STATIC
447MemNGenHwRcvEnReadsNb (
448 IN OUT MEM_NB_BLOCK *NBPtr,
449 IN UINT32 Address
450 )
451{
452 UINT8 TempBuffer[12 * 64];
453 UINT8 BurstCount;
454
455 for (BurstCount = 0; BurstCount < 10; BurstCount++) {
456 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
457 NBPtr->FlushPattern (NBPtr, Address, 12);
458 }
459}
460
461/* -----------------------------------------------------------------------------*/
462/**
463 *
464 * This function writes cache lines continuously using TCB CPG engine
465 *
466 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
467 * @param[in] Pattern - Array of bytes that will be written to DRAM
468 * @param[in] Address - System Address [47:16]
469 * @param[in] ClCount - Number of cache lines
470 *
471 */
472VOID
473STATIC
474MemNContWritePatternClientNb (
475 IN OUT MEM_NB_BLOCK *NBPtr,
476 IN UINT32 Address,
477 IN UINT8 Pattern[],
478 IN UINT16 ClCount
479 )
480{
481 UINT32 PatternHash;
482 UINT32 *DwordPtr;
483 UINT16 i;
484 UINT16 j;
485 UINT16 Multiplier;
486
487 Multiplier = 1;
488
489 // 1. Program D18F2x1C0[WrDramTrainMode]=1.
490 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
491
492 PatternHash = ClCount << 24;
493 for (i = 0; i < 3; i ++) {
494 PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
495 }
496 if (NBPtr->CPGInit != PatternHash) {
497
498 if (ClCount == 3) {
499 // Double pattern length for MaxRdLat training
500 Multiplier = 2;
501 }
502
503 // If write training buffer has not been initialized, initialize it
504 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
505 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
506
507 // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
508 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
509
510 // 4. Successively write each dword of the training pattern to D18F2x1D4.
511 DwordPtr = (UINT32 *) Pattern;
512 for (j = 0; j < Multiplier; j++) {
513 for (i = 0; i < (ClCount * 16); i++) {
514 MemNSetBitFieldNb (NBPtr, BFWrTrainBufDat, DwordPtr[i]);
515 }
516 }
517
518 NBPtr->CPGInit = PatternHash;
519 }
520
521 // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
522 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
523
524 // 6. Program the DRAM training address
525 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
526 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
527
528 // 7. Program D18F2x1C0[WrTrainGo]=1.
529 MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
530
531 // 8. Wait for D18F2x1C0[WrTrainGo]=0.
532 while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
533
534 // 9. Program D18F2x1C0[WrDramTrainMode]=0.
535 MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
536}
537
538/* -----------------------------------------------------------------------------*/
539/**
540 *
541 *
542 * This function reads cache lines continuously using TCB CPG engine
543 *
544 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
545 * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
546 * @param[in] Address - System Address [47:16]
547 * @param[in] ClCount - Number of cache lines
548 *
549 */
550
551VOID
552STATIC
553MemNContReadPatternClientNb (
554 IN OUT MEM_NB_BLOCK *NBPtr,
555 IN UINT8 Buffer[],
556 IN UINT32 Address,
557 IN UINT16 ClCount
558 )
559{
560 UINT16 Multiplier;
561
562 Multiplier = 1;
563 if (ClCount == 3) {
564 // Double pattern length for MaxRdLat training
565 Multiplier = 2;
566 }
567
568 // 1. Program D18F2x1C0[RdDramTrainMode]=1.
569 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
570
571 // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
572 MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
573
574 // 3. Program the DRAM training address as follows:
575 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
576 MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
577
578 // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
579 MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
580
581 // 5. Program D18F2x1C0[RdTrainGo]=1.
582 MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
583
584 // 6. Wait for D18F2x1C0[RdTrainGo]=0.
585 while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
586
587 // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
588 // This step will be accomplished in Compare routine.
589
590 // 8. Program D18F2x1C0[RdDramTrainMode]=0.
591 MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
592}
593
594/* -----------------------------------------------------------------------------*/
595/**
596 *
597 *
598 * This function generates a continuous burst of reads during HW RcvEn training.
599 *
600 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
601 * @param[in] Address - System Address [47:16]
602 *
603 */
604VOID
605STATIC
606MemNGenHwRcvEnReadsClientNb (
607 IN OUT MEM_NB_BLOCK *NBPtr,
608 IN UINT32 Address
609 )
610{
611 UINT8 TempBuffer[64];
612 UINT8 Count;
613
614 for (Count = 0; Count < 3; Count++) {
615 NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
616 }
617}
618
619/* -----------------------------------------------------------------------------*/
620/**
621 *
622 * This function assigns read/write function pointers to CPG read/write modules.
623 *
624 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
625 *
626 */
627VOID
628MemNInitCPGClientNb (
629 IN OUT MEM_NB_BLOCK *NBPtr
630 )
631{
632 NBPtr->WritePattern = MemNContWritePatternClientNb;
633 NBPtr->ReadPattern = MemNContReadPatternClientNb;
634 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsClientNb;
635 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
636 NBPtr->CompareTestPattern = MemNCompareTestPatternClientNb;
637 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternClientNb;
638 NBPtr->FamilySpecificHook[BeforeMemClr] = MemNBeforeMemClrClientNb;
639 NBPtr->CPGInit = 0;
640}
641
642/* -----------------------------------------------------------------------------*/
643/**
644 *
645 * This function compares test pattern with data in buffer and
646 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
647 *
648 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
649 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
650 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
651 * @param[in] ByteCount - Byte count
652 *
653 * @return PASS - Bitmap of results of comparison
654 */
655
656UINT16
657STATIC
658MemNCompareTestPatternClientNb (
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, BFTrainCmpSts));
666}
667
668/*-----------------------------------------------------------------------------*/
669/**
670 *
671 * This function compares test pattern with data in buffer and
672 * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
673 *
674 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
675 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
676 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
677 * @param[in] ByteCount - Byte count
678 *
679 * @retval Bitmap of results of comparison
680 */
681UINT16
682STATIC
683MemNInsDlyCompareTestPatternClientNb (
684 IN OUT MEM_NB_BLOCK *NBPtr,
685 IN UINT8 Buffer[],
686 IN UINT8 Pattern[],
687 IN UINT16 ByteCount
688 )
689{
690 return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
691}
692
693/* -----------------------------------------------------------------------------*/
694/**
695 *
696 * This function calculates RcvEn seed value for each rank
697 *
698 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
699 *
700 */
701VOID
702MemNPrepareRcvrEnDlySeedNb (
703 IN OUT MEM_NB_BLOCK *NBPtr
704 )
705{
706 MEM_TECH_BLOCK *TechPtr;
707 CH_DEF_STRUCT *ChannelPtr;
708 DIE_STRUCT *MCTPtr;
709 UINT16 SeedTotal;
710 UINT16 SeedFine;
711 UINT16 SeedGross;
712 UINT16 SeedPreGross;
713 UINT16 SeedTotalPreScaling;
714 UINT8 ByteLane;
715 UINT16 Speed;
716 UINT16 PlatEst;
717 UINT8 ChipSel;
718 UINT8 Pass;
719 UINT16 *PlatEstSeed;
720 UINT16 SeedValue[9];
721 UINT16 SeedTtl[9];
722 UINT16 SeedPre[9];
723
724 TechPtr = NBPtr->TechPtr;
725 MCTPtr = NBPtr->MCTPtr;
726 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
727 Speed = NBPtr->DCTPtr->Timings.Speed;
728 SeedTotalPreScaling = 0;
729 ChipSel = TechPtr->ChipSel;
730 Pass = TechPtr->Pass;
731
732 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
733 TechPtr->Bytelane = ByteLane;
734 if (Pass == 1) {
735 // Get platform override seed
736 PlatEstSeed = (UINT16 *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, MCTPtr->SocketId, ChannelPtr->ChannelID);
737 // For Pass1, BIOS starts with the delay value obtained from the first pass of write
738 // levelization training that was done in DDR3 Training and add a delay value of 3Bh.
739 PlatEst = 0x3B;
740 NBPtr->FamilySpecificHook[OverrideRcvEnSeed] (NBPtr, &PlatEst);
741 PlatEst = ((PlatEstSeed != NULL) ? PlatEstSeed[ByteLane] : PlatEst);
742 SeedTotal = ChannelPtr->WrDqsDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane] + PlatEst;
743 SeedValue[ByteLane] = PlatEst;
744 } else {
745 // For Pass2
746 // SeedTotalPreScaling = (the total delay values in D18F2x[1,0]9C_x0000_00[24:10] from pass 1 of
747 // DQS receiver enable training) - 20h. Subtract 1UI to get back to preamble left edge.
748 if ((ChipSel & 1) == 0) {
749 // Save Seed for odd CS SeedTotalPreScaling RxEn Value
750 TechPtr->PrevPassRcvEnDly[ByteLane] = ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane];
751 }
752 SeedTotalPreScaling = TechPtr->PrevPassRcvEnDly[ByteLane] - 0x20;
753 // SeedTotal = SeedTotalPreScaling*target frequency/lowest supported frequency.
754 SeedTotal = (UINT16) (((UINT32) SeedTotalPreScaling * Speed) / TechPtr->PrevSpeed);
755 NBPtr->FamilySpecificHook[OverrideRcvEnSeedPassN] (NBPtr, &SeedTotal);
756 }
757 SeedTtl[ByteLane] = SeedTotal;
758
759 // SeedGross = SeedTotal DIV 32.
760 SeedGross = SeedTotal >> 5;
761 // SeedFine = SeedTotal MOD 32.
762 SeedFine = SeedTotal & 0x1F;
763 // Next, determine the gross component of SeedTotal. SeedGrossPass1=SeedTotal DIV 32.
764 // Then, determine the fine delay component of SeedTotal. SeedFinePass1=SeedTotal MOD 32.
765 // Use SeedGrossPass1 to determine SeedPreGrossPass1:
766
767 if ((SeedGross & 0x1) != 0) {
768 //if SeedGross is odd
769 SeedPreGross = 1;
770 } else {
771 //if SeedGross is even
772 SeedPreGross = 2;
773 }
774 // (SeedGross - SeedPreGross)
775 TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
776
777 //BIOS programs registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 with SeedPreGrossPass1
778 //and SeedFinePass1 from the preceding steps.
779
780 NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
781 SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
782
783 // 202688: Program seed value to RcvEnDly also.
784 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
785 }
786
787 IDS_HDT_CONSOLE_DEBUG_CODE (
788 if (Pass == 1) {
789 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
790 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
791 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedValue[ByteLane]);
792 }
793 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
794 }
795 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedTotal: ");
796 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
797 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
798 }
799 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
800 for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
801 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
802 }
803 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
804 );
805}
806
807/* -----------------------------------------------------------------------------*/
808/**
809 *
810 * Waits specified number of MEMCLKs
811 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
812 * @param[in] MemClkCount - Number of MEMCLKs
813 *
814 * ----------------------------------------------------------------------------
815 */
816VOID
817MemNWaitXMemClksNb (
818 IN OUT MEM_NB_BLOCK *NBPtr,
819 IN UINT32 MemClkCount
820 )
821{
822 MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
823}
824
825/* -----------------------------------------------------------------------------*/
826/**
827 *
828 * Issues dummy TCB write read to zero out CL that is used for MemClr
829 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
830 * @param[in,out] *UnUsed - unused
831 *
832 * ----------------------------------------------------------------------------
833 */
834BOOLEAN
835STATIC
836MemNBeforeMemClrClientNb (
837 IN OUT MEM_NB_BLOCK *NBPtr,
838 IN VOID *UnUsed
839 )
840{
841 UINT8 Pattern[64];
842 UINT8 i;
843
844 for (i = 0; i < 64; i++) {
845 Pattern[i] = 0;
846 }
847
848 MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
849 MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
850 return TRUE;
851}
852
853/* -----------------------------------------------------------------------------*/
854/**
855 *
856 * This function uses the PRBS generator in the DCT to send a DDR Activate command
857 *
858 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
859 * @param[in] ChipSelect - Chip select 0-7
860 * @param[in] Bank - Bank Address 0-7
861 * @param[in] RowAddress - Row Address [17:0]
862 *
863 */
864
865VOID
866STATIC
867MemNRrwActivateCmd (
868 IN OUT MEM_NB_BLOCK *NBPtr,
869 IN UINT8 ChipSelect,
870 IN UINT8 Bank,
871 IN UINT32 RowAddress
872 )
873{
874 // Set Chip select
875 MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
876 // Set Bank Address
877 MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
878 // Set Row Address
879 MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
880 // Send the command
881 MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
882 // Wait for command complete
883 MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
884 // Wait 75 MEMCLKs
885 NBPtr->WaitXMemClks (NBPtr, 75);
886}
887
888/* -----------------------------------------------------------------------------*/
889/**
890 *
891 * This function uses the PRBS generator in the DCT to send a DDR Precharge
892 * or Precharge All command
893 *
894 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
895 * @param[in] ChipSelect - Chip select 0-7
896 * @param[in] Bank - Bank Address 0-7, PRECHARGE_ALL_BANKS = Precharge All
897 *
898 *
899 */
900
901VOID
902STATIC
903MemNRrwPrechargeCmd (
904 IN OUT MEM_NB_BLOCK *NBPtr,
905 IN UINT8 ChipSelect,
906 IN UINT8 Bank
907 )
908{
909 // Wait 25 MEMCLKs
910 NBPtr->WaitXMemClks (NBPtr, 25);
911 // Set Chip select
912 NBPtr->SetBitField (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
913 if (Bank == PRECHARGE_ALL_BANKS) {
914 // Set Row Address, bit 10
915 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) | (1 << 10) );
916 } else {
917 // Clear Row Address, bit 10
918 NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
919 // Set Bank Address
920 NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
921 }
922 // Send the command
923 NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
924 // Wait for command complete
925 NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
926 // Wait 25 MEMCLKs
927 NBPtr->WaitXMemClks (NBPtr, 25);
928}
929/* -----------------------------------------------------------------------------*/
930/**
931 *
932 *
933 * This function generates a continuous burst of reads for HW RcvEn
934 * training using the Unified Northbridge Reliable Read/Write Engine.
935 *
936 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
937 * @param[in] Address - Unused by this function
938 *
939 */
940VOID
941STATIC
942MemNGenHwRcvEnReadsUnb (
943 IN OUT MEM_NB_BLOCK *NBPtr,
944 IN UINT32 Address
945 )
946{
947 VOID *DummyPtr;
948 DummyPtr = NULL;
949 //
950 // Issue Stream of Reads from the Target Rank
951 //
efdesign9884cbce22011-08-04 12:09:17 -0600952 NBPtr->ReadPattern (NBPtr, DummyPtr, 0, NBPtr->TechPtr->PatternLength);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000953}
954
955/* -----------------------------------------------------------------------------*/
956/**
957 *
958 * This function generates a continuous stream of reads from DRAM using the
959 * Unified Northbridge Reliable Read/Write Engine.
960 *
961 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
962 * @param[in,out] Buffer - Unused by this function
963 * @param[in] Address - Unused by this function
964 * @param[in] ClCount - Number of cache lines to read
965 *
966 * Assumptions:
967 *
968 *
969 *
970 */
971
972VOID
973STATIC
974MemNContReadPatternUnb (
975 IN OUT MEM_NB_BLOCK *NBPtr,
976 IN UINT8 Buffer[],
977 IN UINT32 Address,
978 IN UINT16 ClCount
979 )
980{
981 MEM_TECH_BLOCK *TechPtr;
982 RRW_SETTINGS *Rrw;
983 UINT8 CmdTgt;
984 UINT8 ChipSel;
985
986 TechPtr = NBPtr->TechPtr;
987 Rrw = &NBPtr->RrwSettings;
988
989 ChipSel = TechPtr->ChipSel;
990 CmdTgt = Rrw->CmdTgt;
991 //
992 // Wait for RRW Engine to be ready and turn it on
993 //
994 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
995 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
996 //
997 // Depending upon the Cmd Target, send Row Activate and set Chipselect
998 // for the Row or Rows that will be used
999 //
1000 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1001 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1002 if (CmdTgt == CMD_TGT_AB) {
1003 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
1004 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
1005 }
1006 // Set Comparison Masks
1007 NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
1008 NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
1009 //
1010 // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
1011 //
1012 NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
1013 //
1014 // Program the PRBS Seed
1015 //
1016 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1017 //
1018 // Set the Command Count
1019 //
1020 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1021 //
1022 // Program the Bubble Count and CmdStreamLen
1023 //
1024 NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1025 NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1026 NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1027 //
1028 // Program the Starting Address
1029 //
1030 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1031 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1032 if (CmdTgt == CMD_TGT_AB) {
1033 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1034 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1035 }
1036 //
1037 // Reset All Errors and Disable StopOnErr
1038 //
1039 NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
1040 NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
1041 //
1042 // Program the CmdTarget
1043 //
1044 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1045 //
1046 // Set CmdType to read
1047 //
1048 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
1049 //
1050 // Start the Commands
1051 //
1052 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1053 //
1054 // Commands have started, wait for the reads to complete then clear the command
1055 //
1056 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1057 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1058 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1059 //
1060 // Send the Precharge All Command
1061 //
1062 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1063 //
1064 // Turn Off the RRW Engine
1065 //
1066 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1067}
1068
1069/* -----------------------------------------------------------------------------*/
1070/**
1071 *
1072 * This function generates a continuous stream of writes to DRAM using the
1073 * Unified Northbridge Reliable Read/Write Engine.
1074 *
1075 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1076 * @param[in,out] Address - Unused by this function
1077 * @param[in] Pattern - Unused by this function
1078 * @param[in] ClCount - Number of cache lines to write
1079 *
1080 */
1081
1082VOID
1083STATIC
1084MemNContWritePatternUnb (
1085 IN OUT MEM_NB_BLOCK *NBPtr,
1086 IN UINT32 Address,
1087 IN UINT8 Pattern[],
1088 IN UINT16 ClCount
1089 )
1090{
1091 MEM_TECH_BLOCK *TechPtr;
1092 RRW_SETTINGS *Rrw;
1093 UINT8 CmdTgt;
1094 UINT8 ChipSel;
1095
1096 TechPtr = NBPtr->TechPtr;
1097 Rrw = &NBPtr->RrwSettings;
1098
1099 ChipSel = TechPtr->ChipSel;
1100 CmdTgt = Rrw->CmdTgt;
1101 //
1102 // Wait for RRW Engine to be ready and turn it on
1103 //
1104 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1105 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
1106
1107 //
1108 // Depending upon the Cmd Target, send Row Activate and set Chipselect
1109 // for the Row or Rows that will be used
1110 //
1111 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
1112 NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
1113 if (CmdTgt == CMD_TGT_AB) {
1114 MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
1115 NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
1116 }
1117 //
1118 // Program the PRBS Seed
1119 //
1120 NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
1121 //
1122 // Set the Command Count
1123 //
1124 NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
1125 //
1126 // Program the Bubble Count and CmdStreamLen
1127 //
1128 NBPtr->SetBitField (NBPtr, BFBubbleCnt, 0);
1129 NBPtr->SetBitField (NBPtr, BFBubbleCnt2, 0);
1130 NBPtr->SetBitField (NBPtr, BFCmdStreamLen, 1);
1131 //
1132 // Program the Starting Address
1133 //
1134 NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
1135 NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
1136 if (CmdTgt == CMD_TGT_AB) {
1137 NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
1138 NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
1139 }
1140 //
1141 // Program the CmdTarget
1142 //
1143 NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
1144 //
1145 // Set CmdType to read
1146 //
1147 NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
1148 //
1149 // Start the Commands
1150 //
1151 NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
1152 //
1153 // Commands have started, wait for the writes to complete then clear the command
1154 //
1155 NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
1156 NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
1157 NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
1158 //
1159 // Send the Precharge All Command
1160 //
1161 MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
1162 //
1163 // Turn Off the RRW Engine
1164 //
1165 NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
1166}
1167
1168/* -----------------------------------------------------------------------------*/
1169/**
1170 *
1171 * This function checks the Error status bits for comparison results
1172 *
1173 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1174 * @param[in] Buffer[] - Not used in this implementation
1175 * @param[in] Pattern[] - Not used in this implementation
1176 * @param[in] ByteCount - Not used in this implementation
1177 *
1178 * @return PASS - Bitmap of results of comparison
1179 */
1180
1181UINT16
1182STATIC
1183MemNCompareTestPatternUnb (
1184 IN OUT MEM_NB_BLOCK *NBPtr,
1185 IN UINT8 Buffer[],
1186 IN UINT8 Pattern[],
1187 IN UINT16 ByteCount
1188 )
1189{
1190
1191
1192 UINT16 i;
1193 UINT16 Pass;
1194 UINT8 ChipSel;
1195 UINT8 ColumnCount;
1196 UINT8* FailingBitMaskPtr;
1197 UINT8 FailingBitMask[9];
1198 UINT32 NibbleErrSts;
1199
1200 ChipSel = NBPtr->TechPtr->ChipSel;
1201 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1202 // Calculate Failing Bitmask pointer
1203 FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
1204
1205 //
1206 // Get Failing bit data
1207 //
1208 *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
1209 *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
1210 FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
1211
1212 Pass = 0x0000;
1213 //
1214 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1215 //
1216 NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
1217
1218 for (i = 0; i < ColumnCount ; i++) {
1219 Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
1220 NibbleErrSts >>= 2;
1221 FailingBitMaskPtr[i] = FailingBitMask[i];
1222 }
1223 Pass = ~Pass;
1224 return Pass;
1225}
1226
1227/*-----------------------------------------------------------------------------*/
1228/**
1229 *
1230 * This function checks the Error status bits for offset comparison results
1231 *
1232 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
1233 * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
1234 * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
1235 * @param[in] ByteCount - Byte count
1236 *
1237 * @retval Bitmap of results of comparison
1238 */
1239UINT16
1240STATIC
1241MemNInsDlyCompareTestPatternUnb (
1242 IN OUT MEM_NB_BLOCK *NBPtr,
1243 IN UINT8 Buffer[],
1244 IN UINT8 Pattern[],
1245 IN UINT16 ByteCount
1246 )
1247{
1248 UINT16 i;
1249 UINT16 Pass;
1250 UINT8 ColumnCount;
1251 UINT32 NibbleErr180Sts;
1252
1253 ColumnCount = NBPtr->ChannelPtr->ColumnCount;
1254 Pass = 0x0000;
1255 //
1256 // Get Comparison Results - Convert Nibble Masks to Byte Masks
1257 //
1258 NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
1259
1260 for (i = 0; i < ColumnCount ; i++) {
1261 Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
1262 NibbleErr180Sts >>= 2;
1263 }
1264 Pass = ~Pass;
1265
1266 return Pass;
1267}
1268
1269/* -----------------------------------------------------------------------------*/
1270/**
1271 *
1272 * This function assigns read/write function pointers to CPG read/write modules.
1273 *
1274 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
1275 *
1276 */
1277VOID
1278MemNInitCPGUnb (
1279 IN OUT MEM_NB_BLOCK *NBPtr
1280 )
1281{
1282 NBPtr->WritePattern = MemNContWritePatternUnb;
1283 NBPtr->ReadPattern = MemNContReadPatternUnb;
1284 NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsUnb;
1285 NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
1286 NBPtr->TrainingPatternInit = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1287 NBPtr->TrainingPatternFinalize = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
1288 NBPtr->CompareTestPattern = MemNCompareTestPatternUnb;
1289 NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternUnb;
1290 NBPtr->FamilySpecificHook[SetupHwTrainingEngine] = MemNSetupHwTrainingEngineUnb;
1291 NBPtr->CPGInit = 0;
1292}
1293