blob: 4ad3ea8db7c939b5abce24867f630edaf356773d [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mttsrc.c
6 *
7 * Technology Software based DQS receiver enable training
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/Tech)
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 **/
15/*****************************************************************************
16*
Siyuan Wang641f00c2013-06-08 11:50:55 +080017 * Copyright (c) 2008 - 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.
zbao7d94cf92012-07-02 14:19:14 +080041* ***************************************************************************
42*
43*/
44
45/*
46 *----------------------------------------------------------------------------
47 * MODULES USED
48 *
49 *----------------------------------------------------------------------------
50 */
51
52
53
54#include "AGESA.h"
55#include "AdvancedApi.h"
56#include "Ids.h"
57#include "mm.h"
58#include "mn.h"
59#include "mu.h"
60#include "mt.h"
61#include "GeneralServices.h"
62#include "merrhdl.h"
63#include "Filecode.h"
64CODE_GROUP (G1_PEICC)
65RDATA_GROUP (G1_PEICC)
66
67#define FILECODE PROC_MEM_TECH_MTTSRC_FILECODE
68/*----------------------------------------------------------------------------
69 * DEFINITIONS AND MACROS
70 *
71 *----------------------------------------------------------------------------
72 */
73
74/*----------------------------------------------------------------------------
75 * TYPEDEFS AND STRUCTURES
76 *
77 *----------------------------------------------------------------------------
78 */
79
80/*----------------------------------------------------------------------------
81 * PROTOTYPES OF LOCAL FUNCTIONS
82 *
83 *----------------------------------------------------------------------------
84 */
85
86BOOLEAN
87STATIC
88MemTDqsTrainRcvrEnSw (
89 IN OUT MEM_TECH_BLOCK *TechPtr,
90 IN UINT8 Pass
91 );
92
93/*----------------------------------------------------------------------------
94 * EXPORTED FUNCTIONS
95 *
96 *----------------------------------------------------------------------------
97 */
98
99/* -----------------------------------------------------------------------------*/
100/**
101 *
102 * This function executes first pass of receiver enable training for all dies
103 *
104 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
105 *
106 * @return TRUE - No fatal error occurs.
107 * @return FALSE - Fatal error occurs.
108 */
109
110BOOLEAN
111MemTTrainRcvrEnSwPass1 (
112 IN OUT MEM_TECH_BLOCK *TechPtr
113 )
114{
115 return MemTDqsTrainRcvrEnSw (TechPtr, 1);
116}
117
118/*----------------------------------------------------------------------------
119 * LOCAL FUNCTIONS
120 *
121 *----------------------------------------------------------------------------
122 */
123
124/*----------------------------------------------------------------------------
125 * LOCAL FUNCTIONS
126 *
127 *----------------------------------------------------------------------------
128 */
129
130/* -----------------------------------------------------------------------------*/
131/**
132 *
133 * This function executes receiver enable training for a specific die
134 *
135 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
136 * @param[in] Pass - Pass of the receiver training
137 *
138 * @return TRUE - No fatal error occurs.
139 * @return FALSE - Fatal error occurs.
140 */
141BOOLEAN
142STATIC
143MemTDqsTrainRcvrEnSw (
144 IN OUT MEM_TECH_BLOCK *TechPtr,
145 IN UINT8 Pass
146 )
147{
148 _16BYTE_ALIGN UINT8 PatternBuffer[3 * 64];
149 UINT8 TestBuffer[120];
150 UINT8 *PatternBufPtr[4];
151 UINT8 *TempPtr;
152 UINT32 TestAddrRJ16[4];
153 UINT32 TempAddrRJ16;
154 UINT32 RealAddr;
155 UINT16 CurTest[4];
156 UINT8 Dct;
157 UINT8 Receiver;
158 UINT8 i;
159 UINT8 TimesFail;
160 UINT8 TimesRetrain;
161 UINT16 RcvrEnDly;
162 UINT16 MaxRcvrEnDly;
163 UINT16 RcvrEnDlyLimit;
164 UINT16 MaxDelayCha;
165 BOOLEAN IsDualRank;
166 BOOLEAN S0En;
167 BOOLEAN S1En;
168 UINT8 MaxFilterDly;
169
170 MEM_DATA_STRUCT *MemPtr;
171 DIE_STRUCT *MCTPtr;
172 DCT_STRUCT *DCTPtr;
173 MEM_NB_BLOCK *NBPtr;
174
175 NBPtr = TechPtr->NBPtr;
176 MemPtr = NBPtr->MemPtr;
177 MCTPtr = NBPtr->MCTPtr;
178 TechPtr->TrainingType = TRN_RCVR_ENABLE;
179
180
181 TempAddrRJ16 = 0;
182 TempPtr = NULL;
183 MaxDelayCha = 0;
184 MaxFilterDly = TechPtr->MaxFilterDly;
185 RcvrEnDlyLimit = NBPtr->RcvrEnDlyLimit;
186 TimesRetrain = DEFAULT_TRAINING_TIMES;
187 IDS_OPTION_HOOK (IDS_MEM_RETRAIN_TIMES, &TimesRetrain, &MemPtr->StdHeader);
188
189 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart SW RxEn training\n");
190 // Set environment settings before training
191 MemTBeginTraining (TechPtr);
192
193 PatternBufPtr[0] = PatternBufPtr[2] = PatternBuffer;
194 MemUFillTrainPattern (TestPattern0, PatternBufPtr[0], 64);
195 PatternBufPtr[1] = PatternBufPtr[3] = PatternBufPtr[0] + 128;
196 MemUFillTrainPattern (TestPattern1, PatternBufPtr[1], 64);
197
198 // Begin receiver enable training
199 AGESA_TESTPOINT (TpProcMemReceiverEnableTraining, &(MemPtr->StdHeader));
200 MaxRcvrEnDly = 0;
201 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
202 IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
203 NBPtr->SwitchDCT (NBPtr, Dct);
204 DCTPtr = NBPtr->DCTPtr;
205
206 // Set training bit
207 NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 1);
208
209 // Relax Max Latency before training
210 NBPtr->SetMaxLatency (NBPtr, 0xFFFF);
211
212 if (Pass == FIRST_PASS) {
213 TechPtr->InitDQSPos4RcvrEn (TechPtr);
214 }
215
216 // there are four receiver pairs, loosely associated with chipselects.
217 Receiver = DCTPtr->Timings.CsEnabled ? 0 : 8;
218 for (; Receiver < 8; Receiver += 2) {
219 TechPtr->DqsRcvEnSaved = 0;
220 RcvrEnDly = RcvrEnDlyLimit;
221 S0En = NBPtr->GetSysAddr (NBPtr, Receiver, &TestAddrRJ16[0]);
222 S1En = NBPtr->GetSysAddr (NBPtr, Receiver + 1, &TestAddrRJ16[2]);
223 if (S0En) {
224 TestAddrRJ16[1] = TestAddrRJ16[0] + BIGPAGE_X8_RJ16;
225 }
226 if (S1En) {
227 TestAddrRJ16[3] = TestAddrRJ16[2] + BIGPAGE_X8_RJ16;
228 }
229 if (S0En && S1En) {
230 IsDualRank = TRUE;
231 } else {
232 IsDualRank = FALSE;
233 }
234
235 if (S0En || S1En) {
236 IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", Receiver);
237
238 // Write the test patterns
239 AGESA_TESTPOINT (TpProcMemRcvrWritePattern, &(MemPtr->StdHeader));
240 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrite to addresses: ");
241 for (i = (S0En ? 0 : 2); i < (S1En ? 4 : 2); i++) {
242 RealAddr = MemUSetUpperFSbase (TestAddrRJ16[i], MemPtr);
243 MemUWriteCachelines (RealAddr, PatternBufPtr[i], 1);
244 IDS_HDT_CONSOLE (MEM_FLOW, " %04x0000 ", TestAddrRJ16[i]);
245 }
246 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
247
248 // Initialize RcvrEnDly value and other DCT stored values
249 // MCTPtr->DqsRcvEnPass = Pass ? 0xFF : 0;
250
251 // Sweep receiver enable delays
252 AGESA_TESTPOINT (TpProcMemRcvrStartSweep, &(MemPtr->StdHeader));
253 TimesFail = 0;
254 ERROR_HANDLE_RETRAIN_BEGIN (TimesFail, TimesRetrain)
255 {
256 for (RcvrEnDly = 0; RcvrEnDly < RcvrEnDlyLimit; RcvrEnDly++) {
257 AGESA_TESTPOINT (TpProcMemRcvrSetDelay, &(MemPtr->StdHeader));
258 TechPtr->SetRcvrEnDly (TechPtr, Receiver, RcvrEnDly);
259 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tDly %3x", RcvrEnDly);
260
261 // Read and compare the first beat of data
262 for (i = (S0En ? 0 : 2); i < (S1En ? 4 : 2); i++) {
263 AGESA_TESTPOINT (TpProcMemRcvrReadPattern, &(MemPtr->StdHeader));
264 RealAddr = MemUSetUpperFSbase (TestAddrRJ16[i], MemPtr);
265 MemUReadCachelines (TestBuffer, RealAddr, 1);
266 AGESA_TESTPOINT (TpProcMemRcvrTestPattern, &(MemPtr->StdHeader));
267 CurTest[i] = TechPtr->Compare1ClPattern (TechPtr, TestBuffer, PatternBufPtr[i]);
268 // Due to speculative execution during MemUReadCachelines, we must
269 // flush one more cache line than we read.
270 MemUProcIOClFlush (TestAddrRJ16[i], 2, MemPtr);
271 TechPtr->ResetDCTWrPtr (TechPtr, Receiver);
272
273 //
274 // Swap the test pointers such that even and odd steps alternate.
275 //
276 if ((i % 2) == 0) {
277 TempPtr = PatternBufPtr[i];
278 PatternBufPtr[i] = PatternBufPtr[i + 1];
279
280 TempAddrRJ16 = TestAddrRJ16[i];
281 TestAddrRJ16[i] = TestAddrRJ16[i + 1];
282 } else {
283 PatternBufPtr[i] = TempPtr;
284 TestAddrRJ16[i] = TempAddrRJ16;
285 }
286 }
287
288 if (TechPtr->SaveRcvrEnDly (TechPtr, Receiver, RcvrEnDly, S0En ? (CurTest[0] & CurTest[1]) : 0xFFFF, S1En ? (CurTest[2] & CurTest[3]) : 0xFFFF)) {
289 // if all bytelanes pass
290 if (MaxRcvrEnDly < (RcvrEnDly - MaxFilterDly)) {
291 MaxRcvrEnDly = RcvrEnDly - MaxFilterDly;
292 }
293 break;
294 }
295 } // End of delay sweep
296 ERROR_HANDLE_RETRAIN_END ((RcvrEnDly > (RcvrEnDlyLimit - 1)), TimesFail)
297 }
298
299 if (RcvrEnDly == RcvrEnDlyLimit) {
300 // no passing window
301 PutEventLog (AGESA_ERROR, MEM_ERROR_RCVR_EN_NO_PASSING_WINDOW_EQUAL_LIMIT, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
302 SetMemError (AGESA_ERROR, MCTPtr);
303 }
304
305 if (RcvrEnDly > (RcvrEnDlyLimit - 1)) {
306 // passing window too narrow, too far delayed
307 PutEventLog (AGESA_ERROR, MEM_ERROR_RCVR_EN_VALUE_TOO_LARGE_LIMIT_LESS_ONE, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
308 SetMemError (AGESA_ERROR, MCTPtr);
309 DCTPtr->Timings.CsTrainFail |= DCTPtr->Timings.CsPresent & (UINT16) (3 << Receiver);
310 MCTPtr->ChannelTrainFail |= (UINT32)1 << Dct;
311 if (!NBPtr->MemPtr->ErrorHandling (MCTPtr, NBPtr->Dct, DCTPtr->Timings.CsTrainFail, &NBPtr->MemPtr->StdHeader)) {
312 ASSERT (FALSE);
313 return FALSE;
314 }
315 }
316 }
317
318 TechPtr->LoadRcvrEnDly (TechPtr, Receiver); // set final delays
319 } // End while Receiver < 8
320
321 // Clear training bit when done
322 NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 0);
323
324 // Set Max Latency for both channels
325 MaxRcvrEnDly += 0x20; // @attention -
326 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRcvrEnDly: %03x\n", MaxRcvrEnDly);
327 if (MCTPtr->GangedMode) {
328 if (Dct == 0) {
329 MaxDelayCha = MaxRcvrEnDly;
330 } else if (MaxRcvrEnDly > MaxDelayCha) {
331 NBPtr->SwitchDCT (NBPtr, 0);
332 NBPtr->SetMaxLatency (NBPtr, MaxRcvrEnDly);
333 }
334 } else {
335 NBPtr->SetMaxLatency (NBPtr, MaxRcvrEnDly);
336 }
337 TechPtr->ResetDCTWrPtr (TechPtr, 6);
338 }
339
340 // Restore environment settings after training
341 MemTEndTraining (TechPtr);
342 IDS_HDT_CONSOLE (MEM_FLOW, "End SW RxEn training\n\n");
343 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
344}
345