7 * New Technology Software based DQS receiver enable training
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/Tech)
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
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 *----------------------------------------------------------------------------
56 #include "AdvancedApi.h"
67 #define FILECODE PROC_MEM_TECH_MTTOPTSRC_FILECODE
68 /*----------------------------------------------------------------------------
69 * DEFINITIONS AND MACROS
71 *----------------------------------------------------------------------------
74 /*----------------------------------------------------------------------------
75 * TYPEDEFS AND STRUCTURES
77 *----------------------------------------------------------------------------
80 /*----------------------------------------------------------------------------
81 * PROTOTYPES OF LOCAL FUNCTIONS
83 *----------------------------------------------------------------------------
88 MemTDqsTrainOptRcvrEnSw (
89 IN OUT MEM_TECH_BLOCK *TechPtr,
94 MemTNewRevTrainingSupport (
95 IN OUT MEM_TECH_BLOCK *TechPtr
101 /*----------------------------------------------------------------------------
104 *----------------------------------------------------------------------------
107 /* -----------------------------------------------------------------------------*/
110 * This function executes first pass of receiver enable training for all dies
112 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
114 * @return TRUE - No fatal error occurs.
115 * @return FALSE - Fatal error occurs.
119 MemTTrainOptRcvrEnSwPass1 (
120 IN OUT MEM_TECH_BLOCK *TechPtr
123 return MemTDqsTrainOptRcvrEnSw (TechPtr, 1);
126 /*----------------------------------------------------------------------------
129 *----------------------------------------------------------------------------
132 /* -----------------------------------------------------------------------------*/
135 * This function executes receiver enable training for a specific die
137 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
138 * @param[in] Pass - Pass of the receiver training
140 * @return TRUE - No fatal error occurs.
141 * @return FALSE - Fatal error occurs.
145 MemTDqsTrainOptRcvrEnSw (
146 IN OUT MEM_TECH_BLOCK *TechPtr,
150 _16BYTE_ALIGN UINT8 PatternBuffer[6 * 64];
151 UINT8 TestBuffer[256];
152 UINT8 *PatternBufPtr[6];
154 UINT32 TestAddrRJ16[4];
165 UINT16 RcvrEnDlyLimit;
172 MEM_DATA_STRUCT *MemPtr;
177 NBPtr = TechPtr->NBPtr;
178 MemPtr = NBPtr->MemPtr;
179 MCTPtr = NBPtr->MCTPtr;
180 TechPtr->TrainingType = TRN_RCVR_ENABLE;
186 TimesRetrain = DEFAULT_TRAINING_TIMES;
187 IDS_OPTION_HOOK (IDS_MEM_RETRAIN_TIMES, &TimesRetrain, &MemPtr->StdHeader);
189 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Optimized SW RxEn training\n");
190 // Set environment settings before training
191 MemTBeginTraining (TechPtr);
193 PatternBufPtr[0] = PatternBufPtr[2] = PatternBuffer;
194 // These two patterns used for first Test Address
195 MemUFillTrainPattern (TestPattern0, PatternBufPtr[0], 64);
196 // Second Cacheline used for Dummy Read is the inverse of
197 // the first so that is is not mistaken for the real read
198 MemUFillTrainPattern (TestPattern1, PatternBufPtr[0] + 64, 64);
199 PatternBufPtr[1] = PatternBufPtr[3] = PatternBufPtr[0] + 128;
200 // These two patterns used for second Test Address
201 MemUFillTrainPattern (TestPattern1, PatternBufPtr[1], 64);
202 // Second Cacheline used for Dummy Read is the inverse of
203 // the first so that is is not mistaken for the real read
204 MemUFillTrainPattern (TestPattern0, PatternBufPtr[1] + 64, 64);
206 // Fill pattern for flush after every sweep
207 PatternBufPtr[4] = PatternBufPtr[0] + 256;
208 MemUFillTrainPattern (TestPattern3, PatternBufPtr[4], 64);
210 // Fill pattern for initial dummy read
211 PatternBufPtr[5] = PatternBufPtr[0] + 320;
212 MemUFillTrainPattern (TestPattern4, PatternBufPtr[5], 64);
215 // Begin receiver enable training
216 AGESA_TESTPOINT (TpProcMemReceiverEnableTraining, &(MemPtr->StdHeader));
217 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
218 IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
219 NBPtr->SwitchDCT (NBPtr, Dct);
220 DCTPtr = NBPtr->DCTPtr;
223 NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 1);
225 // Relax Max Latency before training
226 NBPtr->SetMaxLatency (NBPtr, 0xFFFF);
228 if (Pass == FIRST_PASS) {
229 TechPtr->InitDQSPos4RcvrEn (TechPtr);
232 // there are four receiver pairs, loosely associated with chipselects.
233 Receiver = DCTPtr->Timings.CsEnabled ? 0 : 8;
234 for (; Receiver < 8; Receiver += 2) {
235 S0En = NBPtr->GetSysAddr (NBPtr, Receiver, &TestAddrRJ16[0]);
236 S1En = NBPtr->GetSysAddr (NBPtr, Receiver + 1, &TestAddrRJ16[2]);
238 TestAddrRJ16[1] = TestAddrRJ16[0] + BIGPAGE_X8_RJ16;
241 TestAddrRJ16[3] = TestAddrRJ16[2] + BIGPAGE_X8_RJ16;
249 IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", Receiver);
251 RcvrEnDlyLimit = 0x1FF; // @attention - limit depends on proc type
252 TechPtr->DqsRcvEnSaved = 0;
253 RcvrEnDly = RcvrEnDlyLimit;
256 TechPtr->GetFirstPassVal = FALSE;
257 TechPtr->DqsRcvEnFirstPassVal = 0;
258 TechPtr->RevertPassVal = FALSE;
259 TechPtr->InitializeVariablesOpt (TechPtr);
261 // Write the test patterns
262 AGESA_TESTPOINT (TpProcMemRcvrWritePattern, &(MemPtr->StdHeader));
263 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrite to addresses: ");
264 for (i = (S0En ? 0 : 2); i < (S1En ? 4 : 2); i++) {
265 RealAddr = MemUSetUpperFSbase (TestAddrRJ16[i], MemPtr);
266 // One cacheline of data to be tested and one of dummy data
267 MemUWriteCachelines (RealAddr, PatternBufPtr[i], 2);
268 // This is dummy data with a different pattern used for the first dummy read.
269 MemUWriteCachelines (RealAddr + 128, PatternBufPtr[5], 1);
270 IDS_HDT_CONSOLE (MEM_FLOW, " %04x0000 ", TestAddrRJ16[i]);
272 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
274 // Sweep receiver enable delays
275 AGESA_TESTPOINT (TpProcMemRcvrStartSweep, &(MemPtr->StdHeader));
277 ERROR_HANDLE_RETRAIN_BEGIN (TimesFail, TimesRetrain)
279 TechPtr->LoadInitialRcvrEnDlyOpt (TechPtr, Receiver);
280 while (!TechPtr->CheckRcvrEnDlyLimitOpt (TechPtr)) {
281 AGESA_TESTPOINT (TpProcMemRcvrSetDelay, &(MemPtr->StdHeader));
282 TechPtr->SetRcvrEnDlyOpt (TechPtr, Receiver, RcvrEnDly);
283 // Read and compare the first beat of data
284 for (i = (S0En ? 0 : 2); i < (S1En ? 4 : 2); i++) {
285 AGESA_TESTPOINT (TpProcMemRcvrReadPattern, &(MemPtr->StdHeader));
286 RealAddr = MemUSetUpperFSbase (TestAddrRJ16[i], MemPtr);
288 // Issue dummy cacheline reads
290 #if 0 //KR make OPT DQS Receiver Enable training happy
291 MemUReadCachelines (TestBuffer + 128, RealAddr + 128, 1);
292 MemUReadCachelines (TestBuffer, RealAddr, 1);
294 MemUProcIOClFlush (TestAddrRJ16[i], 2, MemPtr);
296 // Perform actual read which will be compared
298 MemUReadCachelines (TestBuffer + 64, RealAddr + 64, 1);
299 AGESA_TESTPOINT (TpProcMemRcvrTestPattern, &(MemPtr->StdHeader));
300 CurTest[i] = TechPtr->Compare1ClPatternOpt (TechPtr, TestBuffer + 64 , PatternBufPtr[i] + 64, i, Receiver, S1En);
301 // Due to speculative execution during MemUReadCachelines, we must
302 // flush one more cache line than we read.
303 MemUProcIOClFlush (TestAddrRJ16[i], 4, MemPtr);
304 TechPtr->ResetDCTWrPtr (TechPtr, Receiver);
307 // Swap the test pointers such that even and odd steps alternate.
310 TempPtr = PatternBufPtr[i];
311 PatternBufPtr[i] = PatternBufPtr[i + 1];
313 TempAddrRJ16 = TestAddrRJ16[i];
314 TestAddrRJ16[i] = TestAddrRJ16[i + 1];
316 PatternBufPtr[i] = TempPtr;
317 TestAddrRJ16[i] = TempAddrRJ16;
320 } // End of delay sweep
321 ERROR_HANDLE_RETRAIN_END (!TechPtr->SetSweepErrorOpt (TechPtr, Receiver, Dct, TRUE), TimesFail)
324 if (!TechPtr->SetSweepErrorOpt (TechPtr, Receiver, Dct, FALSE)) {
328 TechPtr->LoadRcvrEnDlyOpt (TechPtr, Receiver); // set final delays
330 // Flush AA and 55 patterns by reading a dummy pattern to fill in FIFO
332 // Aquire a new FSBase, based on the last test address that we stored.
333 RealAddr = MemUSetUpperFSbase (TempAddrRJ16, MemPtr);
334 ASSERT (RealAddr != 0);
335 MemUWriteCachelines (RealAddr, PatternBufPtr[4], 1);
336 MemUWriteCachelines (RealAddr + 64, PatternBufPtr[4], 1);
337 MemUReadCachelines (TestBuffer, RealAddr, 2);
338 // Due to speculative execution during MemUReadCachelines, we must
339 // flush one more cache line than we read.
340 MemUProcIOClFlush (TempAddrRJ16, 3, MemPtr);
342 } // End while Receiver < 8
344 // Clear training bit when done
345 NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 0);
347 // Set Max Latency for both channels
348 MaxRcvrEnDly = TechPtr->GetMaxValueOpt (TechPtr);
349 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRcvrEnDly: %03x\n", MaxRcvrEnDly);
350 if (MCTPtr->GangedMode) {
352 MaxDelayCha = MaxRcvrEnDly;
353 } else if (MaxRcvrEnDly > MaxDelayCha) {
354 NBPtr->SwitchDCT (NBPtr, 0);
355 NBPtr->SetMaxLatency (NBPtr, MaxRcvrEnDly);
358 NBPtr->SetMaxLatency (NBPtr, MaxRcvrEnDly);
360 TechPtr->ResetDCTWrPtr (TechPtr, 6);
363 // Restore environment settings after training
364 MemTEndTraining (TechPtr);
365 IDS_HDT_CONSOLE (MEM_FLOW, "End Optimized SW RxEn training\n\n");
366 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
369 /*-----------------------------------------------------------------------------
371 * This function saves passing DqsRcvEnDly values to the stack
373 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
374 * @param[in] Receiver - Current Chip select value
375 * @param[in] RcvEnDly - receiver enable delay to be saved
376 * @param[in] cmpResultRank0 - compare result for Rank 0
377 * @param[in] cmpResultRank0 - compare result for Rank 1
379 * @retval TRUE - All bytelanes pass
380 * FALSE - Some bytelanes fail
381 * ----------------------------------------------------------------------------
385 MemTSaveRcvrEnDlyByteFilterOpt (
386 IN OUT MEM_TECH_BLOCK *TechPtr,
389 IN UINT16 CmpResultRank0,
390 IN UINT16 CmpResultRank1
396 CH_DEF_STRUCT *ChannelPtr;
398 ASSERT (Receiver < MAX_CS_PER_CHANNEL);
399 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
401 Passed = (UINT8) ((CmpResultRank0 & CmpResultRank1) & 0xFF);
403 Dimm = Receiver >> 1;
405 if (TechPtr->GetFirstPassVal && (RcvEnDly - TechPtr->DqsRcvEnFirstPassVal) >= 0x30) {
406 for (i = 0; i < 8; i++) {
407 ChannelPtr->RcvEnDlys[Dimm * TechPtr->DlyTableWidth () + i] = TechPtr->DqsRcvEnFirstPassVal + NEW_RECEIVER_FINAL_OFFSETVALUE;
409 TechPtr->DqsRcvEnSaved = 0xFF;
412 if (Passed == 0xFF) {
413 if (!TechPtr->GetFirstPassVal) {
414 TechPtr->DqsRcvEnFirstPassVal = RcvEnDly;
415 TechPtr->GetFirstPassVal = TRUE;
419 TechPtr->DqsRcvEnFirstPassVal = 0;
421 // We have got first passing value, but later, we meet with glitch
422 if (TechPtr->GetFirstPassVal) {
423 TechPtr->DqsRcvEnFirstPassVal = 0xFF;
424 TechPtr->GetFirstPassVal = FALSE;