AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Tech / mtthrcSeedTrain.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mtthrcSt.c
6  *
7  * Phy assisted DQS receiver enable seedless training
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Tech)
12  * @e \$Revision: 42643 $ @e \$Date: 2010-11-24 13:51:41 -0600 (Wed, 24 Nov 2010) $
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
54
55 #include "AGESA.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "mm.h"
59 #include "mn.h"
60 #include "mt.h"
61 #include "mttEdgeDetect.h"
62 #include "Filecode.h"
63 CODE_GROUP (G1_PEICC)
64 RDATA_GROUP (G2_PEI)
65
66 #define FILECODE PROC_MEM_TECH_MTTHRCSEEDTRAIN_FILECODE
67 /*----------------------------------------------------------------------------
68 3 *                          DEFINITIONS AND MACROS
69  *
70  *----------------------------------------------------------------------------
71  */
72
73 /*----------------------------------------------------------------------------
74  *                           TYPEDEFS AND STRUCTURES
75  *
76  *----------------------------------------------------------------------------
77  */
78
79 /*----------------------------------------------------------------------------
80  *                        PROTOTYPES OF LOCAL FUNCTIONS
81  *
82  *----------------------------------------------------------------------------
83  */
84
85 VOID
86 STATIC
87 MemTRdPosRxEnSeedSetDly3 (
88   IN OUT   MEM_TECH_BLOCK *TechPtr,
89   IN OUT   UINT16 RcvEnDly,
90   IN OUT   UINT8 ByteLane
91   );
92
93 VOID
94 STATIC
95 MemTRdPosRxEnSeedCheckRxEndly3 (
96   IN OUT   MEM_TECH_BLOCK *TechPtr
97   );
98 /*----------------------------------------------------------------------------
99  *                            EXPORTED FUNCTIONS
100  *
101  *----------------------------------------------------------------------------
102  */
103 /*----------------------------------------------------------------------------
104  *                              LOCAL FUNCTIONS
105  *
106  *----------------------------------------------------------------------------
107  */
108 /*-----------------------------------------------------------------------------
109  *
110  *
111  *     This function checks each bytelane for no window error.
112  *
113  *
114  *     @param[in,out]   *TechPtr   - Pointer to the MEM_TECH_BLOCK
115  *     @param[in,out]   OptParam   - Optional parameter
116  *
117  *     @return    TRUE
118  * ----------------------------------------------------------------------------
119  */
120 BOOLEAN
121 MemTTrackRxEnSeedlessRdWrNoWindBLError (
122   IN OUT   MEM_TECH_BLOCK *TechPtr,
123   IN OUT   VOID *OptParam
124   )
125 {
126   UINT8 i;
127   SWEEP_INFO SweepData;
128   SweepData = *(SWEEP_INFO*)OptParam;
129   for (i = 0; i < ((TechPtr->NBPtr->MCTPtr->Status[SbEccDimms] && TechPtr->NBPtr->IsSupported[EccByteTraining]) ? 9 : 8) ; i++) {
130     //
131     /// Skip Bytelanes that have already reached the desired result
132     //
133     if ((SweepData.ResultFound & ((UINT16)1 << i)) == 0) {
134       if (SweepData.TrnDelays[i] == SweepData.EndDelay) {
135         if ((SweepData.EndResult & ((UINT16) (1 << i))) != 0) {
136           TechPtr->ByteLaneError[i] = TRUE;
137         } else {
138           TechPtr->ByteLaneError[i] = FALSE;
139         }
140       }
141     }
142   }
143   return TRUE;
144 }
145 /*-----------------------------------------------------------------------------
146  *
147  *
148  *      This function checks each bytelane for small window error.
149  *
150  *
151  *     @param[in,out]   *TechPtr   - Pointer to the MEM_TECH_BLOCK
152  *     @param[in,out]   OptParam   - Optional parameter(Unused)
153  *
154  *     @return    TRUE
155  * ----------------------------------------------------------------------------
156  */
157 BOOLEAN
158 MemTTrackRxEnSeedlessRdWrSmallWindBLError (
159   IN OUT   MEM_TECH_BLOCK *TechPtr,
160   IN OUT   VOID *OptParam
161   )
162 {
163     TechPtr->ByteLaneError[TechPtr->Bytelane] = TRUE;
164   return TRUE;
165 }
166 /* -----------------------------------------------------------------------------*/
167 /**
168  *
169  *     This function sets the RxEn delay
170  *
171  *     @param[in,out]   *TechPtr   - Pointer to the MEM_TECH_BLOCK
172  *     @param[in,out]   *RcvEnDly   - Receiver Enable Delay
173  *     @param[in,out]   *ByteLane   - Bytelane
174  *
175 */
176 VOID
177 STATIC
178 MemTRdPosRxEnSeedSetDly3 (
179   IN OUT   MEM_TECH_BLOCK *TechPtr,
180   IN OUT   UINT16 RcvEnDly,
181   IN OUT   UINT8 ByteLane
182   )
183 {
184   TechPtr->NBPtr->ChannelPtr->RcvEnDlys[(TechPtr->ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane] = RcvEnDly;
185   TechPtr->NBPtr->SetTrainDly (TechPtr->NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((TechPtr->ChipSel >> 1), ByteLane), RcvEnDly);
186   TechPtr->NBPtr->FamilySpecificHook[ResetRxFifoPtr] (TechPtr->NBPtr, TechPtr->NBPtr);
187 }
188 /* -----------------------------------------------------------------------------*/
189 /**
190  *
191  *     This function determines if the currert RxEn delay settings have failed
192  *
193  *     @param[in,out]   *TechPtr   - Pointer to the MEM_TECH_BLOCK
194  *
195 */
196 VOID
197 STATIC
198 MemTRdPosRxEnSeedCheckRxEndly3 (
199   IN OUT   MEM_TECH_BLOCK *TechPtr
200   )
201 {
202   UINT8  MaxDlyDimm;
203   TechPtr->FindMaxDlyForMaxRdLat (TechPtr, &MaxDlyDimm);
204   TechPtr->NBPtr->SetMaxLatency (TechPtr->NBPtr, TechPtr->MaxDlyForMaxRdLat);
205   TechPtr->DqsRdWrPosSaved = 0;
206   MemTTrainDQSEdgeDetect (TechPtr);
207 }
208 /* -----------------------------------------------------------------------------*/
209 /**
210  *
211  *     This function executes RdDQS training and if fails adjusts the RxEn Gross results for
212  *     each bytelane
213  *
214  *     @param[in,out]   *TechPtr   - Pointer to the MEM_TECH_BLOCK
215  *
216  *     @return  TRUE - All bytelanes pass
217  *     @return  FALSE - Some bytelanes fail
218 */
219 BOOLEAN
220 MemTRdPosWithRxEnDlySeeds3 (
221   IN OUT   MEM_TECH_BLOCK *TechPtr
222   )
223 {
224   UINT8  ByteLane;
225   UINT16 PassTestRxEnDly[MAX_BYTELANES_PER_CHANNEL + 1];
226   UINT16 FailTestRxEnDly[MAX_BYTELANES_PER_CHANNEL + 1];
227   UINT16 FinalRxEnCycle[MAX_BYTELANES_PER_CHANNEL + 1];
228   UINT16 RxOrig[MAX_BYTELANES_PER_CHANNEL];
229   UINT8  i;
230   UINT8  j;
231   UINT8  NumBLWithTargetFound;
232   UINT8  MaxByteLanes;
233   INT16  RxEn;
234   BOOLEAN status;
235   BOOLEAN EsbNoDqsPosSave;
236   BOOLEAN OutOfRange[MAX_BYTELANES_PER_CHANNEL];
237   BOOLEAN ByteLanePass[MAX_BYTELANES_PER_CHANNEL];
238   BOOLEAN ByteLaneFail[MAX_BYTELANES_PER_CHANNEL];
239   BOOLEAN RxEnMemClkTested[MAX_BYTELANES_PER_CHANNEL][MAX_POS_RX_EN_SEED_GROSS_RANGE];
240   BOOLEAN RxEnMemClkSt[MAX_BYTELANES_PER_CHANNEL][MAX_POS_RX_EN_SEED_GROSS_RANGE];
241   BOOLEAN RxEnDlyTargetFound[MAX_BYTELANES_PER_CHANNEL];
242   BOOLEAN DlyWrittenToReg[MAX_BYTELANES_PER_CHANNEL];
243   UINT16 RxEnDlyTargetValue[MAX_BYTELANES_PER_CHANNEL];
244   UINT8 AllByteLanesOutOfRange;
245   UINT8 AllByteLanesSaved;
246   UINT8 TotalByteLanesCheckedForSaved;
247   UINT8  MemClkCycle;
248   MEM_NB_BLOCK  *NBPtr;
249   CH_DEF_STRUCT *ChannelPtr;
250   NBPtr = TechPtr->NBPtr;
251   ChannelPtr = TechPtr->NBPtr->ChannelPtr;
252   NumBLWithTargetFound = 0;
253   status = FALSE;
254   EsbNoDqsPosSave = TechPtr->NBPtr->MCTPtr->ErrStatus[EsbNoDqsPos];
255   NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_SUSPEND;
256   IDS_HDT_CONSOLE (MEM_FLOW, "\n\nStart HW RxEn Seedless training\n\n");
257   // 1. Program D18F2x9C_x0D0F_0[F,8:0]30_dct[1:0][BlockRxDqsLock] = 1.
258   NBPtr->SetBitField (NBPtr, BFBlockRxDqsLock, 0x0100);
259   IDS_HDT_CONSOLE (MEM_FLOW, "\tChip Select: %02x \n", TechPtr->ChipSel);
260   IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t       Byte:  00  01  02  03  04  05  06  07  ECC\n");
261   IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t\tRxEn Orig: ");
262   //
263   // Start sweep loops for RxEn Seedless Training
264   //
265   MaxByteLanes = (TechPtr->NBPtr->MCTPtr->Status[SbEccDimms] && TechPtr->NBPtr->IsSupported[EccByteTraining]) ? 9 : 8;    //dmach
266   //
267   //Initialialize BL variables
268   //
269   for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
270     OutOfRange[ByteLane] = FALSE;
271     ByteLanePass[ByteLane] = FALSE;
272     ByteLaneFail[ByteLane] = FALSE;
273     // 2. RxEnOrig = D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] result
274     //    from 2.10.6.8.2 [Phy Assisted DQS Receiver Enable Training]
275     RxOrig[ByteLane] = TechPtr->RxOrig[ByteLane]; // Original RxEn Dly based on PRE results
276     RxEnDlyTargetFound[ByteLane] = FALSE;
277     RxEnDlyTargetValue[ByteLane] = 0;
278     IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RxOrig[ByteLane]);
279     for (i = 0; i < MAX_POS_RX_EN_SEED_GROSS_RANGE; i++) {
280       RxEnMemClkTested[ByteLane][i] = FALSE;
281     }
282   }
283   // Start MemClk delay sweep
284   for (i = 0; i < MAX_POS_RX_EN_SEED_GROSS_RANGE; i++) {
285     IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\ti: %02x\n", i);
286     // Start direction sweep (0, - Positive, 1 - negative)
287     for (j = 0; j < MAX_POS_RX_EN_SEED_GROSS_DIR; j++) {
288       // Edge detect may run twice to see Pass to fail transition
289       // It is not run if the value are already saved
290       // Fail test is only done if pass is found
291       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tj: %02x\n", j);
292       // Reset Bytelane Flags for next sweep
293       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
294         ByteLaneFail[ByteLane] = FALSE;
295         ByteLanePass[ByteLane] = FALSE;
296         OutOfRange[ByteLane] = FALSE;
297       }
298       if (i == 0 && j == 1) {
299         continue; // Since i & j are the same skip
300       }
301       IDS_HDT_CONSOLE_DEBUG_CODE (
302         IDS_HDT_CONSOLE (MEM_FLOW, "\t             Byte:  00  01  02  03  04  05  06  07  ECC\n");
303         IDS_HDT_CONSOLE (MEM_FLOW, "\t  Target BL Found: ");
304         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
305          IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", ((RxEnDlyTargetFound[ByteLane] == TRUE) ? 'Y' : 'N'));
306         }
307         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t  Target BL Value: ");
308         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
309           IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RxEnDlyTargetValue[ByteLane]);
310         }
311       );
312       //
313       //  Find the RxEn Delay for the Pass condition in the Pass to Fail transition
314       //              "PassTestRxEnDly"
315       //
316       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t Setting PassTestRxEnDly\n");
317       IDS_HDT_CONSOLE (MEM_FLOW, "\t  PassTestRxEnDly: ");
318       PassTestRxEnDly[ByteLane] = RxOrig[ByteLane];
319       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
320         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
321           // Calculate "PassTestRxEnDly" from  current "RxEnDly"
322           // 3. RxEnOffset = MOD(RxEnOrig + 0x10, 0x40)
323           RxEn = (j == 0) ? ((INT16)RxOrig[ByteLane] + 0x10 + (0x40*i)) : ((INT16)RxOrig[ByteLane] + 0x10 - (0x40*i));
324           // Check if RxEnDly is in a valid range
325           if ((RxEn >= NBPtr->MinRxEnSeedGross) && (RxEn <= NBPtr->MaxRxEnSeedTotal)) {
326             PassTestRxEnDly[ByteLane] = (UINT16)RxEn;
327             // 4. For each DqsRcvEn value beginning from RxEnOffset incrementing by 1 MEMCLK:
328             //    A. Program D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] with
329             //    the current value.
330             MemTRdPosRxEnSeedSetDly3 (TechPtr, PassTestRxEnDly[ByteLane], ByteLane);
331             OutOfRange[ByteLane] = FALSE;
332           } else {
333             OutOfRange[ByteLane] = TRUE;
334           }
335         } else {
336           PassTestRxEnDly[ByteLane] = RxEnDlyTargetValue[ByteLane];
337         }
338         IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", PassTestRxEnDly[ByteLane]);
339       }
340       // Check if all BLs out of Range at "PassTestRxEnDly"
341       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t       OutOfRange: ");
342       AllByteLanesOutOfRange = 0;
343       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
344         if (OutOfRange[ByteLane]) {
345           AllByteLanesOutOfRange++;
346         }
347         IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
348       }
349       if (AllByteLanesOutOfRange == MaxByteLanes) {
350         continue;  // All BLs out of range, so skip
351       }
352       // Check if all BLs saved Results  at "PassTestRxEnDly"
353       AllByteLanesSaved = 0;
354       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
355         MemClkCycle = (UINT8) (PassTestRxEnDly[ByteLane] >> 5);
356         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
357           if (!RxEnMemClkTested[ByteLane][MemClkCycle]) {
358             AllByteLanesSaved++;
359           }
360         }
361       }
362       // Check if "RxEnDlyValueForPassCond" passed
363       if (AllByteLanesSaved != 0) {
364         // At least one BL has not been saved, so check if "PassTestRxEnDly" passed
365         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t Checking if PassTestRxEnDly Passes?\n\n");
366         // 4B. Perform 2.10.6.8.5 [DQS Position Training].
367         //     Record the result for the current DqsRcvEn setting as a pass or fail depending if a data eye is found.
368         MemTRdPosRxEnSeedCheckRxEndly3 (TechPtr);
369         IDS_HDT_CONSOLE_DEBUG_CODE (
370           IDS_HDT_CONSOLE (MEM_FLOW, "\n\t             Byte:  00  01  02  03  04  05  06  07  ECC\n");
371           IDS_HDT_CONSOLE (MEM_FLOW, "\t\t     Err Status: ");
372           for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
373             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (TechPtr->ByteLaneError[ByteLane] == TRUE) ? 'F' : 'P');
374           }
375         );
376       } else {
377         // All BLs saved, so use saved results for "PassTestRxEnDly"
378         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tAll BLs Saved at PassTestRxEnDly\n");
379         IDS_HDT_CONSOLE_DEBUG_CODE (
380           IDS_HDT_CONSOLE (MEM_FLOW, "\t             Byte:  00  01  02  03  04  05  06  07  ECC\n");
381           IDS_HDT_CONSOLE (MEM_FLOW, "\t    Save Err Stat: ");
382           for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
383             MemClkCycle = (UINT8) (PassTestRxEnDly[ByteLane] >> 5);
384             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", ((RxEnMemClkSt[ByteLane][MemClkCycle] == TRUE) ? 'F' : 'P'));
385           }
386         );
387       }
388       // Update Saved values for "PassTestRxEnDly"
389       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
390         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
391           if (OutOfRange[ByteLane] == FALSE) {
392             MemClkCycle = (UINT8) (PassTestRxEnDly[ByteLane] >> 5);
393             if (!RxEnMemClkTested[ByteLane][MemClkCycle]) {
394               RxEnMemClkTested[ByteLane][MemClkCycle] = TRUE;
395               RxEnMemClkSt[ByteLane][MemClkCycle] = TechPtr->ByteLaneError[ByteLane];
396             }
397           }
398         }
399       }
400       //
401       //  Find the RxEn Delay for the Fail condition in the Pass to Fail transition
402       //              "FailTestRxEnDly"
403       //
404       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
405         DlyWrittenToReg[ByteLane] = FALSE;
406       }
407       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
408         FailTestRxEnDly[ByteLane] = PassTestRxEnDly[ByteLane] + 0x40;
409       }
410       IDS_HDT_CONSOLE_DEBUG_CODE (
411         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t             Byte:  00  01  02  03  04  05  06  07  ECC\n");
412         IDS_HDT_CONSOLE (MEM_FLOW, "\t  FailTestRxEnDly: ");
413         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
414           IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", FailTestRxEnDly[ByteLane]);
415         }
416       );
417       // Check if all BLs Saved Results at FailTestRxEnDly
418       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tSetting FailTestRxEnDly");
419       AllByteLanesSaved = 0;
420       TotalByteLanesCheckedForSaved = 0;
421       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
422         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
423           MemClkCycle = (UINT8) (FailTestRxEnDly[ByteLane] >> 5);
424           // Check if RxEnDly + 40 is valid
425           if ((FailTestRxEnDly[ByteLane] >= NBPtr->MinRxEnSeedGross) && (FailTestRxEnDly[ByteLane] <= NBPtr->MaxRxEnSeedTotal)) {
426             if (RxEnMemClkTested[ByteLane][MemClkCycle]) {
427               AllByteLanesSaved++;
428             }
429             OutOfRange[ByteLane] = FALSE;
430           } else {
431             OutOfRange[ByteLane] = TRUE;
432           }
433           TotalByteLanesCheckedForSaved++;
434         }
435       }
436       // Check if all BLs out of Range condition at FailTestRxEnDly
437       AllByteLanesOutOfRange = 0;
438       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t       OutOfRange: ");
439       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
440         if (OutOfRange[ByteLane]) {
441           AllByteLanesOutOfRange++;
442         }
443         IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
444       }
445       if (AllByteLanesOutOfRange == MaxByteLanes) {
446         continue;  // All BLs out of range, so skip
447       }
448       // Setting FailTestRxEnDly for any BL that was not saved
449       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t  FailTestRxEnDly: ");
450       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
451         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
452           MemClkCycle = (UINT8) (PassTestRxEnDly[ByteLane] >> 5);
453           // Check if New RxEnDly has Passed
454           if ((RxEnMemClkTested[ByteLane][MemClkCycle] ? RxEnMemClkSt[ByteLane][MemClkCycle] : TechPtr->ByteLaneError[ByteLane]) == FALSE) {
455             if (OutOfRange[ByteLane] == FALSE) {
456               // BL has passed at "New RxEnDly", so check if "New RxEnDly" + 0x40 fails
457               MemClkCycle = (UINT8) (FailTestRxEnDly[ByteLane] >> 5);
458               if (!RxEnMemClkTested[ByteLane][MemClkCycle]) {
459                 // Only Set Delays for ByteLanes that have not been already tested
460                 MemTRdPosRxEnSeedSetDly3 (TechPtr, FailTestRxEnDly[ByteLane], ByteLane);
461                 DlyWrittenToReg[ByteLane] = TRUE;
462                 IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'Y');
463               } else {
464                 IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'N');
465               }
466               ByteLanePass[ByteLane] = TRUE;
467             } else {
468               IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'O');
469             }
470           } else {
471             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'F');
472           }
473         } else {
474           IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'N');
475         }
476       }
477       // Check if BLs that passed at PassTestRxEnDly fail at FailTestRxEnDly
478       if (AllByteLanesSaved != TotalByteLanesCheckedForSaved) {
479           // At least one BL has not been saved, so check if FailTestRxEnDly passed
480         IDS_HDT_CONSOLE (MEM_FLOW, "\n\n\t\t Checking if FailTestRxEnDly Fails?\n");
481         MemTRdPosRxEnSeedCheckRxEndly3 (TechPtr);
482         IDS_HDT_CONSOLE_DEBUG_CODE (
483           IDS_HDT_CONSOLE (MEM_FLOW, "\n\t         Byte:  00  01  02  03  04  05  06  07  ECC\n");
484           IDS_HDT_CONSOLE (MEM_FLOW, "\t     Err Status: ");
485           for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
486             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (TechPtr->ByteLaneError[ByteLane] == TRUE) ? 'F' : 'P');
487           }
488         );
489       } else {
490         // All BLs saved, so use saved results for FailTestRxEnDly
491         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tAll BLs Saved at PassTestRxEnDly\n");
492         IDS_HDT_CONSOLE_DEBUG_CODE (
493           IDS_HDT_CONSOLE (MEM_FLOW, "\t               Byte:  00  01  02  03  04  05  06  07  ECC\n");
494           IDS_HDT_CONSOLE (MEM_FLOW, "\t      Save Err Stat: ");
495           for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
496             MemClkCycle = (UINT8) (FailTestRxEnDly[ByteLane] >> 5);
497             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (RxEnMemClkSt[ByteLane][MemClkCycle] == TRUE) ? 'F' : 'P');
498           }
499         );
500       }
501       //
502       //  If BL failes at "FailTestRxEnDly" set FinalRxEnCycle
503       //
504       // Setting FinalRxEnCycle for any BL that Failed at FailTestRxEnDly
505       IDS_HDT_CONSOLE (MEM_FLOW, "\n   Set FinalRxEnCycle: ");
506       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
507         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
508           MemClkCycle = (UINT8) (FailTestRxEnDly[ByteLane] >> 5);
509           if (RxEnMemClkTested[ByteLane][MemClkCycle] ? RxEnMemClkSt[ByteLane][MemClkCycle] == TRUE : (TechPtr->ByteLaneError[ByteLane] && DlyWrittenToReg[ByteLane])) {
510             FinalRxEnCycle[ByteLane] = PassTestRxEnDly[ByteLane] - 0x10;
511             if (((UINT16) FinalRxEnCycle[ByteLane] >= NBPtr->MinRxEnSeedGross) && ((UINT16) FinalRxEnCycle[ByteLane] <= NBPtr->MaxRxEnSeedTotal)) {
512               // Since FailTestRxEnDly, we can set FinalRxEnCycle
513               MemTRdPosRxEnSeedSetDly3 (TechPtr, (UINT16) FinalRxEnCycle[ByteLane], ByteLane);
514               ByteLaneFail[ByteLane] = TRUE;
515               OutOfRange[ByteLane] = FALSE;
516               IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'Y');
517             } else {
518               OutOfRange[ByteLane] = TRUE;
519               IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'N');
520             }
521           } else {
522             IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'F');
523             OutOfRange[ByteLane] = FALSE;
524           }
525         } else {
526           IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", 'Y');
527         }
528       }
529       // Update Saved values for FailTestRxEnDly
530       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
531         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
532           if (OutOfRange[ByteLane] == FALSE) {
533             MemClkCycle = (UINT8) (FailTestRxEnDly[ByteLane] >> 5);
534             if (!RxEnMemClkTested[ByteLane][MemClkCycle] && DlyWrittenToReg[ByteLane]) {
535               RxEnMemClkTested[ByteLane][MemClkCycle] = TRUE;
536               RxEnMemClkSt[ByteLane][MemClkCycle] = TechPtr->ByteLaneError[ByteLane];
537             }
538           }
539         }
540       }
541       // Check for out of Range condition
542       AllByteLanesOutOfRange = 0;
543       IDS_HDT_CONSOLE (MEM_FLOW, "\n\t       OutOfRange: ");
544       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
545         if (OutOfRange[ByteLane]) {
546           AllByteLanesOutOfRange++;
547         }
548         IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
549       }
550       if (AllByteLanesOutOfRange == MaxByteLanes) {
551         continue; // All BLs out of range so skip
552       }
553       IDS_HDT_CONSOLE_DEBUG_CODE (
554         IDS_HDT_CONSOLE (MEM_FLOW, "\n     FinalRxEnCycle: ");
555         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
556           IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", (UINT16) FinalRxEnCycle[ByteLane]);
557         }
558         IDS_HDT_CONSOLE (MEM_FLOW, "\n       ByteLaneFail: ");
559         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
560           IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (ByteLaneFail[ByteLane] == TRUE) ? 'Y' : 'N');
561         }
562         IDS_HDT_CONSOLE (MEM_FLOW, "\n       ByteLanePass: ");
563         for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
564           IDS_HDT_CONSOLE (MEM_FLOW, " %c  ", (ByteLanePass[ByteLane] == TRUE) ? 'Y' : 'N');
565         }
566       );
567       //
568       // Check for exit condition
569       // PassTestRxEnDly = Pass and FailTestRxEnDly[ByteLane] = Fail
570       // If found, use "FinalRxEnCycle" as final RxEnDly value
571       //
572       // 5. Process the array of results and determine a pass-to-fail transition.
573       NumBLWithTargetFound = 0;
574       for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
575         if (RxEnDlyTargetFound[ByteLane] == FALSE) {
576           // Check if the current BL has found its target
577           if (ByteLanePass[ByteLane] == TRUE && ByteLaneFail[ByteLane] == TRUE) {
578             RxEnDlyTargetFound[ByteLane] = TRUE;
579             NumBLWithTargetFound++;
580             RxEnDlyTargetValue[ByteLane] = FinalRxEnCycle[ByteLane];
581           } else {
582             RxEnDlyTargetFound[ByteLane] = FALSE;
583           }
584         } else {
585           // BL has already failed and passed, so increment both flags
586           NumBLWithTargetFound++;
587         }
588       }
589       IDS_HDT_CONSOLE (MEM_FLOW, "\n");
590       // Check for exit condition
591       if (NumBLWithTargetFound == MaxByteLanes) {
592         // Exit condition found, so setting new RDQS based on RxEn-0x10 \n\n
593         IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t Setting new RDQS based on FinalRxEnCycle \n\n");
594         // 5 A. DqsRcvEnCycle = the total delay value of the pass result.
595         //   B. Program D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] =
596         //   DqsRcvEnCycle - 0x10.
597         NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_NEEDED;
598         MemTRdPosRxEnSeedCheckRxEndly3 (TechPtr);
599         IDS_HDT_CONSOLE (MEM_FLOW, "\n");
600         status = TRUE;
601         break;
602       } else {
603         status = FALSE;
604       }
605     }
606     // Check for exit condition
607     if (NumBLWithTargetFound == MaxByteLanes) {
608       status = TRUE;
609       break;
610     } else {
611       status = FALSE;
612     }
613     IDS_HDT_CONSOLE (MEM_FLOW, "\n");
614   }
615   TechPtr->NBPtr->MCTPtr->ErrStatus[EsbNoDqsPos] = EsbNoDqsPosSave;
616   if (i == MAX_POS_RX_EN_SEED_GROSS_RANGE) {
617     TechPtr->NBPtr->MCTPtr->ErrStatus[EsbNoDqsPos] = TRUE;
618   }
619
620   // 6. Program D18F2x9C_x0D0F_0[F,8:0]30_dct[1:0][BlockRxDqsLock] = 0.
621   NBPtr->SetBitField (NBPtr, BFBlockRxDqsLock, 0);
622   IDS_HDT_CONSOLE (MEM_FLOW, "\nEnd HW RxEn Seedless training\n\n");
623   return status;
624 }