blob: 2640689ca701cffbfe78210d281729bcba0fe350 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mtthrc.c
6 *
7 * Phy assisted 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: 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
55
56#include "AGESA.h"
57#include "amdlib.h"
58#include "Ids.h"
59#include "mm.h"
60#include "mn.h"
61#include "mu.h"
62#include "mt.h"
63#include "Filecode.h"
64CODE_GROUP (G1_PEICC)
65RDATA_GROUP (G1_PEICC)
66
67#define FILECODE PROC_MEM_TECH_MTTHRC_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
86VOID
87STATIC
88MemTProgramRcvrEnDly (
89 IN OUT MEM_TECH_BLOCK *TechPtr,
90 IN UINT8 ChipSel,
91 IN UINT8 Pass
92 );
93
94BOOLEAN
95STATIC
96MemTDqsTrainRcvrEnHw (
97 IN OUT MEM_TECH_BLOCK *TechPtr,
98 IN UINT8 Pass
99 );
100
101/*----------------------------------------------------------------------------
102 * EXPORTED FUNCTIONS
103 *
104 *----------------------------------------------------------------------------
105 */
106extern UINT16 T1minToFreq[];
107
108/* -----------------------------------------------------------------------------*/
109/**
110 *
111 * This function executes first pass of Phy assisted receiver enable training
112 * for current node at DDR800 and below.
113 *
114 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
115 *
116 * @pre Auto refresh and ZQCL must be disabled
117 *
118 * @return TRUE - No fatal error occurs.
119 * @return FALSE - Fatal error occurs.
120 */
121BOOLEAN
122MemTDqsTrainRcvrEnHwPass1 (
123 IN OUT MEM_TECH_BLOCK *TechPtr
124 )
125{
126 return MemTDqsTrainRcvrEnHw (TechPtr, 1);
127}
128
129/* -----------------------------------------------------------------------------*/
130/**
131 *
132 * This function executes second pass of Phy assisted receiver enable training
133 * for current node at DDR1066 and above.
134 *
135 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
136 *
137 * @pre Auto refresh and ZQCL must be disabled
138 *
139 * @return TRUE - No fatal error occurs.
140 * @return FALSE - Fatal error occurs.
141 */
142BOOLEAN
143MemTDqsTrainRcvrEnHwPass2 (
144 IN OUT MEM_TECH_BLOCK *TechPtr
145 )
146{
147 // If current speed is higher than start-up speed, do second pass of WL
148 if (TechPtr->NBPtr->DCTPtr->Timings.Speed > TechPtr->NBPtr->StartupSpeed) {
149 return MemTDqsTrainRcvrEnHw (TechPtr, 2);
150 }
151 return TRUE;
152}
153
154/*----------------------------------------------------------------------------
155 * LOCAL FUNCTIONS
156 *
157 *----------------------------------------------------------------------------
158 */
159
160/* -----------------------------------------------------------------------------*/
161/**
162 *
163 * This function executes Phy assisted receiver enable training for current node.
164 *
165 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
166 * @param[in] Pass - Pass of the receiver training
167 *
168 * @pre Auto refresh and ZQCL must be disabled
169 *
170 */
171BOOLEAN
172STATIC
173MemTDqsTrainRcvrEnHw (
174 IN OUT MEM_TECH_BLOCK *TechPtr,
175 IN UINT8 Pass
176 )
177{
178 MEM_NB_BLOCK *NBPtr;
179 UINT32 TestAddrRJ16;
180 UINT8 Dct;
181 UINT8 ChipSel;
182 NBPtr = TechPtr->NBPtr;
183
184 TechPtr->TrainingType = TRN_RCVR_ENABLE;
185
186 AGESA_TESTPOINT (TpProcMemReceiverEnableTraining , &(NBPtr->MemPtr->StdHeader));
187 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart HW RxEn training\n");
188
189 // Set environment settings before training
190 MemTBeginTraining (TechPtr);
191 //
192 // Setup hardware training engine (if applicable)
193 //
194 NBPtr->FamilySpecificHook[SetupHwTrainingEngine] (NBPtr, &TechPtr->TrainingType);
195
196 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
197 IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
198 NBPtr->SwitchDCT (NBPtr, Dct);
199 //training for each rank
200 for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
201 if (NBPtr->GetSysAddr (NBPtr, ChipSel, &TestAddrRJ16)) {
202 if (!(NBPtr->MCTPtr->Status[SbLrdimms]) || ((NBPtr->ChannelPtr->LrDimmPresent & ((UINT8) 1 << (ChipSel >> 1))) != 0)) {
203 // 1.Prepare the DIMMs for training
204 NBPtr->SetBitField (NBPtr, BFTrDimmSel, ChipSel >> 1);
205
206 TechPtr->ChipSel = ChipSel;
207 TechPtr->Pass = Pass;
208 NBPtr->FamilySpecificHook[InitPerNibbleTrn] (NBPtr, NULL);
209 for (TechPtr->TrnNibble = NIBBLE_0; TechPtr->TrnNibble <= (NBPtr->FamilySpecificHook[TrainRxEnPerNibble] (NBPtr, &ChipSel)? NIBBLE_0 : NIBBLE_1); TechPtr->TrnNibble++) {
210 // 2.Prepare the phy for DQS receiver enable training.
211 IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", ChipSel);
212 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tTestAddr %x0000\n", TestAddrRJ16);
213 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t Byte: 00 01 02 03 04 05 06 07 ECC\n");
214 NBPtr->MemNPrepareRcvrEnDlySeed (NBPtr);
215
216 // 3.BIOS initiates the phy assisted receiver enable training
217 NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 1);
218
219 // 4.BIOS begins sending out of back-to-back reads to create
220 // a continuous stream of DQS edges on the DDR interface
221 NBPtr->GenHwRcvEnReads (NBPtr, TestAddrRJ16);
222
223 // 7.Program [DqsRcvTrEn]=0 to stop the DQS receive enable training.
224 NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 0);
225
226 // 8.Get the gross and fine delay values.
227 // 9.Calculate the corresponding final delay values
228 MemTProgramRcvrEnDly (TechPtr, ChipSel, Pass);
229 }
230 }
231 }
232 }
233 }
234 // Restore environment settings after training
235 MemTEndTraining (TechPtr);
236 IDS_HDT_CONSOLE (MEM_FLOW, "End HW RxEn training\n\n");
237
238 return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
239}
240
241/* -----------------------------------------------------------------------------*/
242/**
243 *
244 * This function calculates final RcvrEnDly for each rank
245 *
246 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
247 * @param[in] ChipSel - Rank to be trained
248 * @param[in] Pass - Pass of the receiver training
249 *
250 */
251VOID
252STATIC
253MemTProgramRcvrEnDly (
254 IN OUT MEM_TECH_BLOCK *TechPtr,
255 IN UINT8 ChipSel,
256 IN UINT8 Pass
257 )
258{
259 MEM_NB_BLOCK *NBPtr;
260 CH_DEF_STRUCT *ChannelPtr;
261 UINT8 ByteLane;
262 UINT16 RcvEnDly;
263 UINT16 CsPairRcvEnDly;
264 UINT16 RankRcvEnDly[9];
265 NBPtr = TechPtr->NBPtr;
266 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
267 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t PRE: ");
268 for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8) ; ByteLane++) {
269 RcvEnDly = (UINT8) NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane));
270 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RcvEnDly);
271
272 RcvEnDly = RcvEnDly + TechPtr->DiffSeedGrossSeedPreGross[ByteLane];
273
274 // Add 1 UI to get to the midpoint of preamble
275 RcvEnDly += 0x20;
276 TechPtr->Bytelane = ByteLane;
277 RankRcvEnDly[ByteLane] = RcvEnDly;
278 if (NBPtr->FamilySpecificHook[TrainRxEnAdjustDlyPerNibble] (NBPtr, &RcvEnDly)) {
279 if ((ChipSel & 1) == 1) {
280 // For each rank pair on a dual-rank DIMM, compute the average value of the total delays saved during the
281 // training of each rank and program the result in D18F2x[1,0]9C_x0000_00[24:10][DqsRcvEnGrossDelay,
282 // DqsRcvEnFineDelay].
283 CsPairRcvEnDly = ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane];
284 RcvEnDly = (CsPairRcvEnDly + RcvEnDly + 1) / 2;
285 }
286 }
287 ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane] = RcvEnDly;
288 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), RcvEnDly);
289 }
290
291 IDS_HDT_CONSOLE_DEBUG_CODE (
292 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t RxEn: ");
293 for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
294 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RankRcvEnDly[ByteLane]);
295 }
296 if (NBPtr->FamilySpecificHook[TrainRxEnGetAvgDlyPerNibble] (NBPtr, NULL)) {
297 if ((ChipSel & 1) == 1) {
298 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t Avg: ");
299 for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
300 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", ChannelPtr->RcvEnDlys[(ChipSel >> 1) * TechPtr->DlyTableWidth () + ByteLane]);
301 }
302 }
303 }
304 IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");
305 );
306}