AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / NB / DR / mndctdr.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mndctdr.c
6  *
7  * Northbridge DR DCT supporting functions
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/NB/DR)
12  * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
13  *
14  **/
15 /*****************************************************************************
16 *
17 * Copyright (C) 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.
41 *
42 * ***************************************************************************
43 *
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 "cpuFamRegisters.h"
60 #include "mport.h"
61 #include "mm.h"
62 #include "mn.h"
63 #include "mt.h"
64 #include "mu.h"
65 #include "OptionMemory.h"       // need def for MEM_FEAT_BLOCK_NB
66 #include "mndr.h"
67 #include "merrhdl.h"
68 #include "OptionMemory.h"
69 #include "Filecode.h"
70 CODE_GROUP (G1_PEICC)
71 RDATA_GROUP (G2_PEI)
72
73 #define FILECODE PROC_MEM_NB_DR_MNDCTDR_FILECODE
74 /*----------------------------------------------------------------------------
75  *                          DEFINITIONS AND MACROS
76  *
77  *----------------------------------------------------------------------------
78  */
79 #define UNUSED_CLK 4
80
81 /*----------------------------------------------------------------------------
82  *                           TYPEDEFS AND STRUCTURES
83  *
84  *----------------------------------------------------------------------------
85  */
86
87 /*----------------------------------------------------------------------------
88  *                        PROTOTYPES OF LOCAL FUNCTIONS
89  *
90  *----------------------------------------------------------------------------
91  */
92
93 VOID
94 STATIC
95 MemTCtlOnDimmMirrorDr (
96   IN OUT   MEM_NB_BLOCK *NBPtr,
97   IN       BOOLEAN SetFlag
98   );
99 /*----------------------------------------------------------------------------
100  *                            EXPORTED FUNCTIONS
101  *
102  *----------------------------------------------------------------------------
103  */
104
105 extern BUILD_OPT_CFG UserOptions;
106
107
108
109 /* -----------------------------------------------------------------------------*/
110 /**
111  *
112  *
113  *      This function programs the memory controller with configuration parameters
114  *
115  *
116  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
117  *
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
121  */
122
123 BOOLEAN
124 memNAutoConfigDr (
125   IN OUT   MEM_NB_BLOCK *NBPtr
126   )
127 {
128   DIE_STRUCT *MCTPtr;
129   DCT_STRUCT *DCTPtr;
130   MEM_PARAMETER_STRUCT *RefPtr;
131
132   RefPtr = NBPtr->RefPtr;
133   MCTPtr = NBPtr->MCTPtr;
134   DCTPtr = NBPtr->DCTPtr;
135   //======================================================================
136   // Build Dram Control Register Value (F2x78)
137   //======================================================================
138   //
139
140   MemNSetBitFieldNb (NBPtr, BFRdPtrInit, 6);
141   MemNSetBitFieldNb (NBPtr, BFDataTxFifoWrDly, 0);
142
143   MemNSetBitFieldNb (NBPtr, BFEarlyArbEn, 1);
144
145   //======================================================================
146   // Build Dram Config Lo Register Value
147   //======================================================================
148   //
149
150
151   if (MCTPtr->Status[SbParDimms]) {
152     //
153     // SbParDimms should be set for all DDR3 RDIMMS or DDR2 that support parity
154     // Cannot turn off ParEn for DDR3
155     //
156     //@attention - add debug option for parity control
157     if ((MemNGetBitFieldNb (NBPtr, BFDdr3Mode)!= 0) || (RefPtr->EnableParity)) {
158       MemNSetBitFieldNb (NBPtr, BFParEn, 1);
159     }
160   }
161
162   if (MCTPtr->GangedMode) {
163     MemNSetBitFieldNb (NBPtr, BFWidth128, 1);
164   }
165
166   MemNSetBitFieldNb (NBPtr, BFX4Dimm, DCTPtr->Timings.Dimmx4Present & 0xF);
167
168   if (!MCTPtr->Status[SbRegistered]) {
169     MemNSetBitFieldNb (NBPtr, BFUnBuffDimm, 1);
170   }
171
172   if (MCTPtr->Status[SbEccDimms]) {
173     MemNSetBitFieldNb (NBPtr, BFDimmEccEn, 1);
174   }
175
176   //======================================================================
177   // Build Dram Config Hi Register Value
178   //======================================================================
179   //
180
181   MemNSetBitFieldNb (NBPtr, BFMemClkFreq, MemNGetMemClkFreqIdNb (NBPtr, DCTPtr->Timings.Speed));
182
183   if (MCTPtr->Status[SbRegistered]) {
184     if (DCTPtr->Timings.Dimmx4Present && DCTPtr->Timings.Dimmx8Present) {
185       MemNSetBitFieldNb (NBPtr, BFRDqsEn, 1);
186     }
187   }
188
189   if (RefPtr->EnableBankSwizzle) {
190     MemNSetBitFieldNb (NBPtr, BFBankSwizzleMode, 1);
191   }
192
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);
198     }
199   }
200
201   MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0xF);
202
203   MemNSetBitFieldNb (NBPtr, BFDcqArbBypassEn, 1);
204
205   //======================================================================
206   // Build Dram Config Misc Register Value
207   //======================================================================
208   //
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);
214     }
215   }
216   return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
217 }
218 /*----------------------------------------------------------------------------
219  *                              LOCAL FUNCTIONS
220  *
221  *----------------------------------------------------------------------------
222  */
223
224 /* -----------------------------------------------------------------------------*/
225 /**
226  *
227  *
228  *   This is a general purpose function that executes before DRAM init
229  *
230  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
231  *
232  */
233
234 VOID
235 MemNBeforeDramInitDr (
236   IN OUT   MEM_NB_BLOCK *NBPtr
237   )
238 {
239 }
240
241 /* -----------------------------------------------------------------------------*/
242 /**
243  *
244  *
245  *   This function sends an MRS command
246  *
247  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
248  *
249  */
250
251 VOID
252 MemNSendMrsCmdDr (
253   IN OUT   MEM_NB_BLOCK *NBPtr
254   )
255 {
256   BOOLEAN ClearODM;
257
258   ClearODM = FALSE;
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);
263       ClearODM = TRUE;
264     }
265   }
266
267   MemNSwapBitsNb (NBPtr);
268
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));
273
274   // 1.Set SendMrsCmd=1
275   MemNSetBitFieldNb (NBPtr, BFSendMrsCmd, 1);
276
277   // 2.Wait for SendMrsCmd=0
278   MemNPollBitFieldNb (NBPtr, BFSendMrsCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
279
280   if (ClearODM) {
281     // Restore ODM if necessary
282     MemTCtlOnDimmMirrorDr (NBPtr, TRUE);
283   }
284 }
285
286
287 /* -----------------------------------------------------------------------------*/
288 /**
289  *
290  *
291  *   Workaround for erratum 322 and 263
292  *
293  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
294  *
295  */
296 VOID
297 MemNBeforePlatformSpecDr (
298   IN OUT   MEM_NB_BLOCK *NBPtr
299   )
300 {
301   // Errata 263
302   if ((NBPtr->DCTPtr->Timings.Speed == DDR533_FREQUENCY) || (NBPtr->DCTPtr->Timings.Speed == DDR667_FREQUENCY)) {
303     MemNSetBitFieldNb (NBPtr, BFErr263, 0x0800);
304   } else {
305     MemNSetBitFieldNb (NBPtr, BFErr263, 0);
306   }
307
308   // Errata 322
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);
316 }
317
318 /* -----------------------------------------------------------------------------*/
319 /**
320  *
321  *      This function disables/enables F2x[1, 0][5C:40][OnDimmMirror]
322  *
323  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
324  *     @param[in]   SetFlag   - Enable or disable flag - TRUE - Enable, FALSE - DISABLE
325  *
326  */
327
328 VOID
329 STATIC
330 MemTCtlOnDimmMirrorDr (
331   IN OUT   MEM_NB_BLOCK *NBPtr,
332   IN       BOOLEAN SetFlag
333   )
334 {
335   UINT8 Chipsel;
336   UINT32 CSBaseAddrReg;
337
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);
343       } else {
344         CSBaseAddrReg &= ~((UINT32) 1 << BFOnDimmMirror);
345       }
346       MemNSetBitFieldNb (NBPtr, BFCSBaseAddr1Reg + Chipsel, CSBaseAddrReg);
347     }
348   }
349 }
350
351 /* -----------------------------------------------------------------------------*/
352 /**
353  *
354  *
355  *   This function adjusts Avg PRE value of Phy fence training according to specific CPU family.
356  *
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
359  *
360  */
361
362 VOID
363 MemNPFenceAdjustDr (
364   IN OUT   MEM_NB_BLOCK *NBPtr,
365   IN OUT   INT16 *Value16
366   )
367 {
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.
370   }
371 }
372
373 /* -----------------------------------------------------------------------------*/
374 /**
375  *
376  *
377  *      This function uses calculated values from DCT.Timings structure to
378  *      program its RB registers.
379  *
380  *
381  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
382  *
383  */
384
385 VOID
386 MemNProgramCycTimingsDr (
387   IN OUT   MEM_NB_BLOCK *NBPtr
388   )
389 {
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}
402   };
403
404   CTENTRY DDR2TmgAdjTab[] = {
405     // BitField, Min, Max, Bias, Ratio_x2
406     {BFTcl, 3, 7, 1, 2},
407     {BFTrcd, 3, 6, 3, 2},
408     {BFTrp, 3, 6, 3, 4},
409     {BFTrtp, 2, 3, 2, 4},
410     {BFTras, 5, 18, 3, 2},
411     {BFTrc, 11, 26, 11, 2},
412     {BFTwr, 3, 6, 3, 2},
413     {BFTrrd, 2, 5, 2, 2},
414     {BFTwtr, 5, 8, 4, 2},
415     {BFFourActWindow, 8, 20, 7, 2}
416   };
417
418   CTENTRY *TmgAdjTab;
419   DCT_STRUCT *DCTPtr;
420   UINT8  *MiniMaxTmg;
421   UINT8  *MiniMaxTrfc;
422   UINT8  Value8;
423   UINT8  j;
424   UINT8  BurstMode;
425   BIT_FIELD_NAME BitField;
426
427   DCTPtr = NBPtr->DCTPtr;
428
429   //======================================================================
430   // Program DRAM Timing values
431   //======================================================================
432   //
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;
441   } else {
442     TmgAdjTab = DDR2TmgAdjTab;
443   }
444
445   MiniMaxTmg = &DCTPtr->Timings.CasL;
446   for (j = 0; j < GET_SIZE_OF (TmgAdjTab); j++) {
447     BitField = TmgAdjTab[j].BitField;
448
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;
453     }
454
455     Value8 = (UINT8) MiniMaxTmg[j];
456
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;
461     }
462
463     Value8 = Value8 - TmgAdjTab[j].Bias;
464     Value8 = (Value8 * TmgAdjTab[j].Ratio_x2) >> 1;
465
466     MemNSetBitFieldNb (NBPtr, BitField, Value8);
467   }
468
469   MiniMaxTrfc = &DCTPtr->Timings.Trfc0;
470   for (j = 0; j < 4; j++) {
471     MemNSetBitFieldNb (NBPtr, BFTrfc0 + j, MiniMaxTrfc[j]);
472   }
473
474   MemNSetBitFieldNb (NBPtr, BFTref, 2);      // 7.8 us
475
476   if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode) == 1) {
477     //======================================================================
478     // DDR3 additional settings
479     //======================================================================
480
481     MemNSetBitFieldNb (NBPtr, BFTcwl, ((DCTPtr->Timings.Speed >= DDR800_FREQUENCY) ?
482                                        (NBPtr->GetMemClkFreqId (NBPtr, DCTPtr->Timings.Speed) - 3) : 0));
483
484     MemNSetBitFieldNb (NBPtr, BFNonSPD, 0x28FF);
485
486     MemNSetBitFieldNb (NBPtr, BFNonSPDHi, 0x2A);
487
488     // DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
489     MemNSetBitFieldNb (NBPtr, BFDrvImpCtrl, 1);
490
491     // burst length control
492     if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
493       MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 2);
494     }
495
496     // ASR=1, auto self refresh; SRT=0
497     MemNSetBitFieldNb (NBPtr, BFASR, 1);
498   } else {
499     //======================================================================
500     // DDR2 additional settings
501     //======================================================================
502
503     MemNSetBitFieldNb (NBPtr, BFNonSPD, 0xFF77);
504
505     BurstMode = UserOptions.CfgUseBurstMode;
506     IDS_OPTION_HOOK (IDS_BURST_LENGTH32, &BurstMode, &(NBPtr->MemPtr->StdHeader));
507     if (BurstMode) {
508       if (!NBPtr->MCTPtr->GangedMode) {
509         NBPtr->SetBitField (NBPtr, BFBurstLength32, 1);
510       }
511     }
512   }
513 }
514