7 * Phy assisted DQS receiver enable training
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Proc/Recovery/Mem)
12 * @e \$Revision: 50454 $ @e \$Date: 2011-04-10 21:20:37 -0600 (Sun, 10 Apr 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 "OptionMemory.h"
63 #include "PlatformMemoryConfiguration.h"
68 #define FILECODE PROC_RECOVERY_MEM_TECH_MRTTHRC_FILECODE
69 /*----------------------------------------------------------------------------
70 * DEFINITIONS AND MACROS
72 *----------------------------------------------------------------------------
74 #define MAX_BYTELANES 8 /* Max Bytelanes per channel */
76 /*----------------------------------------------------------------------------
77 * TYPEDEFS AND STRUCTURES
79 *----------------------------------------------------------------------------
82 /*----------------------------------------------------------------------------
83 * PROTOTYPES OF LOCAL FUNCTIONS
85 *----------------------------------------------------------------------------
90 MemRecTPrepareRcvrEnDlySeed (
91 IN OUT MEM_TECH_BLOCK *TechPtr,
97 MemRecTProgramRcvrEnDly (
98 IN OUT MEM_TECH_BLOCK *TechPtr,
102 /*----------------------------------------------------------------------------
105 *----------------------------------------------------------------------------
108 /* -----------------------------------------------------------------------------*/
111 * This function executes Phy assisted receiver enable training for current node.
113 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
115 * @pre Auto refresh and ZQCL must be disabled
119 MemRecTTrainRcvrEnHw (
120 IN OUT MEM_TECH_BLOCK *TechPtr
123 UINT8 TempBuffer[64];
130 NBPtr = TechPtr->NBPtr;
132 AGESA_TESTPOINT (TpProcMemReceiverEnableTraining , &(NBPtr->MemPtr->StdHeader));
133 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart HW RxEn training\n");
135 // Set environment settings before training
136 MemRecTBeginTraining (TechPtr);
138 ChipSel = NBPtr->DimmToBeUsed << 1;
141 IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", TechPtr->NBPtr->Dct);
142 IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", ChipSel);
143 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tTestAddr %x\n", TestAddr);
144 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t Byte: 00 01 02 03 04 05 06 07 ECC\n");
146 // 1.Prepare the DIMMs for training
147 NBPtr->SetBitField (NBPtr, BFTrDimmSel, ChipSel >> 1);
149 // 2.Prepare the phy for DQS receiver enable training.
150 MemRecTPrepareRcvrEnDlySeed (TechPtr, ChipSel);
152 // 3.BIOS initiates the phy assisted receiver enable training
153 NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 1);
155 // 4.BIOS begins sending out of back-to-back reads to create
156 // a continuous stream of DQS edges on the DDR interface.
157 for (Count = 0; Count < 3; Count++) {
158 NBPtr->ReadPattern (NBPtr, TempBuffer, TestAddr, 64);
161 // 6.Wait 200 MEMCLKs.
162 MemRecUWait10ns (200, NBPtr->MemPtr);
164 // 7.Program [DqsRcvTrEn]=0 to stop the DQS receive enable training.
165 NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 0);
167 // 8.Get the gross and fine delay values.
168 // 9.Calculate the corresponding final delay values
169 MaxRcvrDly = MemRecTProgramRcvrEnDly (TechPtr, ChipSel);
171 // Set Max Latency for both channels
172 NBPtr->SetMaxLatency (NBPtr, MaxRcvrDly);
174 // Restore environment settings after training
175 MemRecTEndTraining (TechPtr);
176 IDS_HDT_CONSOLE (MEM_FLOW, "End HW RxEn training\n\n");
180 /* -----------------------------------------------------------------------------*/
183 * This function calculates RcvEn seed value for each rank
185 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
186 * @param[in] ChipSel - rank to be trained
191 MemRecTPrepareRcvrEnDlySeed (
192 IN OUT MEM_TECH_BLOCK *TechPtr,
197 CH_DEF_STRUCT *ChannelPtr;
202 UINT16 DiffSeedGrossSeedPreGross;
210 NBPtr = TechPtr->NBPtr;
211 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
213 // Get platform override seed
214 PlatEstSeed = (UINT16 *) MemRecFindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, NBPtr->MCTPtr->SocketId, ChannelPtr->ChannelID, ChipSel >> 1);
216 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
217 // For Pass1, BIOS starts with the delay value obtained from the first pass of write
218 // levelization training that was done in DDR3 Training and add a delay value of 3Bh.
220 NBPtr->FamilySpecificHook[OverrideRcvEnSeed] (NBPtr, &PlatEst);
221 PlatEst = ((PlatEstSeed != NULL) ? PlatEstSeed[ByteLane] : PlatEst);
222 SeedTotal = ChannelPtr->WrDqsDlys[((ChipSel >> 1) * MAX_BYTELANES) + ByteLane] + PlatEst;
223 SeedValue[ByteLane] = PlatEst;
224 SeedTtl[ByteLane] = SeedTotal;
225 // SeedGross = SeedTotal DIV 32.
226 SeedGross = SeedTotal >> 5;
227 // SeedFine = SeedTotal MOD 32.
228 SeedFine = SeedTotal & 0x1F;
230 // Next, determine the gross component of SeedTotal. SeedGrossPass1=SeedTotal DIV 32.
231 // Then, determine the fine delay component of SeedTotal. SeedFinePass1=SeedTotal MOD 32.
232 // Use SeedGrossPass1 to determine SeedPreGrossPass1:
234 if ((SeedGross & 0x1) != 0) {
235 //if SeedGross is odd
238 //if SeedGross is even
242 // (SeedGross - SeedPreGross)
243 DiffSeedGrossSeedPreGross = SeedGross - SeedPreGross;
245 ChannelPtr->RcvEnDlys[(ChipSel * MAX_BYTELANES) + ByteLane] = DiffSeedGrossSeedPreGross << 5;
247 //BIOS programs registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52) with SeedPreGrossPass1
248 //and SeedFinePass1 from the preceding steps.
249 NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
250 SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
252 // 202688: Program seed value to RcvEnDly also.
253 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
255 IDS_HDT_CONSOLE_DEBUG_CODE (
256 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
257 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
258 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedValue[ByteLane]);
260 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
262 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedTotal: ");
263 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
264 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
266 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
267 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
268 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
270 IDS_HDT_CONSOLE (MEM_FLOW, "\n");
274 /* -----------------------------------------------------------------------------*/
277 * This function calculates final RcvrEnDly for each rank
279 * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
280 * @param[in] ChipSel - Rank to be trained
282 * @return MaxDly - The largest delay value
287 MemRecTProgramRcvrEnDly (
288 IN OUT MEM_TECH_BLOCK *TechPtr,
293 CH_DEF_STRUCT *ChannelPtr;
294 UINT16 DiffSeedGrossSeedPreGross;
298 UINT16 RankRcvEnDly[8];
299 NBPtr = TechPtr->NBPtr;
300 ChannelPtr = TechPtr->NBPtr->ChannelPtr;
301 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t PRE: ");
303 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
304 DiffSeedGrossSeedPreGross = (ChannelPtr->RcvEnDlys[(ChipSel * MAX_BYTELANES) + ByteLane]) & 0x1E0;
305 RcvEnDly = (UINT8) NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane));
306 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RcvEnDly);
308 RcvEnDly = RcvEnDly + DiffSeedGrossSeedPreGross;
310 // Add 1 UI to get to the midpoint of preamble
312 RankRcvEnDly[ByteLane] = RcvEnDly;
314 if (RcvEnDly > MaxDly) {
318 NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), RcvEnDly);
320 IDS_HDT_CONSOLE_DEBUG_CODE (
321 IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t RxEn: ");
322 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
323 IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RankRcvEnDly[ByteLane]);
325 IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");