AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Ps / mp.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mp.c
6  *
7  * Common platform specific configuration.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Ps)
12  * @e \$Revision: 55046 $ @e \$Date: 2011-06-15 23:59:07 -0600 (Wed, 15 Jun 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
53
54 #include "AGESA.h"
55 #include "AdvancedApi.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "cpuFamRegisters.h"
59 #include "cpuRegisters.h"
60 #include "OptionMemory.h"
61 #include "PlatformMemoryConfiguration.h"
62 #include "mu.h"
63 #include "ma.h"
64 #include "mp.h"
65 #include "merrhdl.h"
66 #include "GeneralServices.h"
67 #include "Filecode.h"
68 CODE_GROUP (G2_PEI)
69 RDATA_GROUP (G2_PEI)
70
71 #define FILECODE PROC_MEM_PS_MP_FILECODE
72
73
74 /*----------------------------------------------------------------------------
75  *                          DEFINITIONS AND MACROS
76  *
77  *----------------------------------------------------------------------------
78  */
79 #define PSO_TYPE    0
80 #define PSO_LENGTH  1
81 #define PSO_DATA    2
82
83 /*----------------------------------------------------------------------------
84  *                           TYPEDEFS AND STRUCTURES
85  *
86  *----------------------------------------------------------------------------
87  */
88 /*----------------------------------------------------------------------------
89  *                        PROTOTYPES OF LOCAL FUNCTIONS
90  *
91  *----------------------------------------------------------------------------
92  */
93 BOOLEAN
94 STATIC
95 MemPPSCGen (
96   IN OUT   MEM_NB_BLOCK *NBPtr,
97   IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
98   );
99
100 BOOLEAN
101 STATIC
102 MemPCheckTblDrvOverrideConfig (
103   IN OUT   MEM_NB_BLOCK *NBPtr,
104   IN       UINT8 *Buffer
105   );
106
107 BOOLEAN
108 STATIC
109 MemPCheckTblDrvOverrideConfigSpeedLimit (
110   IN OUT   MEM_NB_BLOCK *NBPtr,
111   IN       UINT8 *Buffer
112   );
113
114 VOID
115 STATIC
116 MemPTblDrvOverrideSpeedLimit (
117   IN OUT   MEM_NB_BLOCK *NBPtr,
118   IN       UINT8 *Buffer
119   );
120
121 UINT8
122 STATIC
123 MemPTblDrvOverrideODT (
124   IN OUT   MEM_NB_BLOCK *NBPtr,
125   IN       UINT8 *Buffer
126   );
127
128 VOID
129 STATIC
130 MemPTblDrvOverrideODTPattern (
131   IN OUT   MEM_NB_BLOCK *NBPtr,
132   IN       UINT8 *Buffer
133   );
134
135 UINT8
136 STATIC
137 MemPTblDrvOverrideRC2IBT (
138   IN OUT   MEM_NB_BLOCK *NBPtr,
139   IN       UINT8 *Buffer,
140   IN       UINT8 NumOfReg
141   );
142
143 BOOLEAN
144 STATIC
145 MemPTblDrvOverrideMR0WR (
146   IN OUT   MEM_NB_BLOCK *NBPtr,
147   IN       UINT8 *Buffer
148   );
149
150 BOOLEAN
151 STATIC
152 MemPTblDrvOverrideMR0CL (
153   IN OUT   MEM_NB_BLOCK *NBPtr,
154   IN       UINT8 *Buffer
155   );
156
157 BOOLEAN
158 STATIC
159 MemPTblDrvOverrideMR10OpSpeed (
160   IN OUT   MEM_NB_BLOCK *NBPtr,
161   IN       UINT8 *Buffer
162   );
163
164 /*----------------------------------------------------------------------------
165  *                            EXPORTED FUNCTIONS
166  *
167  *----------------------------------------------------------------------------
168  */
169 extern MEM_PSC_FLOW_BLOCK* memPlatSpecFlowArray[];
170
171 /* -----------------------------------------------------------------------------*/
172 /**
173  *
174  *    This is the default return function of the Platform Specific block. The function always
175  *    returns   AGESA_UNSUPPORTED
176  *
177  *     @param[in,out]   *MemPtr           Pointer to MEM_DATA_STRUCTURE
178  *     @param[in]       *ChannelPtr       Pointer to CH_DEF_STRUCT
179  *     @param[in]       *PsPtr            Pointer to MEM_PS_BLOCK
180  *
181  *     @return          AGESA_UNSUPPORTED  AGESA status indicating that default is unsupported
182  *
183  */
184
185 AGESA_STATUS
186 MemPConstructPsUDef (
187   IN OUT   MEM_DATA_STRUCT *MemPtr,
188   IN OUT   CH_DEF_STRUCT *ChannelPtr,
189   IN OUT   MEM_PS_BLOCK *PsPtr
190   )
191 {
192   return AGESA_UNSUPPORTED;
193 }
194
195 /* -----------------------------------------------------------------------------*/
196 /**
197  *
198  *    This function will set the DramTerm and DramTermDyn in the structure of a channel.
199  *
200  *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
201  *     @param[in]       ArraySize        Size of the array of DramTerm
202  *     @param[in]       *DramTermPtr     Address the array of DramTerm
203  *
204  *     @return          TRUE - Find DramTerm and DramTermDyn for corresponding platform and dimm population.
205  *     @return          FALSE - Fail to find DramTerm and DramTermDyn for corresponding platform and dimm population.
206  *
207  */
208 BOOLEAN
209 MemPGetDramTerm (
210   IN OUT   MEM_NB_BLOCK *NBPtr,
211   IN       UINT8 ArraySize,
212   IN       CONST DRAM_TERM_ENTRY *DramTermPtr
213   )
214 {
215   UINT8 Dimms;
216   UINT8 QR_Dimms;
217   UINT8 i;
218   Dimms = NBPtr->ChannelPtr->Dimms;
219   QR_Dimms = 0;
220   for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i ++) {
221     if (((NBPtr->ChannelPtr->DimmQrPresent & (UINT16) (1 << i)) != 0) && (i < 2)) {
222       QR_Dimms ++;
223     }
224   }
225
226   for (i = 0; i < ArraySize; i ++) {
227     if ((DramTermPtr[i].Speed & ((UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66))) != 0) {
228       if ((((UINT8) (1 << (Dimms - 1)) & DramTermPtr[i].Dimms) != 0) || (DramTermPtr[i].Dimms == ANY_NUM)) {
229         if (((QR_Dimms == 0) && (DramTermPtr[i].QR_Dimms == NO_DIMM)) ||
230             ((QR_Dimms > 0) && (((UINT8) (1 << (QR_Dimms - 1)) & DramTermPtr[i].QR_Dimms) != 0)) ||
231             (DramTermPtr[i].QR_Dimms == ANY_NUM)) {
232           NBPtr->PsPtr->DramTerm = DramTermPtr[i].DramTerm;
233           NBPtr->PsPtr->QR_DramTerm = DramTermPtr[i].QR_DramTerm;
234           NBPtr->PsPtr->DynamicDramTerm = DramTermPtr[i].DynamicDramTerm;
235           break;
236         }
237       }
238     }
239   }
240   return TRUE;
241 }
242
243 /* -----------------------------------------------------------------------------*/
244 /**
245  *
246  *    This function gets the highest POR supported speed.
247  *
248  *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
249  *     @param[in]       FreqLimitSize    Size of the array of Frequency Limit
250  *     @param[in]       *FreqLimitPtr     Address the array of Frequency Limit
251  *
252  *     @return          UINT8 - frequency limit
253  *
254  */
255 UINT16
256 MemPGetPorFreqLimit (
257   IN OUT   MEM_NB_BLOCK *NBPtr,
258   IN       UINT8 FreqLimitSize,
259   IN       CONST POR_SPEED_LIMIT *FreqLimitPtr
260   )
261 {
262   UINT8 i;
263   UINT8 j;
264   UINT8 DimmTpMatch;
265   UINT16 SpeedLimit;
266   UINT16 DIMMRankType;
267   UINT16 _DIMMRankType;
268
269   SpeedLimit = 0;
270   DIMMRankType = MemAGetPsRankType (NBPtr->ChannelPtr);
271   for (i = 0; i < FreqLimitSize; i++, FreqLimitPtr++) {
272     if (NBPtr->ChannelPtr->Dimms != FreqLimitPtr->Dimms) {
273       continue;
274     }
275     DimmTpMatch = 0;
276     _DIMMRankType = DIMMRankType & FreqLimitPtr->DIMMRankType;
277     for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j ++) {
278       if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
279         DimmTpMatch++;
280       }
281     }
282     if (DimmTpMatch == FreqLimitPtr->Dimms) {
283       if (NBPtr->RefPtr->DDR3Voltage == VOLT1_5) {
284         SpeedLimit = FreqLimitPtr->SpeedLimit_1_5V;
285         break;
286       } else if (NBPtr->RefPtr->DDR3Voltage == VOLT1_25) {
287         SpeedLimit = FreqLimitPtr->SpeedLimit_1_25V;
288         break;
289       } else {
290         SpeedLimit = FreqLimitPtr->SpeedLimit_1_35V;
291         break;
292       }
293     }
294   }
295
296   return SpeedLimit;
297 }
298
299 /* -----------------------------------------------------------------------------*/
300 /**
301  *
302  *    This function is the default function for getting POR speed limit. When a
303  *    package does not need to cap the speed, it should use this function to initialize
304  *    the corresponding function pointer.
305  *
306  *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
307  *
308  */
309 VOID
310 MemPGetPORFreqLimitDef (
311   IN OUT   MEM_NB_BLOCK *NBPtr
312   )
313 {
314 }
315
316 /* -----------------------------------------------------------------------------*/
317 /**
318  *
319  *      This function gets the seed value of WL and HW RxEn pass 1 training.
320  *
321  *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
322  *
323  *     @return          TRUE - Entries are found
324  *     @return          FALSE - Entries are not found
325  *
326  */
327 BOOLEAN
328 MemPGetPSCPass1Seed (
329   IN OUT   MEM_NB_BLOCK *NBPtr
330   )
331 {
332   UINT8 i;
333   UINT8 Dct;
334
335   for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
336     NBPtr->SwitchDCT (NBPtr, Dct);
337     i = 0;
338     while (memPlatSpecFlowArray[i] != NULL) {
339       if (!(memPlatSpecFlowArray[i])->TrainingSeedVal (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
340         return FALSE;
341       }
342       i++;
343     }
344   }
345
346   return TRUE;
347 }
348
349
350 /* -----------------------------------------------------------------------------*/
351 /**
352  *
353  *    This function gets platform specific configuration such as Max Freq., Slow Mode, Dram Term,
354  *    and so on.
355  *
356  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
357  *
358  *     @return          TRUE - Successfully execute platform specific configuration flow.
359  *     @return          FALSE - Fail to execute platform specific configuration flow.
360  *
361  */
362 BOOLEAN
363 MemPPSCFlow (
364   IN OUT   MEM_NB_BLOCK *NBPtr
365   )
366 {
367   UINT8 i;
368   BOOLEAN Result;
369
370   Result = TRUE;
371   i = 0;
372   while (memPlatSpecFlowArray[i] != NULL) {
373     if ((memPlatSpecFlowArray[i])->DramTerm (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
374       if ((memPlatSpecFlowArray[i])->ODTPattern (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
375         if ((memPlatSpecFlowArray[i])->SAO (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
376           if ((memPlatSpecFlowArray[i])->MR0WrCL (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
377             if ((memPlatSpecFlowArray[i])->RC2IBT (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
378               if ((memPlatSpecFlowArray[i])->RC10OpSpeed (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
379                 if ((memPlatSpecFlowArray[i])->LRIBT (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
380                   if ((memPlatSpecFlowArray[i])->LRNPR (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
381                     if ((memPlatSpecFlowArray[i])->LRNLR (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
382                       if (MemPPSCGen (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
383                         break;
384                       }
385                     }
386                   }
387                 }
388               }
389             }
390           }
391         }
392       }
393     }
394     i++;
395   }
396
397   IDS_SKIP_HOOK (IDS_ENFORCE_PLAT_TABLES, NBPtr, &(NBPtr->MemPtr->StdHeader)) {
398     if (memPlatSpecFlowArray[i] == NULL) {
399       Result = FALSE;
400     }
401   }
402   return Result;
403 }
404
405 /* -----------------------------------------------------------------------------*/
406 /**
407  *
408  *     This function constructs the rank type map of Dimm0, Dimm1, Dimm2. Also it counts the number
409  *     of dimm in the table.
410  *
411  *     @param[in]       Dimm0       Rank type of Dimm0
412  *     @param[in]       Dimm1       Rank type of Dimm1
413  *     @param[in]       Dimm2       Rank type of Dimm2
414  *     @param[in, out]       *RankTypeInTable       Pointer to RankTypeInTable variable
415  *
416  *
417  */
418 VOID
419 MemPConstructRankTypeMap (
420   IN       UINT16 Dimm0,
421   IN       UINT16 Dimm1,
422   IN       UINT16 Dimm2,
423   IN OUT   UINT16 *RankTypeInTable
424   )
425 {
426   UINT8 i;
427   UINT16 RT;
428   UINT8 BitShift;
429
430   *RankTypeInTable = 0;
431   RT = 0;
432   BitShift = 0;
433
434   for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
435     switch (i) {
436     case 0:
437       RT = (Dimm0 == 0) ? NP : Dimm0;
438       BitShift = 0;
439       break;
440     case 1:
441       RT = (Dimm1 == 0) ? NP : Dimm1;
442       BitShift = 4;
443       break;
444     case 2:
445       RT = (Dimm2 == 0) ? NP : Dimm2;
446       BitShift = 8;
447       break;
448     default:
449       // dimm3 is not used, fills nibble3 with "NP"
450       RT = NP;
451       BitShift = 12;
452     }
453     *RankTypeInTable |= RT << BitShift;
454   }
455 }
456
457 /*-----------------------------------------------------------------------------*/
458 /**
459  *     MemPIsIdSupported
460  *      This function matches the CPU_LOGICAL_ID and PackageType with certain criteria to
461  *      determine if it is supported by this NB type.
462  *
463  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
464  *     @param[in]       LogicalId - CPU_LOGICAL_ID
465  *     @param[in]       PackageType - Package Type
466  *
467  *     @return          TRUE -  NB type is matched !
468  *     @return          FALSE - NB type is not matched !
469  *
470  */
471 BOOLEAN
472 MemPIsIdSupported (
473   IN OUT   MEM_NB_BLOCK *NBPtr,
474   IN       CPU_LOGICAL_ID LogicalId,
475   IN       UINT8 PackageType
476   )
477 {
478   CPUID_DATA CpuId;
479   UINT8 PkgType;
480
481   LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, &(NBPtr->MemPtr->StdHeader));
482   PkgType = (UINT8) (CpuId.EBX_Reg >> 28) & 0xF; // bit 31:28
483
484   if (((NBPtr->MCTPtr->LogicalCpuid.Family & LogicalId.Family) != 0)
485       && ((NBPtr->MCTPtr->LogicalCpuid.Revision & LogicalId.Revision) != 0)) {
486     if ((PackageType == PT_DONT_CARE) || (PackageType == PkgType)) {
487       return TRUE;
488     }
489   }
490   return FALSE;
491 }
492
493 /* -----------------------------------------------------------------------------*/
494 /**
495  *
496  *    This function returns the rank type map of a channel.
497  *
498  *     @param[in]       *CurrentChannel       Pointer to CH_DEF_STRUCT
499  *
500  *     @return          UINT16 - The map of rank type.
501  *
502  */
503 UINT16
504 MemPGetPsRankType (
505   IN       CH_DEF_STRUCT *CurrentChannel
506   )
507 {
508   UINT8 i;
509   UINT16 DIMMRankType;
510
511   DIMMRankType = 0;
512   for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
513     if (CurrentChannel->MCTPtr->Status[SbLrdimms]) {
514       // For LrDimm, we construct the map according to Dimm present bits rather than rank type bits
515       if ((CurrentChannel->LrDimmPresent & (UINT8) 1 << i) != 0) {
516         DIMMRankType |= (UINT16) DIMM_LR << (i << 2);
517       } else {
518         DIMMRankType |= (UINT16) NP << (i << 2);
519       }
520     } else {
521       if ((CurrentChannel->DimmQrPresent & (UINT8) 1 << i) != 0) {
522         if (i < 2) {
523           DIMMRankType |= (UINT16) DIMM_QR << (i << 2);
524         }
525       } else if ((CurrentChannel->DimmDrPresent & (UINT8) 1 << i) != 0) {
526         DIMMRankType |= (UINT16) DIMM_DR << (i << 2);
527       } else if ((CurrentChannel->DimmSRPresent & (UINT8) 1 << i) != 0) {
528         DIMMRankType |= (UINT16) DIMM_SR << (i << 2);
529       } else {
530         DIMMRankType |= (UINT16) NP << (i << 2);
531       }
532     }
533   }
534
535   return DIMMRankType;
536 }
537
538 /* -----------------------------------------------------------------------------*/
539 /**
540  *
541  *    This function performs the action for the rest of platform specific configuration such as
542  *    tri-state stuff
543  *
544  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
545  *     @param[in]       *EntryOfTables       Pointer to MEM_PSC_TABLE_BLOCK
546  *
547  *     @return          TRUE - No error occurred.
548  *     @return          FALSE - Error occurred.
549  *
550  */
551 BOOLEAN
552 STATIC
553 MemPPSCGen (
554   IN OUT   MEM_NB_BLOCK *NBPtr,
555   IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
556   )
557 {
558   UINT8 i;
559   PSCFG_TYPE PSCType;
560   DIMM_TYPE DimmType;
561   UINT8 MaxDimmPerCh;
562   UINT8 NOD;
563   CPU_LOGICAL_ID LogicalCpuid;
564   UINT8 PackageType;
565   CH_DEF_STRUCT *CurrentChannel;
566   UINT32 EventInfo;
567
568   CurrentChannel = NBPtr->ChannelPtr;
569
570   PackageType = 0;
571   LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
572   MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
573   NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
574
575   if (CurrentChannel->RegDimmPresent != 0) {
576     DimmType = RDIMM_TYPE;
577   } else if (CurrentChannel->SODimmPresent != 0) {
578     DimmType = SODIMM_TYPE;
579   } else if (CurrentChannel->LrDimmPresent != 0) {
580     DimmType = LRDIMM_TYPE;
581   } else {
582     DimmType = UDIMM_TYPE;
583   }
584
585   for (PSCType = PSCFG_GEN_START + 1; PSCType < PSCFG_GEN_END; PSCType++) {
586     i = 0;
587     while (EntryOfTables->TblEntryOfGen[i] != NULL) {
588       if ((EntryOfTables->TblEntryOfGen[i])->Header.PSCType == PSCType) {
589         if (((EntryOfTables->TblEntryOfGen[i])->Header.DimmType & DimmType) != 0) {
590           if (((EntryOfTables->TblEntryOfGen[i])->Header.NumOfDimm & NOD) != 0) {
591             //
592             // Determine if this is the expected NB Type
593             //
594             LogicalCpuid = (EntryOfTables->TblEntryOfGen[i])->Header.LogicalCpuid;
595             PackageType = (EntryOfTables->TblEntryOfGen[i])->Header.PackageType;
596             if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
597               break;
598             }
599           }
600         }
601       }
602       i++;
603     }
604
605     // Check whether no table entry is found.
606     if (EntryOfTables->TblEntryOfGen[i] == NULL) {
607       IDS_HDT_CONSOLE (MEM_FLOW, "\nNo %s Table\n", (PSCType == PSCFG_CLKDIS) ? "ClkDis" : ((PSCType == PSCFG_CKETRI) ? "CkeTri" : ((PSCType == PSCFG_ODTTRI) ? "OdtTri" : "CsTri")));
608       EventInfo = (PSCType == PSCFG_CLKDIS) ? MEM_ERROR_CLK_DIS_MAP_NOT_FOUND : ((PSCType == PSCFG_CKETRI) ? MEM_ERROR_CKE_TRI_MAP_NOT_FOUND : ((PSCType == PSCFG_ODTTRI) ? MEM_ERROR_ODT_TRI_MAP_NOT_FOUND : MEM_ERROR_CS_TRI_MAP_NOT_FOUND));
609       PutEventLog (AGESA_ERROR, EventInfo, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
610       SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
611       if (!NBPtr->MemPtr->ErrorHandling (NBPtr->MCTPtr, NBPtr->Dct, EXCLUDE_ALL_CHIPSEL, &NBPtr->MemPtr->StdHeader)) {
612         ASSERT (FALSE);
613       }
614       return FALSE;
615     }
616
617     // Perform the action for specific PSCType.
618     if (PSCType == PSCFG_CLKDIS) {
619       CurrentChannel->MemClkDisMap = (UINT8 *) (EntryOfTables->TblEntryOfGen[i])->TBLPtr;
620     } else if (PSCType == PSCFG_CKETRI) {
621       CurrentChannel->CKETriMap = (UINT8 *) (EntryOfTables->TblEntryOfGen[i])->TBLPtr;
622     } else if (PSCType == PSCFG_ODTTRI) {
623       CurrentChannel->ODTTriMap = (UINT8 *) (EntryOfTables->TblEntryOfGen[i])->TBLPtr;
624     } else if (PSCType == PSCFG_CSTRI) {
625       CurrentChannel->ChipSelTriMap = (UINT8 *) (EntryOfTables->TblEntryOfGen[i])->TBLPtr;
626     }
627   }
628
629   CurrentChannel->DctEccDqsLike = 0x0403;
630   CurrentChannel->DctEccDqsScale = 0x70;
631
632   return TRUE;
633 }
634
635
636  /* -----------------------------------------------------------------------------*/
637 /**
638  *
639  *    This function proceeds Table Driven Overriding.
640  *
641  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
642  *     @param[in] PlatformMemoryConfiguration - Pointer to Platform config table
643  *     @param[in] ProceededPSOType - Proceeded PSO type
644  *
645  *     @return          bit0 ~ bit7 - Overriding CS or DIMM map.
646  *     @return          bit15         - Invalid entry found if set.
647  *
648  */
649 UINT16
650 MemPProceedTblDrvOverride (
651   IN OUT   MEM_NB_BLOCK *NBPtr,
652   IN       PSO_TABLE *PlatformMemoryConfiguration,
653   IN       UINT8 ProceededPSOType
654   )
655 {
656   UINT8 *Buffer;
657   UINT8 *PSOStartPtr;
658   UINT8 NumOfReg;
659   UINT8 RetVal;
660   UINT16 RetVal16;
661   BOOLEAN ConfigMatched;
662   BOOLEAN FirstGoThrough;
663   BOOLEAN FindNewConfig;
664   BOOLEAN InvertRetVal;
665   BOOLEAN InvalidConfigDetected;
666
667
668   ASSERT (PlatformMemoryConfiguration != NULL);
669   ASSERT ((ProceededPSOType >= PSO_TBLDRV_START) && (ProceededPSOType <= PSO_TBLDRV_END));
670
671   NumOfReg = 0;
672   RetVal = 0;
673   RetVal16 = 0;
674   FirstGoThrough = TRUE;
675   InvertRetVal = FALSE;
676   InvalidConfigDetected = FALSE;
677   //
678   //   << P E R S P E C T I V E >>
679   //
680   //   PlatformMemoryConfiguration [] = {
681   //     . . . . . . . . . . . . . . . . . . .
682   //     . . . . . . . . . . . . . . . . . . .
683   //    TBLDRV_CONFIG_TO_OVERRIDE (2, DDR1600, VOLT1_5_ + VOLT1_35_, SR_DIMM0 + DR_DIMM1),
684   //       TBLDRV_CONFIG_ENTRY_RTTNOM (CS2_ + CS3_, 2),
685   //       TBLDRV_CONFIG_ENTRY_RTTWR (CS2_, 2),
686   //       TBLDRV_CONFIG_ENTRY_RTTWR (CS3_, 1),
687   //       TBLDRV_CONFIG_ENTRY_ADDRTMG (0x003C3C3C),
688   //       TBLDRV_CONFIG_ENTRY_ODCCTRL (0x20112222),
689   //
690   //     TBLDRV_SPEEDLIMIT_CONFIG_TO_OVERRIDE (2, 2, 0, 0)
691   //       TBLDRV_CONFIG_ENTRY_SPEEDLIMIT (DDR1600_FREQUENCY, DDR1333_FREQUENCY, DDR1066_FREQUENCY),
692   //
693   //     TBLDRV_CONFIG_TO_OVERRIDE (2, DDR1333, VOLT1_5_ + VOLT1_35_, SR_DIMM0 + DR_DIMM1),
694   //       TBLDRV_CONFIG_ENTRY_RTTNOM (CS2_ + CS3_, 3),
695   //       TBLDRV_CONFIG_ENTRY_RTTWR (CS2_ + CS3_, 0),
696   //
697   //     TBLDRV_OVERRIDE_MR0_WR (3, 5)
698   //     TBLDRV_OVERRIDE_MR0_WR (4, 6)
699   //
700   //     TBLDRV_OVERRIDE_MR0_CL (3, 5)
701   //     TBLDRV_OVERRIDE_MR0_CL (4, 6)
702   //     . . . . . . . . . . . . . . . . . . .
703   //     . . . . . . . . . . . . . . . . . . .
704   //
705   //     PSO_END
706   //   }
707   //
708   Buffer = PlatformMemoryConfiguration;
709   // Look for configuration descriptor and its sub-descriptor.
710   while (Buffer[PSO_TYPE] != PSO_END) {
711     FindNewConfig = FALSE;
712     ConfigMatched = FALSE;
713     if (Buffer[PSO_TYPE] == PSO_TBLDRV_CONFIG) {
714       //
715       // Config. descriptor is found, check its sub-descriptor to execute different checking routine.
716       //
717       if ((Buffer[PSO_DATA] == CONFIG_SPEEDLIMIT) && (ProceededPSOType == PSO_TBLDRV_SPEEDLIMIT)) {
718         if (MemPCheckTblDrvOverrideConfigSpeedLimit (NBPtr, &Buffer[PSO_DATA + 1])) {
719           ConfigMatched = TRUE;
720         }
721       } else if (Buffer[PSO_DATA] == CONFIG_DONT_CARE) {
722         ConfigMatched = TRUE;
723       } else {
724         if (MemPCheckTblDrvOverrideConfig (NBPtr, &Buffer[PSO_DATA + 1])) {
725           ConfigMatched = TRUE;
726           if ((Buffer[PSO_DATA] == CONFIG_RC2IBT) && (ProceededPSOType == PSO_TBLDRV_RC2_IBT)) {
727             NumOfReg = Buffer[PSO_DATA + 9];
728           }
729         }
730       }
731     }
732
733     if (ConfigMatched) {
734       //
735       // If config. is matched, parsing "Table Driven PSO" macros behinds this config. macro until PSO_END is reached.
736       //
737       PSOStartPtr = Buffer + (Buffer[PSO_LENGTH] + 2);
738       // Look for the current proceeded PSO type in PlatformMemoryConfiguration array.
739       while ((PSOStartPtr[PSO_TYPE] != PSO_END)) {
740         if (PSOStartPtr[PSO_TYPE] == PSO_TBLDRV_CONFIG) {
741           //
742           // If there is an additional config. macro existed, break this while loop,
743           // then check its content with real platform config. again.
744           // If matched, parsing "Table Driven PSO" macros behind it.
745           //
746           Buffer = PSOStartPtr;
747           FindNewConfig = TRUE;
748           break;
749         } else if (PSOStartPtr[PSO_TYPE] == PSO_TBLDRV_INVALID_TYPE) {
750           InvalidConfigDetected = TRUE;
751           break;
752         }
753
754         if (PSOStartPtr[PSO_TYPE] == ProceededPSOType) {
755           //
756           // Pre-set overriding Cs/Dimm map to "0xFF" for the types which are regardless of Cs/Dimm
757           // for the first time going through the overriding routines.
758           //
759           if (FirstGoThrough) {
760             RetVal = 0xFF;
761           }
762           switch (ProceededPSOType) {
763           case PSO_TBLDRV_SPEEDLIMIT :
764             MemPTblDrvOverrideSpeedLimit (NBPtr, &PSOStartPtr[PSO_DATA]);
765             break;
766
767           case PSO_TBLDRV_ODT_RTTNOM :
768           case PSO_TBLDRV_ODT_RTTWR :
769             // Mask off Cs overridng map to record which Cs has been overridden.
770             RetVal &= ~ MemPTblDrvOverrideODT (NBPtr, &PSOStartPtr[PSO_TYPE]);
771             // Indicate RetVal is inverted.
772             InvertRetVal = TRUE;
773             break;
774
775           case PSO_TBLDRV_ODTPATTERN :
776             MemPTblDrvOverrideODTPattern (NBPtr, &PSOStartPtr[PSO_DATA]);
777             break;
778
779           case PSO_TBLDRV_ADDRTMG :
780             NBPtr->ChannelPtr->DctAddrTmg = *(UINT32 *)&PSOStartPtr[PSO_DATA];
781             IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: AddrTmg = 0x%x for Dct%d\n\n", *(UINT32 *)&PSOStartPtr[PSO_DATA], NBPtr->Dct);
782             break;
783
784           case PSO_TBLDRV_ODCCTRL :
785             NBPtr->ChannelPtr->DctOdcCtl = *(UINT32 *)&PSOStartPtr[PSO_DATA];
786             IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: OdcCtl = 0x%x for Dct%d\n\n", *(UINT32 *)&PSOStartPtr[PSO_DATA], NBPtr->Dct);
787             break;
788
789           case PSO_TBLDRV_SLOWACCMODE :
790             NBPtr->ChannelPtr->SlowMode = (PSOStartPtr[PSO_DATA] == 1) ? TRUE : FALSE;
791             IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: Slow Access Mode = %d for Dct%d\n\n", PSOStartPtr[PSO_DATA], NBPtr->Dct);
792             break;
793
794           case PSO_TBLDRV_RC2_IBT :
795             // Mask off Dimm overridng map to record which Dimm has been overridden.
796             RetVal &= ~ MemPTblDrvOverrideRC2IBT (NBPtr, &PSOStartPtr[PSO_DATA], NumOfReg);
797             // Indicate RetVal is inverted.
798             InvertRetVal = TRUE;
799             break;
800
801           case PSO_TBLDRV_MR0_CL :
802             RetVal = 0;
803             if (MemPTblDrvOverrideMR0WR (NBPtr, &PSOStartPtr[PSO_DATA])) {
804               RetVal = 0xFF;
805             }
806             break;
807
808           case PSO_TBLDRV_MR0_WR :
809             RetVal = 0;
810             if (MemPTblDrvOverrideMR0CL (NBPtr, &PSOStartPtr[PSO_DATA])) {
811               RetVal = 0xFF;
812             }
813             break;
814
815           case PSO_TBLDRV_RC10_OPSPEED :
816             RetVal = 0;
817             if (MemPTblDrvOverrideMR10OpSpeed (NBPtr, &PSOStartPtr[PSO_DATA])) {
818               RetVal = 0xFF;
819             }
820             break;
821
822           case PSO_TBLDRV_LRDIMM_IBT :
823             NBPtr->PsPtr->F0RC8 = PSOStartPtr[PSO_DATA];
824             NBPtr->PsPtr->F1RC0 = PSOStartPtr[PSO_DATA + 1];
825             NBPtr->PsPtr->F1RC1 = PSOStartPtr[PSO_DATA + 2];
826             NBPtr->PsPtr->F1RC2 = PSOStartPtr[PSO_DATA + 3];
827             IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: LRDIMM IBT for Dct%d\n", NBPtr->Dct);
828             IDS_HDT_CONSOLE (MEM_FLOW, "\nF0RC8 = %d, F1RC0 = %d, F1RC1 = %d, F1RC2 = %d", PSOStartPtr[PSO_DATA], PSOStartPtr[PSO_DATA + 1], \
829                                         PSOStartPtr[PSO_DATA + 2], PSOStartPtr[PSO_DATA + 3]);
830             break;
831
832           case PSO_TBLDRV____TRAINING :
833             RetVal = 0x1;
834             NBPtr->Override__Training = (PSOStartPtr[PSO_DATA] == 1) ? TRUE : FALSE;
835             IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: Training = %d for Dct%d\n\n", PSOStartPtr[PSO_DATA], NBPtr->Dct);
836             break;
837
838           default:
839             ASSERT (FALSE);
840           }
841           FirstGoThrough = FALSE;
842         }
843          PSOStartPtr += (PSOStartPtr[PSO_LENGTH] + 2);
844       }
845
846       if (FindNewConfig) {
847         continue;
848       }
849       RetVal = (InvertRetVal) ? ~RetVal : RetVal;
850       RetVal16 = (UINT16) RetVal;
851       if (InvalidConfigDetected) {
852         RetVal16 |= INVALID_CONFIG_FLAG;
853       }
854
855       return RetVal16;
856     }
857      Buffer += (Buffer[PSO_LENGTH] + 2);
858   }
859
860   RetVal = (InvertRetVal) ? ~RetVal : RetVal;
861   RetVal16 = (UINT16) RetVal;
862   if (InvalidConfigDetected) {
863     RetVal16 |= INVALID_CONFIG_FLAG;
864   }
865   return RetVal16;
866 }
867
868 /* -----------------------------------------------------------------------------*/
869 /**
870  *
871  *    This function overrides the speed limit.
872  *
873  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
874  *     @param[in]       *Buffer  - Pointer to Platform config table
875  *
876  */
877 VOID
878 STATIC
879 MemPTblDrvOverrideSpeedLimit (
880   IN OUT   MEM_NB_BLOCK *NBPtr,
881   IN       UINT8 *Buffer
882   )
883 {
884   UINT8 CurrentVoltage;
885
886   IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: Max. Memory Speed for Dct%d\n", NBPtr->Dct);
887
888   LibAmdMemCopy (NBPtr->PsPtr->SpeedLimit, Buffer, 6, &(NBPtr->MemPtr->StdHeader));
889
890   for (CurrentVoltage = VOLT1_5_ENCODED_VAL; CurrentVoltage <= VOLT1_25_ENCODED_VAL; CurrentVoltage ++) {
891     IDS_HDT_CONSOLE (MEM_FLOW, "%s -> %dMHz\t", (CurrentVoltage == VOLT1_5_ENCODED_VAL) ? "1.5V" : ((CurrentVoltage == VOLT1_35_ENCODED_VAL) ? "1.35V" : "1.25V"), NBPtr->PsPtr->SpeedLimit[CurrentVoltage]);
892   }
893   IDS_HDT_CONSOLE (MEM_FLOW, "\n");
894 }
895
896 /* -----------------------------------------------------------------------------*/
897 /**
898  *
899  *    This function overrides the ODTs (RttNom and RttWr).
900  *
901  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
902  *     @param[in]       *Buffer  - Pointer to Platform config table
903  *
904  *     @return          Target CS overriding bit map
905  *
906  */
907 UINT8
908 STATIC
909 MemPTblDrvOverrideODT (
910   IN OUT   MEM_NB_BLOCK *NBPtr,
911   IN       UINT8 *Buffer
912   )
913 {
914   UINT16 i;
915   UINT8 TgtCS;
916
917   IDS_HDT_CONSOLE_DEBUG_CODE (
918     IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: ODT for Dct%d\n", NBPtr->Dct);
919     if (Buffer[0] == PSO_TBLDRV_ODT_RTTNOM) {
920       IDS_HDT_CONSOLE (MEM_FLOW, "RttNom = %d for ", Buffer[3]);
921     } else {
922       IDS_HDT_CONSOLE (MEM_FLOW, "RttWr = %d for ", Buffer[3]);
923     }
924   );
925
926   TgtCS = Buffer[2];
927   for (i = 0; i < MAX_CS_PER_CHANNEL; i++) {
928     if ((NBPtr->DCTPtr->Timings.CsEnabled & (UINT16) (1 << i)) != 0) {
929       if ((TgtCS & (UINT8) 1 << i) != 0) {
930         IDS_HDT_CONSOLE (MEM_FLOW, "CS%d  ", i);
931         if (Buffer[0] == PSO_TBLDRV_ODT_RTTNOM) {
932           NBPtr->PsPtr->RttNom[i] = Buffer[3];
933         } else {
934           NBPtr->PsPtr->RttWr[i] = Buffer[3];
935         }
936       }
937     }
938   }
939   IDS_HDT_CONSOLE (MEM_FLOW, "\n");
940
941   return TgtCS;
942 }
943
944 /* -----------------------------------------------------------------------------*/
945 /**
946  *
947  *    This function overrides the ODT patterns.
948  *
949  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
950  *     @param[in]       *Buffer  - Pointer to Platform config table
951  *
952  */
953 VOID
954 STATIC
955 MemPTblDrvOverrideODTPattern (
956   IN OUT   MEM_NB_BLOCK *NBPtr,
957   IN       UINT8 *Buffer
958   )
959 {
960   CH_DEF_STRUCT *CurrentChannel;
961
962   CurrentChannel = NBPtr->ChannelPtr;
963
964   IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: ODT pattern for Dct%d\n", NBPtr->Dct);
965   IDS_HDT_CONSOLE (MEM_FLOW, "\nRODTCSHigh = 0x%x\n", *(UINT32 *)&Buffer[0]);
966   IDS_HDT_CONSOLE (MEM_FLOW, "\nRODTCSLow = 0x%x\n", *(UINT32 *)&Buffer[4]);
967   IDS_HDT_CONSOLE (MEM_FLOW, "\nWODTCSHigh = 0x%x\n", *(UINT32 *)&Buffer[8]);
968   IDS_HDT_CONSOLE (MEM_FLOW, "\nWODTCSLow = 0x%x\n", *(UINT32 *)&Buffer[12]);
969
970   CurrentChannel->PhyRODTCSHigh = *(UINT32 *)&Buffer[0];
971   CurrentChannel->PhyRODTCSLow = *(UINT32 *)&Buffer[4];
972   CurrentChannel->PhyWODTCSHigh = *(UINT32 *)&Buffer[8];
973   CurrentChannel->PhyWODTCSLow = *(UINT32 *)&Buffer[12];
974
975   //WL ODTs need to be modified as well while overriding...
976   CurrentChannel->PhyWLODT[0] = (UINT8) (CurrentChannel->PhyWODTCSLow & 0x0F);
977   CurrentChannel->PhyWLODT[1] = (UINT8) ((CurrentChannel->PhyWODTCSLow  >> 16) & 0x0F);
978   CurrentChannel->PhyWLODT[2] = (UINT8) (CurrentChannel->PhyWODTCSHigh & 0x0F);
979   CurrentChannel->PhyWLODT[3] = (UINT8) ((CurrentChannel->PhyWODTCSHigh >> 16) & 0x0F);
980
981   IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");
982 }
983
984 /* -----------------------------------------------------------------------------*/
985 /**
986  *
987  *    This function overrides the Ctrl Word 2 and 8.
988  *
989  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
990  *     @param[in]       *Buffer  - Pointer to Platform config table
991  *     @param[in]       NumOfReg  - Number of registers
992  *
993  *     @return          Target DIMM overridng bit map
994  *
995  */
996 UINT8
997 STATIC
998 MemPTblDrvOverrideRC2IBT (
999   IN OUT   MEM_NB_BLOCK *NBPtr,
1000   IN       UINT8 *Buffer,
1001   IN       UINT8 NumOfReg
1002   )
1003 {
1004   UINT16 i;
1005   UINT8 TgtDimm;
1006   CH_DEF_STRUCT *CurrentChannel;
1007
1008   CurrentChannel = NBPtr->ChannelPtr;
1009
1010   IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: RC2[IBT] for Dct%d\n", NBPtr->Dct);
1011   IDS_HDT_CONSOLE (MEM_FLOW, "RC2[IBT] = %d for ", Buffer[1]);
1012
1013   TgtDimm = Buffer[0];
1014   for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
1015     if ((CurrentChannel->ChDimmValid & (UINT16) (1 << i)) != 0) {
1016       if (((TgtDimm & (UINT8) 1 << i) != 0) && (NBPtr->PsPtr->NumOfReg[i] == NumOfReg)) {
1017         IDS_HDT_CONSOLE (MEM_FLOW, "DIMM%d  ", i);
1018         CurrentChannel->CtrlWrd02[i] = (Buffer[1] & 0x1) << 2;
1019         CurrentChannel->CtrlWrd08[i] = (Buffer[1] & 0xE) >> 1;
1020       }
1021     }
1022   }
1023   IDS_HDT_CONSOLE (MEM_FLOW, "\n");
1024
1025   return TgtDimm;
1026 }
1027
1028 /* -----------------------------------------------------------------------------*/
1029 /**
1030  *
1031  *    This function overrides MR0[WR].
1032  *
1033  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
1034  *     @param[in]       *Buffer  - Pointer to Platform config table
1035  *
1036  *     @return          TRUE : Overridden
1037  *     @return          FALSE : Not overriden
1038  *
1039  */
1040 BOOLEAN
1041 STATIC
1042 MemPTblDrvOverrideMR0WR (
1043   IN OUT   MEM_NB_BLOCK *NBPtr,
1044   IN       UINT8 *Buffer
1045   )
1046 {
1047   if (Buffer[0] == (UINT8) NBPtr->GetBitField (NBPtr, BFTcl)) {
1048     NBPtr->PsPtr->MR0CL31 = Buffer[1];
1049     NBPtr->PsPtr->MR0CL0 = Buffer[2];
1050     IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: MR0[CL][3:1] = %d,\tMR0[CL][0] = %d for Dct%d\n", \
1051                                      Buffer[1], Buffer[2], NBPtr->Channel);
1052     IDS_HDT_CONSOLE (MEM_FLOW, "Tcl = %d\n\n", (UINT8) NBPtr->GetBitField (NBPtr, BFTcl));
1053     return TRUE;
1054   }
1055   return FALSE;
1056 }
1057
1058 /* -----------------------------------------------------------------------------*/
1059 /**
1060  *
1061  *    This function overrides MR0[WR].
1062  *
1063  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
1064  *     @param[in]       *Buffer  - Pointer to Platform config table
1065  *
1066  *     @return          TRUE : Overridden
1067  *     @return          FALSE : Not overriden
1068  *
1069  */
1070 BOOLEAN
1071 STATIC
1072 MemPTblDrvOverrideMR0CL (
1073   IN OUT   MEM_NB_BLOCK *NBPtr,
1074   IN       UINT8 *Buffer
1075   )
1076 {
1077   if (Buffer[0] == (UINT8) NBPtr->GetBitField (NBPtr, BFTwrDDR3)) {
1078     NBPtr->PsPtr->MR0WR = Buffer[1];
1079     IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: MR0[WR] = %d for Dct%d\n", Buffer[1], NBPtr->Dct);
1080     IDS_HDT_CONSOLE (MEM_FLOW, "Twr = %d\n\n", (UINT8) NBPtr->GetBitField (NBPtr, BFTwrDDR3));
1081     return TRUE;
1082   }
1083   return FALSE;
1084 }
1085
1086 /* -----------------------------------------------------------------------------*/
1087 /**
1088  *
1089  *    This function overrides MR10[OperatingSpeed].
1090  *
1091  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
1092  *     @param[in]       *Buffer  - Pointer to Platform config table
1093  *
1094  *     @return          TRUE : Overridden
1095  *     @return          FALSE : Not overriden
1096  *
1097  */
1098 BOOLEAN
1099 STATIC
1100 MemPTblDrvOverrideMR10OpSpeed (
1101   IN OUT   MEM_NB_BLOCK *NBPtr,
1102   IN       UINT8 *Buffer
1103   )
1104 {
1105   UINT32 CurDDRrate;
1106   CH_DEF_STRUCT *CurrentChannel;
1107
1108   CurrentChannel = NBPtr->ChannelPtr;
1109   CurDDRrate = (UINT32) (1 << (CurrentChannel->DCTPtr->Timings.Speed / 66));
1110
1111   if ((Buffer[0] & CurDDRrate) != 0) {
1112     NBPtr->PsPtr->RC10OpSpd = Buffer[1];
1113     IDS_HDT_CONSOLE (MEM_FLOW, "\nTable Driven Platform Override: MR10[OperatingSpeed] = %d for Dct%d\n", Buffer[1], NBPtr->Dct);
1114     return TRUE;
1115   }
1116   return FALSE;
1117 }
1118
1119 /* -----------------------------------------------------------------------------*/
1120 /**
1121  *
1122  *    This function checks if platform configuration is matched or not.
1123  *
1124  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
1125  *     @param[in]       *Buffer  - Pointer to Platform config table
1126  *
1127  *     @return          TRUE : Configuration is matched
1128  *     @return          FALSE : Configuration is not matched
1129  *
1130  */
1131 BOOLEAN
1132 STATIC
1133 MemPCheckTblDrvOverrideConfig (
1134   IN OUT   MEM_NB_BLOCK *NBPtr,
1135   IN       UINT8 *Buffer
1136   )
1137 {
1138   UINT8 MaxDimmPerCh;
1139   UINT32 CurDDRrate;
1140   UINT8 DDR3Voltage;
1141   UINT16 RankTypeOfPopulatedDimm;
1142   CH_DEF_STRUCT *CurrentChannel;
1143
1144   CurrentChannel = NBPtr->ChannelPtr;
1145
1146   // Get platform configuration.
1147   MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
1148   CurDDRrate = (UINT32) (1 << (CurrentChannel->DCTPtr->Timings.Speed / 66));
1149   DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
1150   RankTypeOfPopulatedDimm = MemAGetPsRankType (CurrentChannel);
1151
1152   if ((MaxDimmPerCh == Buffer[0]) && ((DDR3Voltage & Buffer[1]) != 0) &&
1153     ((CurDDRrate & *(UINT32 *)&Buffer[2]) != 0) && ((RankTypeOfPopulatedDimm & *(UINT16 *)&Buffer[6]) != 0)) {
1154     return TRUE;
1155   }
1156
1157   return FALSE;
1158 }
1159
1160
1161 /* -----------------------------------------------------------------------------*/
1162 /**
1163  *
1164  *    This function checks if platform configuration is matched or not.
1165  *
1166  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
1167  *     @param[in]       *Buffer  - Pointer to Platform config table
1168  *
1169  *     @return          TRUE : Configuration is matched
1170  *     @return          FALSE : Configuration is not matched
1171  *
1172  */
1173 BOOLEAN
1174 STATIC
1175 MemPCheckTblDrvOverrideConfigSpeedLimit (
1176   IN OUT   MEM_NB_BLOCK *NBPtr,
1177   IN       UINT8 *Buffer
1178   )
1179 {
1180   UINT8 MaxDimmPerCh;
1181   UINT8 NumOfSR;
1182   UINT8 NumOfDR;
1183   UINT8 NumOfQR;
1184   UINT8 NumOfLRDimm;
1185   UINT8 i;
1186   CH_DEF_STRUCT *CurrentChannel;
1187
1188   CurrentChannel = NBPtr->ChannelPtr;
1189   NumOfSR = 0;
1190   NumOfDR = 0;
1191   NumOfQR = 0;
1192   NumOfLRDimm = 0;
1193
1194   // Get platform configuration.
1195   MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
1196
1197   for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
1198     if ((CurrentChannel->DimmSRPresent & (UINT8) (1 << i)) != 0) {
1199       NumOfSR += 1;
1200     } else if ((CurrentChannel->DimmDrPresent & (UINT16) (1 << i)) != 0) {
1201       NumOfDR += 1;
1202     } else if ((CurrentChannel->DimmQrPresent & (UINT16) (1 << i)) != 0) {
1203       if (i < 2) {
1204         NumOfQR += 1;
1205       }
1206     } else if ((CurrentChannel->LrDimmPresent & (UINT16) (1 << i))) {
1207       NumOfLRDimm += 1;
1208     }
1209   }
1210
1211   if ((Buffer[0] == MaxDimmPerCh) && (Buffer[1] == CurrentChannel->Dimms)) {
1212     if (NBPtr->MCTPtr->Status[SbLrdimms] == TRUE) {
1213       if (Buffer[5] == NumOfLRDimm) {
1214         return TRUE;
1215       }
1216     } else {
1217       if ((Buffer[2] == NumOfSR) && (Buffer[3] == NumOfDR) && (Buffer[4] == NumOfQR)) {
1218         return TRUE;
1219       }
1220     }
1221   }
1222
1223   return FALSE;
1224 }
1225