7 * Northbridge DR DCT supporting functions
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/NB/DR)
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 * ***************************************************************************
48 *----------------------------------------------------------------------------
51 *----------------------------------------------------------------------------
59 #include "cpuFamRegisters.h"
65 #include "OptionMemory.h" // need def for MEM_FEAT_BLOCK_NB
68 #include "OptionMemory.h"
73 #define FILECODE PROC_MEM_NB_DR_MNDCTDR_FILECODE
74 /*----------------------------------------------------------------------------
75 * DEFINITIONS AND MACROS
77 *----------------------------------------------------------------------------
81 /*----------------------------------------------------------------------------
82 * TYPEDEFS AND STRUCTURES
84 *----------------------------------------------------------------------------
87 /*----------------------------------------------------------------------------
88 * PROTOTYPES OF LOCAL FUNCTIONS
90 *----------------------------------------------------------------------------
95 MemTCtlOnDimmMirrorDr (
96 IN OUT MEM_NB_BLOCK *NBPtr,
99 /*----------------------------------------------------------------------------
102 *----------------------------------------------------------------------------
105 extern BUILD_OPT_CFG UserOptions;
109 /* -----------------------------------------------------------------------------*/
113 * This function programs the memory controller with configuration parameters
116 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
118 * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
119 * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
120 * @return NBPtr->MCTPtr->ErrCode - Contains detailed AGESA_STATUS value
125 IN OUT MEM_NB_BLOCK *NBPtr
130 MEM_PARAMETER_STRUCT *RefPtr;
132 RefPtr = NBPtr->RefPtr;
133 MCTPtr = NBPtr->MCTPtr;
134 DCTPtr = NBPtr->DCTPtr;
135 //======================================================================
136 // Build Dram Control Register Value (F2x78)
137 //======================================================================
140 MemNSetBitFieldNb (NBPtr, BFRdPtrInit, 6);
141 MemNSetBitFieldNb (NBPtr, BFDataTxFifoWrDly, 0);
143 MemNSetBitFieldNb (NBPtr, BFEarlyArbEn, 1);
145 //======================================================================
146 // Build Dram Config Lo Register Value
147 //======================================================================
151 if (MCTPtr->Status[SbParDimms]) {
153 // SbParDimms should be set for all DDR3 RDIMMS or DDR2 that support parity
154 // Cannot turn off ParEn for DDR3
156 //@attention - add debug option for parity control
157 if ((MemNGetBitFieldNb (NBPtr, BFDdr3Mode)!= 0) || (RefPtr->EnableParity)) {
158 MemNSetBitFieldNb (NBPtr, BFParEn, 1);
162 if (MCTPtr->GangedMode) {
163 MemNSetBitFieldNb (NBPtr, BFWidth128, 1);
166 MemNSetBitFieldNb (NBPtr, BFX4Dimm, DCTPtr->Timings.Dimmx4Present & 0xF);
168 if (!MCTPtr->Status[SbRegistered]) {
169 MemNSetBitFieldNb (NBPtr, BFUnBuffDimm, 1);
172 if (MCTPtr->Status[SbEccDimms]) {
173 MemNSetBitFieldNb (NBPtr, BFDimmEccEn, 1);
176 //======================================================================
177 // Build Dram Config Hi Register Value
178 //======================================================================
181 MemNSetBitFieldNb (NBPtr, BFMemClkFreq, MemNGetMemClkFreqIdNb (NBPtr, DCTPtr->Timings.Speed));
183 if (MCTPtr->Status[SbRegistered]) {
184 if (DCTPtr->Timings.Dimmx4Present && DCTPtr->Timings.Dimmx8Present) {
185 MemNSetBitFieldNb (NBPtr, BFRDqsEn, 1);
189 if (RefPtr->EnableBankSwizzle) {
190 MemNSetBitFieldNb (NBPtr, BFBankSwizzleMode, 1);
193 if (DCTPtr->Timings.DimmQrPresent) {
194 if (UserOptions.CfgMemoryQuadrankType == QUADRANK_UNBUFFERED) {
195 MemNSetBitFieldNb (NBPtr, BFFourRankSoDimm, 1);
196 } else if (UserOptions.CfgMemoryQuadrankType == QUADRANK_REGISTERED) {
197 MemNSetBitFieldNb (NBPtr, BFFourRankRDimm, 1);
201 MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0xF);
203 MemNSetBitFieldNb (NBPtr, BFDcqArbBypassEn, 1);
205 //======================================================================
206 // Build Dram Config Misc Register Value
207 //======================================================================
209 MemNSetBitFieldNb (NBPtr, BFOdtSwizzle, 1);
210 // For DDR3 Registered Dimms
211 if (MCTPtr->Status[SbRegistered]) {
212 if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode)!= 0) {
213 MemNSetBitFieldNb (NBPtr, BFSubMemclkRegDly, 1);
216 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
218 /*----------------------------------------------------------------------------
221 *----------------------------------------------------------------------------
224 /* -----------------------------------------------------------------------------*/
228 * This is a general purpose function that executes before DRAM init
230 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
235 MemNBeforeDramInitDr (
236 IN OUT MEM_NB_BLOCK *NBPtr
241 /* -----------------------------------------------------------------------------*/
245 * This function sends an MRS command
247 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
253 IN OUT MEM_NB_BLOCK *NBPtr
259 if ((NBPtr->MCTPtr->LogicalCpuid.Revision & AMD_F10_C0) != 0) {
260 if (MemNGetBitFieldNb (NBPtr, BFEnDramInit) == 0) {
261 // For C0, if EnDramInit bit is cleared, ODM needs to be cleared before sending MRS
262 MemTCtlOnDimmMirrorDr (NBPtr, FALSE);
267 MemNSwapBitsNb (NBPtr);
269 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d MR%d %04x\n",
270 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) >> 20) & 0xF,
271 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) >> 16) & 0xF,
272 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) & 0xFFFF));
274 // 1.Set SendMrsCmd=1
275 MemNSetBitFieldNb (NBPtr, BFSendMrsCmd, 1);
277 // 2.Wait for SendMrsCmd=0
278 MemNPollBitFieldNb (NBPtr, BFSendMrsCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
281 // Restore ODM if necessary
282 MemTCtlOnDimmMirrorDr (NBPtr, TRUE);
287 /* -----------------------------------------------------------------------------*/
291 * Workaround for erratum 322 and 263
293 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
297 MemNBeforePlatformSpecDr (
298 IN OUT MEM_NB_BLOCK *NBPtr
302 if ((NBPtr->DCTPtr->Timings.Speed == DDR533_FREQUENCY) || (NBPtr->DCTPtr->Timings.Speed == DDR667_FREQUENCY)) {
303 MemNSetBitFieldNb (NBPtr, BFErr263, 0x0800);
305 MemNSetBitFieldNb (NBPtr, BFErr263, 0);
309 // 1.Write 00000000h to F2x[1,0]9C_xD08E000
310 MemNSetBitFieldNb (NBPtr, BFErr322I, 0);
311 // 2.If DRAM Configuration Register[MemClkFreq] (F2x[1,0]94[2:0]) is
312 // greater than or equal to 011b (DDR-800 and higher),
313 // then write 00000080h to F2x[1,0]9C_xD02E001,
314 // else write 00000090h to F2x[1,0]9C_xD02E001.
315 MemNSetBitFieldNb (NBPtr, BFErr322II, (NBPtr->DCTPtr->Timings.Speed >= DDR800_FREQUENCY) ? 0x80 : 0x90);
318 /* -----------------------------------------------------------------------------*/
321 * This function disables/enables F2x[1, 0][5C:40][OnDimmMirror]
323 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
324 * @param[in] SetFlag - Enable or disable flag - TRUE - Enable, FALSE - DISABLE
330 MemTCtlOnDimmMirrorDr (
331 IN OUT MEM_NB_BLOCK *NBPtr,
336 UINT32 CSBaseAddrReg;
338 for (Chipsel = 0; Chipsel < MAX_CS_PER_CHANNEL; Chipsel += 2) {
339 CSBaseAddrReg = MemNGetBitFieldNb (NBPtr, BFCSBaseAddr1Reg + Chipsel);
340 if ((CSBaseAddrReg & 1) == 1) {
341 if (SetFlag && ((NBPtr->DCTPtr->Timings.DimmMirrorPresent & ((UINT8) 1 << (Chipsel >> 1))) != 0)) {
342 CSBaseAddrReg |= ((UINT32) 1 << BFOnDimmMirror);
344 CSBaseAddrReg &= ~((UINT32) 1 << BFOnDimmMirror);
346 MemNSetBitFieldNb (NBPtr, BFCSBaseAddr1Reg + Chipsel, CSBaseAddrReg);
351 /* -----------------------------------------------------------------------------*/
355 * This function adjusts Avg PRE value of Phy fence training according to specific CPU family.
357 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
358 * @param[in,out] *Value16 - Pointer to the value that we want to adjust
364 IN OUT MEM_NB_BLOCK *NBPtr,
365 IN OUT INT16 *Value16
368 if ((NBPtr->MCTPtr->LogicalCpuid.Revision & AMD_F10_C0) != 0) {
369 *Value16 += 5; //for RB C0, the Avg PRE value is subtracted by 3 only.
373 /* -----------------------------------------------------------------------------*/
377 * This function uses calculated values from DCT.Timings structure to
378 * program its RB registers.
381 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
386 MemNProgramCycTimingsDr (
387 IN OUT MEM_NB_BLOCK *NBPtr
390 CTENTRY DDR3TmgAdjTab[] = {
391 // BitField, Min, Max, Bias, Ratio_x2
392 {BFTcl, 4, 12, 4, 2},
393 {BFTrcd, 5, 12, 5, 2},
394 {BFTrp, 5, 12, 5, 2},
395 {BFTrtp, 4, 7, 4, 2},
396 {BFTras, 15, 30, 15, 2},
397 {BFTrc, 11, 42, 11, 2},
398 {BFTwrDDR3, 5, 12, 4, 2},
399 {BFTrrd, 4, 7, 4, 2},
400 {BFTwtr, 4, 7, 4, 2},
401 {BFFourActWindow, 16, 32, 14, 1}
404 CTENTRY DDR2TmgAdjTab[] = {
405 // BitField, Min, Max, Bias, Ratio_x2
407 {BFTrcd, 3, 6, 3, 2},
409 {BFTrtp, 2, 3, 2, 4},
410 {BFTras, 5, 18, 3, 2},
411 {BFTrc, 11, 26, 11, 2},
413 {BFTrrd, 2, 5, 2, 2},
414 {BFTwtr, 5, 8, 4, 2},
415 {BFFourActWindow, 8, 20, 7, 2}
425 BIT_FIELD_NAME BitField;
427 DCTPtr = NBPtr->DCTPtr;
429 //======================================================================
430 // Program DRAM Timing values
431 //======================================================================
433 if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode) == 1) {
434 TmgAdjTab = DDR3TmgAdjTab;
435 } else if (DCTPtr->Timings.Speed == DDR1066_FREQUENCY) {
436 // DDR2-1066 uses DDR3 table but differs in tCL
437 TmgAdjTab = DDR3TmgAdjTab;
438 TmgAdjTab[0].Min = 3;
439 TmgAdjTab[0].Max = 7;
440 TmgAdjTab[0].Bias = 1;
442 TmgAdjTab = DDR2TmgAdjTab;
445 MiniMaxTmg = &DCTPtr->Timings.CasL;
446 for (j = 0; j < GET_SIZE_OF (TmgAdjTab); j++) {
447 BitField = TmgAdjTab[j].BitField;
449 if (MiniMaxTmg[j] < TmgAdjTab[j].Min) {
450 MiniMaxTmg[j] = TmgAdjTab[j].Min;
451 } else if (MiniMaxTmg[j] > TmgAdjTab[j].Max) {
452 MiniMaxTmg[j] = TmgAdjTab[j].Max;
455 Value8 = (UINT8) MiniMaxTmg[j];
457 if (BitField == BFTwrDDR3) {
458 Value8 = (Value8 == 10) ? 9 : (Value8 == 12) ? 10 : Value8;
459 } else if (BitField == BFTrtp) {
460 Value8 = (DCTPtr->Timings.Speed <= DDR1066_FREQUENCY) ? 4 : (DCTPtr->Timings.Speed == DDR1333_FREQUENCY) ? 5 : 6;
463 Value8 = Value8 - TmgAdjTab[j].Bias;
464 Value8 = (Value8 * TmgAdjTab[j].Ratio_x2) >> 1;
466 MemNSetBitFieldNb (NBPtr, BitField, Value8);
469 MiniMaxTrfc = &DCTPtr->Timings.Trfc0;
470 for (j = 0; j < 4; j++) {
471 MemNSetBitFieldNb (NBPtr, BFTrfc0 + j, MiniMaxTrfc[j]);
474 MemNSetBitFieldNb (NBPtr, BFTref, 2); // 7.8 us
476 if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode) == 1) {
477 //======================================================================
478 // DDR3 additional settings
479 //======================================================================
481 MemNSetBitFieldNb (NBPtr, BFTcwl, ((DCTPtr->Timings.Speed >= DDR800_FREQUENCY) ?
482 (NBPtr->GetMemClkFreqId (NBPtr, DCTPtr->Timings.Speed) - 3) : 0));
484 MemNSetBitFieldNb (NBPtr, BFNonSPD, 0x28FF);
486 MemNSetBitFieldNb (NBPtr, BFNonSPDHi, 0x2A);
488 // DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
489 MemNSetBitFieldNb (NBPtr, BFDrvImpCtrl, 1);
491 // burst length control
492 if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
493 MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 2);
496 // ASR=1, auto self refresh; SRT=0
497 MemNSetBitFieldNb (NBPtr, BFASR, 1);
499 //======================================================================
500 // DDR2 additional settings
501 //======================================================================
503 MemNSetBitFieldNb (NBPtr, BFNonSPD, 0xFF77);
505 BurstMode = UserOptions.CfgUseBurstMode;
506 IDS_OPTION_HOOK (IDS_BURST_LENGTH32, &BurstMode, &(NBPtr->MemPtr->StdHeader));
508 if (!NBPtr->MCTPtr->GangedMode) {
509 NBPtr->SetBitField (NBPtr, BFBurstLength32, 1);