AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / NB / mn.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mn.c
6  *
7  * Common Northbridge functions
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/NB/)
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  *                                MODULES USED
48  *
49  *----------------------------------------------------------------------------
50  */
51
52 #include "AGESA.h"
53 #include "AdvancedApi.h"
54 #include "amdlib.h"
55 #include "Ids.h"
56 #include "mport.h"
57 #include "OptionMemory.h"
58 #include "mm.h"
59 #include "mn.h"
60 #include "mu.h"
61 #include "Filecode.h"
62 CODE_GROUP (G1_PEICC)
63 RDATA_GROUP (G2_PEI)
64
65 #define FILECODE PROC_MEM_NB_MN_FILECODE
66
67
68 /*----------------------------------------------------------------------------
69  *                          DEFINITIONS AND MACROS
70  *
71  *----------------------------------------------------------------------------
72  */
73 /*----------------------------------------------------------------------------
74  *                           TYPEDEFS AND STRUCTURES
75  *
76  *----------------------------------------------------------------------------
77  */
78
79 /*----------------------------------------------------------------------------
80  *                        PROTOTYPES OF LOCAL FUNCTIONS
81  *
82  *----------------------------------------------------------------------------
83  */
84 BOOLEAN
85 STATIC
86 MemNDefaultFamilyHookNb (
87   IN OUT   MEM_NB_BLOCK *NBPtr,
88   IN OUT   VOID *OptParam
89   );
90
91 /*----------------------------------------------------------------------------
92  *                            EXPORTED FUNCTIONS
93  *
94  *----------------------------------------------------------------------------
95  */
96 extern OPTION_MEM_FEATURE_NB* memNTrainFlowControl[];
97
98 extern BUILD_OPT_CFG UserOptions;
99
100 /* -----------------------------------------------------------------------------*/
101 /**
102  *
103  *   This function initializes member functions and variables of NB block.
104  *
105  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
106  *
107  */
108
109 VOID
110 MemNInitNBDataNb (
111   IN OUT   MEM_NB_BLOCK *NBPtr
112   )
113 {
114   INT32 i;
115   UINT8 *BytePtr;
116
117   NBPtr->DctCachePtr = NBPtr->DctCache;
118   NBPtr->PsPtr = NBPtr->PSBlock;
119
120   BytePtr = (UINT8 *) (NBPtr->DctCache);
121   for (i = 0; i < sizeof (NBPtr->DctCache); i++) {
122     *BytePtr++ = 0;
123   }
124
125   for (i = 0; i < EnumSize; i++) {
126     NBPtr->IsSupported[i] = FALSE;
127   }
128
129   for (i = 0; i < NumberOfHooks; i++) {
130     NBPtr->FamilySpecificHook[i] = MemNDefaultFamilyHookNb;
131   }
132
133   for (i = 0; i < NBPtr->DctCount; i++) {
134     NBPtr->PSBlock[i].MemPGetPass1Seeds = (BOOLEAN (*) (MEM_NB_BLOCK *)) memDefTrue;
135   }
136
137   NBPtr->SwitchDCT = MemNSwitchDCTNb;
138   NBPtr->SwitchChannel = MemNSwitchChannelNb;
139   NBPtr->GetBitField = MemNGetBitFieldNb;
140   NBPtr->SetBitField = MemNSetBitFieldNb;
141 }
142
143 /* -----------------------------------------------------------------------------*/
144 /**
145  *
146  *
147  *   Get System address of Chipselect RJ 16 bits (Addr[47:16])
148  *
149  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
150  *     @param[in]       Receiver - Chipselect to be targeted [0-7]
151  *     @param[out]      AddrPtr -  Pointer to System Address [47:16]
152  *
153  *     @return      TRUE  - Address is valid
154  *     @return      FALSE  - Address is not valid
155  */
156
157 BOOLEAN
158 MemNGetMCTSysAddrNb (
159   IN OUT   MEM_NB_BLOCK *NBPtr,
160   IN       UINT8 Receiver,
161      OUT   UINT32 *AddrPtr
162   )
163 {
164   S_UINT64 SMsr;
165   UINT32 CSBase;
166   UINT32 HoleBase;
167   UINT32 DctSelBaseAddr;
168   UINT32 BottomUma;
169   DIE_STRUCT *MCTPtr;
170   MEM_DATA_STRUCT *MemPtr;
171
172   MCTPtr = NBPtr->MCTPtr;
173   MemPtr = NBPtr->MemPtr;
174
175   ASSERT (Receiver < 8);
176
177   CSBase = MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + Receiver);
178   if (CSBase & 1) {
179     ASSERT ((CSBase & 0xE0) == 0);   // Should not enable CS interleaving before DQS training.
180
181     // Scale base address from [39:8] to [47:16]
182     CSBase >>= 8;
183
184     HoleBase = MCTPtr->NodeHoleBase ? MCTPtr->NodeHoleBase : 0x7FFFFFFF;
185
186     if ((MemNGetBitFieldNb (NBPtr, BFDctSelHiRngEn) == 1) && (NBPtr->Dct == MemNGetBitFieldNb (NBPtr, BFDctSelHi))) {
187       DctSelBaseAddr = MemNGetBitFieldNb (NBPtr, BFDctSelBaseAddr) << (27 - 16);
188       if (DctSelBaseAddr > HoleBase) {
189         DctSelBaseAddr -= _4GB_RJ16 - HoleBase;
190       }
191       CSBase += DctSelBaseAddr;
192     } else {
193       CSBase += MCTPtr->NodeSysBase;
194     }
195
196     if (CSBase >= HoleBase) {
197       CSBase += _4GB_RJ16 - HoleBase;
198     }
199
200     CSBase += (UINT32)1 << (21 - 16);  // Add 2MB offset to avoid compat area.
201     if ((CSBase >= (MCT_TRNG_KEEPOUT_START >> 8)) && (CSBase <= (MCT_TRNG_KEEPOUT_END >> 8))) {
202       CSBase += (((MCT_TRNG_KEEPOUT_END >> 8) - CSBase) + 0x0F) & 0xFFFFFFF0;
203     }
204
205     if (MCTPtr->Status[SbHWHole]) {
206       if (MCTPtr->Status[SbSWNodeHole]) {
207         LibAmdMsrRead (TOP_MEM, (UINT64 *)&SMsr, &MemPtr->StdHeader);
208
209         if ((CSBase >= (SMsr.lo >> 16)) && (CSBase < _4GB_RJ16)) {
210           return FALSE;
211         }
212       }
213     }
214
215     BottomUma = NBPtr->RefPtr->Sub4GCacheTop >> 16;
216     if (BottomUma && (CSBase >= BottomUma) && (CSBase < _4GB_RJ16)) {
217       return FALSE;
218     }
219     *AddrPtr = CSBase;
220     return TRUE;
221   }
222   return FALSE;
223 }
224
225 /* -----------------------------------------------------------------------------*/
226 /**
227  *
228  *   This function determines if a Rank is enabled.
229  *
230  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
231  *     @param[in]    Receiver - Receiver to check
232  *     @return - FALSE
233  *
234  */
235
236 BOOLEAN
237 MemNRankEnabledNb (
238   IN OUT   MEM_NB_BLOCK *NBPtr,
239   IN       UINT8 Receiver
240   )
241 {
242   UINT32 CSBase;
243   CSBase = MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + Receiver);
244   if (CSBase & 1) {
245     return  TRUE;
246   } else {
247     return  FALSE;
248   }
249 }
250
251 /* -----------------------------------------------------------------------------*/
252 /**
253  *
254  *
255  *     This function sets the EccSymbolSize bit depending upon configurations
256  *     and system override.
257  *
258  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
259  *
260  */
261
262 VOID
263 MemNSetEccSymbolSizeNb (
264   IN OUT   MEM_NB_BLOCK *NBPtr
265   )
266 {
267   UINT16 X4DimmsOnly;
268   BOOLEAN Size;
269   DIE_STRUCT *MCTPtr;
270   DCT_STRUCT *DCTPtr;
271
272   ASSERT (NBPtr != NULL);
273
274   MCTPtr = NBPtr->MCTPtr;
275   DCTPtr = NBPtr->DCTPtr;
276
277   // Determine if this node has only x4 DRAM parts
278   X4DimmsOnly = (UINT16) ((!(DCTPtr->Timings.Dimmx8Present | DCTPtr->Timings.Dimmx16Present)) && DCTPtr->Timings.Dimmx4Present);
279   //
280   // Check if EccSymbolSize BKDG value is overridden
281   //
282   if (UserOptions.CfgEccSymbolSize != ECCSYMBOLSIZE_USE_BKDG) {
283     Size = (UserOptions.CfgEccSymbolSize == ECCSYMBOLSIZE_FORCE_X4) ? FALSE : TRUE;
284   } else {
285     if (X4DimmsOnly && MCTPtr->GangedMode) {
286       Size = FALSE;
287     } else {
288       Size = TRUE;
289     }
290   }
291   IDS_OPTION_HOOK (IDS_ECCSYMBOLSIZE, &Size, &(NBPtr->MemPtr->StdHeader));
292   MemNSetBitFieldNb (NBPtr, BFEccSymbolSize, (UINT32) Size);
293 }
294
295 /* -----------------------------------------------------------------------------*/
296 /**
297  *
298  *      This function sets the training control flow
299  *      The DDR3 mode bit must be set prior to calling this function
300  *
301  *      @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
302  */
303 BOOLEAN
304 MemNTrainingFlowNb (
305   IN OUT   MEM_NB_BLOCK *NBPtr
306   )
307 {
308   if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode)!= 0) {
309     memNTrainFlowControl[DDR3_TRAIN_FLOW] (NBPtr);
310   } else {
311     memNTrainFlowControl[DDR2_TRAIN_FLOW] (NBPtr);
312   }
313   return TRUE;
314 }
315
316 /*-----------------------------------------------------------------------------*/
317 /**
318  *
319  *      This function flushes the  training pattern
320  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
321  *     @param[in] Address - System Address [47:16]
322  *     @param[in] ClCount - Number of cache lines
323  *
324  */
325
326 VOID
327 MemNFlushPatternNb (
328   IN OUT   MEM_NB_BLOCK *NBPtr,
329   IN       UINT32 Address,
330   IN       UINT16 ClCount
331   )
332 {
333   // Due to speculative execution during MemUReadCachelines, we must
334   //  flush one more cache line than we read.
335   MemUProcIOClFlush (Address, ClCount + 1, NBPtr->MemPtr);
336 }
337
338 /* -----------------------------------------------------------------------------*/
339 /**
340  *
341  *     This function compares test pattern with data in buffer and
342  *     return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
343  *
344  *     @param[in,out]   *NBPtr    - Pointer to the MEM_NB_BLOCK
345  *     @param[in]       Buffer[]  - Buffer data from DRAM (Measured data from DRAM) to compare
346  *     @param[in]       Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
347  *     @param[in]       ByteCount - Byte count
348  *
349  *     @return  PASS - Bitmap of results of comparison
350  */
351
352 UINT16
353 MemNCompareTestPatternNb (
354   IN OUT   MEM_NB_BLOCK *NBPtr,
355   IN       UINT8 Buffer[],
356   IN       UINT8 Pattern[],
357   IN       UINT16 ByteCount
358   )
359 {
360   UINT16 i;
361   UINT16 Pass;
362   UINT8 ColumnCount;
363   UINT8 FailingBitMask[8];
364
365   ASSERT ((ByteCount == 18 * 64) || (ByteCount == 9 * 64) || (ByteCount == 64 * 64) || (ByteCount == 32 * 64) || (ByteCount == 3 * 64));
366
367   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
368   Pass = 0xFFFF;
369   //
370   // Clear Failing Bit Mask
371   //
372   for (i = 0; i < sizeof (FailingBitMask); i++) {
373     FailingBitMask[i] = 0;
374   }
375
376   if (NBPtr->Ganged && (NBPtr->Dct != 0)) {
377     i = 8;   // DCT 1 in ganged mode
378   } else {
379     i = 0;
380   }
381
382   for (; i < ByteCount; i++) {
383     if (Buffer[i] != Pattern[i]) {
384       // if bytelane n fails
385       Pass &= ~((UINT16)1 << (i % 8));    // clear bit n
386       FailingBitMask[i % NBPtr->TechPtr->MaxByteLanes ()] |= (Buffer[i] ^ Pattern[i]);
387     }
388
389     if (NBPtr->Ganged && ((i & 7) == 7)) {
390       i += 8;     // if ganged, skip over other Channel's Data
391     }
392   }
393   //
394   // Accumulate Failing bit data
395   //
396   for (i = 0; i < sizeof (FailingBitMask); i++) {
397     NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel) + i] &=
398       FailingBitMask[i];
399   }
400
401   return Pass;
402 }
403
404 /*-----------------------------------------------------------------------------
405  *
406  *
407  *     This function compares test pattern with data in buffer and
408  *     return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
409  *
410  *     @param[in,out]  *NBPtr     - Pointer to the MEM_NB_BLOCK
411  *     @param[in]       Buffer[]  - Buffer data from DRAM (Measured data from DRAM) to compare
412  *     @param[in]       Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
413  *     @param[in]       ByteCount - Byte count
414  *
415  *     @retval  PASS - Bitmap of results of comparison
416  * ----------------------------------------------------------------------------
417  */
418 UINT16
419 MemNInsDlyCompareTestPatternNb (
420   IN       MEM_NB_BLOCK *NBPtr,
421   IN       UINT8 Buffer[],
422   IN       UINT8 Pattern[],
423   IN       UINT16 ByteCount
424   )
425 {
426   UINT16 i;
427   UINT16 Pass;
428   UINT16 BeatOffset;
429   UINT16 BeatCnt;
430   UINT8 ColumnCount;
431   UINT8 FailingBitMask[8];
432
433   ASSERT ((ByteCount == 18 * 64) || (ByteCount == 9 * 64) || (ByteCount == 64 * 64) || (ByteCount == 32 * 64) || (ByteCount == 3 * 64));
434
435   ColumnCount = NBPtr->ChannelPtr->ColumnCount;
436   Pass = 0xFFFF;
437   //
438   // Clear Failing Bit Mask
439   //
440   for (i = 0; i < sizeof (FailingBitMask); i++) {
441     FailingBitMask[i] = 0;
442   }
443
444   if (NBPtr->Ganged && (NBPtr->Dct != 0)) {
445     i = 8;   // DCT 1 in ganged mode
446   } else {
447     i = 0;
448   }
449
450   if (NBPtr->Ganged) {
451     BeatOffset = 16;
452   } else {
453     BeatOffset = 8;
454   }
455
456   BeatCnt = 0;
457   for (; i < ByteCount; i++) {
458
459     if (Buffer[i] != Pattern[i + BeatOffset]) {
460       // if bytelane n fails
461       Pass &= ~((UINT16)1 << (i % 8));    // clear bit n
462       FailingBitMask[i % NBPtr->TechPtr->MaxByteLanes ()] |= (Buffer[i] ^ Pattern[i + BeatOffset]);
463     }
464
465     if ((i & 7) == 7) {
466       if (NBPtr->Ganged) {
467         i += 8;     // if ganged, skip over other Channel's Data
468       }
469       BeatCnt++;
470     }
471
472     if ((BeatCnt & 3) == 3) {
473       // Skip last data beat of a 4-beat burst.
474       BeatCnt++;
475       i = i + BeatOffset;
476     }
477   }
478   //
479   // Accumulate Failing bit data
480   //
481   for (i = 0; i < sizeof (FailingBitMask); i++) {
482     NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel) + i] &=
483       FailingBitMask[i];
484   }
485
486   return Pass;
487 }
488
489 /* -----------------------------------------------------------------------------*/
490 /**
491  *
492  *      This function sets the training control flow for UNB
493  *      The DDR3 mode bit must be set prior to calling this function
494  *
495  *      @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
496  */
497 BOOLEAN
498 MemNTrainingFlowUnb (
499   IN OUT   MEM_NB_BLOCK *NBPtr
500   )
501 {
502   memNTrainFlowControl[DDR3_TRAIN_FLOW] (NBPtr);
503   return TRUE;
504 }
505 /*----------------------------------------------------------------------------
506  *                              LOCAL FUNCTIONS
507  *
508  *----------------------------------------------------------------------------
509  */
510
511 /*-----------------------------------------------------------------------------
512  *
513  *
514  *     This function is an empty function used to intialize FamilySpecificHook array
515  *
516  *     @param[in,out]  *NBPtr     - Pointer to the MEM_NB_BLOCK
517  *     @param[in,out]  OptParam   - Optional parameter
518  *
519  *     @return  TRUE - always
520  * ----------------------------------------------------------------------------
521  */
522 BOOLEAN
523 STATIC
524 MemNDefaultFamilyHookNb (
525   IN OUT   MEM_NB_BLOCK *NBPtr,
526   IN OUT   VOID *OptParam
527   )
528 {
529   return TRUE;
530 }