7 * Phy assisted DQS receiver enable seedless training
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/Tech)
12 * @e \$Revision: 42643 $ @e \$Date: 2010-11-24 13:51:41 -0600 (Wed, 24 Nov 2010) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
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.
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.
42 * ***************************************************************************
47 *----------------------------------------------------------------------------
50 *----------------------------------------------------------------------------
61 #include "mttEdgeDetect.h"
66 #define FILECODE PROC_MEM_TECH_MTTHRCSEEDTRAIN_FILECODE
67 /*----------------------------------------------------------------------------
68 3 * DEFINITIONS AND MACROS
70 *----------------------------------------------------------------------------
73 /*----------------------------------------------------------------------------
74 * TYPEDEFS AND STRUCTURES
76 *----------------------------------------------------------------------------
79 /*----------------------------------------------------------------------------
80 * PROTOTYPES OF LOCAL FUNCTIONS
82 *----------------------------------------------------------------------------
87 MemTRdPosRxEnSeedSetDly3 (
88 IN OUT MEM_TECH_BLOCK *TechPtr,
89 IN OUT UINT16 RcvEnDly,
95 MemTRdPosRxEnSeedCheckRxEndly3 (
96 IN OUT MEM_TECH_BLOCK *TechPtr
98 /*----------------------------------------------------------------------------
101 *----------------------------------------------------------------------------
103 /*----------------------------------------------------------------------------
106 *----------------------------------------------------------------------------
108 /*-----------------------------------------------------------------------------
111 * This function checks each bytelane for no window error.
114 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
115 * @param[in,out] OptParam - Optional parameter
118 * ----------------------------------------------------------------------------
121 MemTTrackRxEnSeedlessRdWrNoWindBLError (
122 IN OUT MEM_TECH_BLOCK *TechPtr,
123 IN OUT VOID *OptParam
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++) {
131 /// Skip Bytelanes that have already reached the desired result
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;
138 TechPtr->ByteLaneError[i] = FALSE;
145 /*-----------------------------------------------------------------------------
148 * This function checks each bytelane for small window error.
151 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
152 * @param[in,out] OptParam - Optional parameter(Unused)
155 * ----------------------------------------------------------------------------
158 MemTTrackRxEnSeedlessRdWrSmallWindBLError (
159 IN OUT MEM_TECH_BLOCK *TechPtr,
160 IN OUT VOID *OptParam
163 TechPtr->ByteLaneError[TechPtr->Bytelane] = TRUE;
166 /* -----------------------------------------------------------------------------*/
169 * This function sets the RxEn delay
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
178 MemTRdPosRxEnSeedSetDly3 (
179 IN OUT MEM_TECH_BLOCK *TechPtr,
180 IN OUT UINT16 RcvEnDly,
181 IN OUT UINT8 ByteLane
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);
188 /* -----------------------------------------------------------------------------*/
191 * This function determines if the currert RxEn delay settings have failed
193 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
198 MemTRdPosRxEnSeedCheckRxEndly3 (
199 IN OUT MEM_TECH_BLOCK *TechPtr
203 TechPtr->FindMaxDlyForMaxRdLat (TechPtr, &MaxDlyDimm);
204 TechPtr->NBPtr->SetMaxLatency (TechPtr->NBPtr, TechPtr->MaxDlyForMaxRdLat);
205 TechPtr->DqsRdWrPosSaved = 0;
206 MemTTrainDQSEdgeDetect (TechPtr);
208 /* -----------------------------------------------------------------------------*/
211 * This function executes RdDQS training and if fails adjusts the RxEn Gross results for
214 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
216 * @return TRUE - All bytelanes pass
217 * @return FALSE - Some bytelanes fail
220 MemTRdPosWithRxEnDlySeeds3 (
221 IN OUT MEM_TECH_BLOCK *TechPtr
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];
231 UINT8 NumBLWithTargetFound;
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;
249 CH_DEF_STRUCT *ChannelPtr;
250 NBPtr = TechPtr->NBPtr;
251 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
252 NumBLWithTargetFound = 0;
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: ");
263 // Start sweep loops for RxEn Seedless Training
265 MaxByteLanes = (TechPtr->NBPtr->MCTPtr->Status[SbEccDimms] && TechPtr->NBPtr->IsSupported[EccByteTraining]) ? 9 : 8; //dmach
267 //Initialialize BL variables
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;
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;
298 if (i == 0 && j == 1) {
299 continue; // Since i & j are the same skip
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'));
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]);
313 // Find the RxEn Delay for the Pass condition in the Pass to Fail transition
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;
333 OutOfRange[ByteLane] = TRUE;
336 PassTestRxEnDly[ByteLane] = RxEnDlyTargetValue[ByteLane];
338 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", PassTestRxEnDly[ByteLane]);
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++;
347 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
349 if (AllByteLanesOutOfRange == MaxByteLanes) {
350 continue; // All BLs out of range, so skip
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]) {
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');
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'));
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];
401 // Find the RxEn Delay for the Fail condition in the Pass to Fail transition
404 for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
405 DlyWrittenToReg[ByteLane] = FALSE;
407 for (ByteLane = 0; ByteLane < MaxByteLanes; ByteLane++) {
408 FailTestRxEnDly[ByteLane] = PassTestRxEnDly[ByteLane] + 0x40;
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]);
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]) {
429 OutOfRange[ByteLane] = FALSE;
431 OutOfRange[ByteLane] = TRUE;
433 TotalByteLanesCheckedForSaved++;
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++;
443 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
445 if (AllByteLanesOutOfRange == MaxByteLanes) {
446 continue; // All BLs out of range, so skip
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');
464 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'N');
466 ByteLanePass[ByteLane] = TRUE;
468 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'O');
471 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'F');
474 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'N');
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');
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');
502 // If BL failes at "FailTestRxEnDly" set FinalRxEnCycle
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');
518 OutOfRange[ByteLane] = TRUE;
519 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'N');
522 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'F');
523 OutOfRange[ByteLane] = FALSE;
526 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", 'Y');
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];
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++;
548 IDS_HDT_CONSOLE (MEM_FLOW, " %c ", (OutOfRange[ByteLane] == TRUE) ? 'Y' : 'N');
550 if (AllByteLanesOutOfRange == MaxByteLanes) {
551 continue; // All BLs out of range so skip
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]);
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');
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');
568 // Check for exit condition
569 // PassTestRxEnDly = Pass and FailTestRxEnDly[ByteLane] = Fail
570 // If found, use "FinalRxEnCycle" as final RxEnDly value
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];
582 RxEnDlyTargetFound[ByteLane] = FALSE;
585 // BL has already failed and passed, so increment both flags
586 NumBLWithTargetFound++;
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");
606 // Check for exit condition
607 if (NumBLWithTargetFound == MaxByteLanes) {
613 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
615 TechPtr->NBPtr->MCTPtr->ErrStatus[EsbNoDqsPos] = EsbNoDqsPosSave;
616 if (i == MAX_POS_RX_EN_SEED_GROSS_RANGE) {
617 TechPtr->NBPtr->MCTPtr->ErrStatus[EsbNoDqsPos] = TRUE;
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");