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