blob: 15546ea5d7ed330be0dd9427e69d1c94ae735b54 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mmConditionalPso.c
6 *
7 * Functions to support conditional entries in the Platform Specific Override Table
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/Main)
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 *----------------------------------------------------------------------------
47 * MODULES USED
48 *
49 *----------------------------------------------------------------------------
50 */
51
52
53
54#include "AGESA.h"
55#include "amdlib.h"
56#include "OptionMemory.h"
57#include "PlatformMemoryConfiguration.h"
58#include "Ids.h"
59#include "Filecode.h"
60CODE_GROUP (G1_PEICC)
61RDATA_GROUP (G1_PEICC)
62
63#define FILECODE PROC_MEM_MAIN_MMCONDITIONALPSO_FILECODE
64/*----------------------------------------------------------------------------
65 * DEFINITIONS AND MACROS
66 *
67 *----------------------------------------------------------------------------
68 */
69
70
71/*----------------------------------------------------------------------------
72 * TYPEDEFS AND STRUCTURES
73 *
74 *----------------------------------------------------------------------------
75 */
76
77#define PSO_TYPE 0
78#define PSO_LENGTH 1
79#define PSO_DATA 2
80
81typedef enum _PSO_STATE {
82 PSO_FIND_CONDITION = 100, // Searching for initial Condition statement
83 PSO_FIND_ACTION, // Searching for initial Action Statement
84 PSO_MATCH_ACTION, // Trying to find an action that matches the caller's request
85 PSO_CHECK_CONDITION, // Checking the condition that preceded the found action
86 PSO_DO_ACTION, // Performing Action
87 PSO_COMPLETE // Completed processing of this request
88} PSO_STATE;
89
90typedef struct _D3_CMP_CAL {
91 UINT32 D3Cmp0NCal :3;
92 UINT32 Reserved34 :2;
93 UINT32 D3Cmp0PCal :3;
94 UINT32 Reserved89 :2;
95 UINT32 D3Cmp1NCal :3;
96 UINT32 Reserved1314 :2;
97 UINT32 D3Cmp1PCal :3;
98 UINT32 Reserved1819 :2;
99 UINT32 D3Cmp2NCal :3;
100 UINT32 Reserved2324 :2;
101 UINT32 D3Cmp2PCal :3;
102 UINT32 Reserved2831 :2;
103} D3_CMP_CAL;
104
105/*----------------------------------------------------------------------------
106 * PROTOTYPES OF LOCAL FUNCTIONS
107 *
108 *----------------------------------------------------------------------------
109 */
110BOOLEAN
111 STATIC
112 MemPSODoActionODT (
113 IN OUT MEM_NB_BLOCK *NBPtr,
114 IN UINT8 *Buffer
115 );
116
117 BOOLEAN
118 STATIC
119 MemPSODoActionAddrTmg (
120 IN OUT MEM_NB_BLOCK *NBPtr,
121 IN UINT8 *Buffer
122 );
123
124 BOOLEAN
125 STATIC
126 MemPSODoActionODCControl (
127 IN OUT MEM_NB_BLOCK *NBPtr,
128 IN UINT8 *Buffer
129 );
130
131 BOOLEAN
132 STATIC
133 MemPSODoActionSlewRate (
134 IN OUT MEM_NB_BLOCK *NBPtr,
135 IN UINT8 *Buffer
136 );
137
138BOOLEAN
139STATIC
140MemPSODoActionGetFreqLimit (
141 IN OUT MEM_NB_BLOCK *NBPtr,
142 IN UINT8 *Buffer
143 );
144
145BOOLEAN
146STATIC
147MemCheckRankType (
148 IN CH_DEF_STRUCT *CurrentChannel,
149 IN UINT16 RankType
150 );
151/*----------------------------------------------------------------------------
152 * EXPORTED FUNCTIONS
153 *
154 *----------------------------------------------------------------------------
155 */
156
157
158/* -----------------------------------------------------------------------------*/
159/**
160 *
161 * Process Conditional Platform Specific Overrides
162 *
163 * @param[in] PlatformMemoryConfiguration - Pointer to Platform config table
164 * @param[in] NBPtr - Pointer to Current NBBlock
165 * @param[in] PsoAction - Action type
166 * @param[in] Dimm - Dimm Number
167 *
168 * @return BOOLEAN - TRUE : Action was performed
169 * FALSE: Action was not performed
170 *
171 * ----------------------------------------------------------------------------
172 */
173BOOLEAN
174MemProcessConditionalOverrides (
175 IN PSO_TABLE *PlatformMemoryConfiguration,
176 IN OUT MEM_NB_BLOCK *NBPtr,
177 IN UINT8 PsoAction,
178 IN UINT8 Dimm
179 )
180{
181 BOOLEAN Result;
182 MEM_TECH_BLOCK *TechPtr;
183 UINT8 *Buffer;
184 UINT8 *ConditionStartPtr;
185 UINT8 *ActionStartPtr;
186 UINT8 *SpdBufferPtr;
187 UINT8 i;
188 UINT8 DimmMask;
189 UINT8 CurDimmMask;
190 BOOLEAN Condition;
191 BOOLEAN TmpCond;
192 PSO_STATE State;
193 ASSERT (PlatformMemoryConfiguration != NULL);
194 ASSERT (NBPtr != NULL);
195 ASSERT ((PsoAction >= PSO_ACTION_MIN) && (PsoAction <= PSO_ACTION_MAX));
196 //
197 // Set up local data
198 //
199 TechPtr = NBPtr->TechPtr;
200 Buffer = PlatformMemoryConfiguration;
201 State = PSO_FIND_CONDITION;
202 ConditionStartPtr = NULL;
203 ActionStartPtr = NULL;
204 Condition = FALSE;
205 DimmMask = 0xFF;
206 CurDimmMask = 0xFF;
207 Result = FALSE;
208
209 if (Dimm != 0xFF) {
210 DimmMask = ( 1 << Dimm);
211 }
212 DimmMask &= (UINT8) (NBPtr->ChannelPtr->ChDimmValid & 0xFF);
213 if (DimmMask == 0) {
214 return Result;
215 }
216
217 //
218 // Search for Condition Entry
219 //
220 while (State != PSO_COMPLETE) {
221 switch (State) {
222 //
223 // Searching for initial Condition statement
224 //
225 case PSO_FIND_CONDITION:
226 ASSERT (Buffer != NULL);
227 while (Buffer[PSO_TYPE] != PSO_CONDITION_AND) {
228 //
229 // If end of table is reached, Change state to complete and break.
230 //
231 if (Buffer[PSO_TYPE] == PSO_END) {
232 State = PSO_COMPLETE;
233 break;
234 }
235 //
236 // Otherwise, increment Buffer Pointer to the next PSO entry.
237 //
238 Buffer += (Buffer[PSO_LENGTH] + 2);
239 }
240 //
241 // If Condition statement has been found, save the Condition Start Pointer,
242 // and change to next state
243 //
244 if (State != PSO_COMPLETE) {
245 ASSERT (Buffer != NULL);
246 State = PSO_FIND_ACTION;
247 ConditionStartPtr = Buffer;
248 Buffer += (Buffer[PSO_LENGTH] + 2);
249 }
250 break;
251 //
252 // Searching for an action that matches the caller's request
253 //
254 case PSO_FIND_ACTION:
255 ASSERT (Buffer != NULL);
256 while (Buffer[PSO_TYPE] != PsoAction) {
257 //
258 // If non-conditional entry, change state to complete and break.
259 //
260 if ((Buffer[PSO_TYPE] < CONDITIONAL_PSO_MIN) || (Buffer[PSO_TYPE] > CONDITIONAL_PSO_MAX)) {
261 State = PSO_COMPLETE;
262 break;
263 }
264 //
265 // Check for the Start of a new condition block
266 //
267 if (Buffer[PSO_TYPE] == PSO_CONDITION_AND) {
268 ConditionStartPtr = Buffer;
269 }
270 //
271 // Otherwise, increment buffer pointer to the next PSO entry.
272 //
273 Buffer += (Buffer[PSO_LENGTH] + 2);
274 }
275 //
276 // If Action statement has been found, Save the Action Start Pointer, Reset Buffer to Condition Start
277 // and Change to next state.
278 //
279 if (State != PSO_COMPLETE) {
280 State = PSO_CHECK_CONDITION;
281 ASSERT (Buffer != NULL);
282 ActionStartPtr = Buffer;
283 Buffer = ConditionStartPtr;
284 Condition = TRUE;
285 }
286 break;
287 //
288 // Checking the condition that preceded the found action
289 //
290 case PSO_CHECK_CONDITION:
291 ASSERT (Buffer != NULL);
292 //
293 // Point to the next Condition
294 //
295 Buffer += (Buffer[PSO_LENGTH] + 2);
296 ASSERT ((Buffer[PSO_TYPE] >= CONDITIONAL_PSO_MIN) && (Buffer[PSO_TYPE] <= CONDITIONAL_PSO_MAX));
297 //
298 // This section has already been checked for invalid statements so just exit on ACTION_xx
299 //
300 if ((Buffer[PSO_TYPE] >= PSO_ACTION_MIN) && (Buffer[PSO_TYPE] <= PSO_ACTION_MAX)) {
301 if (Condition) {
302 ASSERT (Buffer != NULL);
303 State = PSO_DO_ACTION; // Perform the Action
304 } else {
305 State = PSO_FIND_CONDITION; // Go back and look for another condition/action
306 }
307 Buffer = ActionStartPtr; // Restore Action Pointer
308 break;
309 }
310 switch (Buffer[PSO_TYPE]) {
311
312 case PSO_CONDITION_AND:
313 //
314 // Additional CONDITION_AND is ORed with Previous ones, so if Previous result is TRUE
315 // just restore action pointer and perform the action.
316 //
317 if (Condition) {
318 State = PSO_DO_ACTION;
319 Buffer = ActionStartPtr;
320 } else {
321 //
322 // If its false, Start over and evaluate next cond.
323 // reset the Current Dimm Mask
324 //
325 Condition = TRUE;
326 CurDimmMask = 0xFF;
327 }
328 break;
329
330 case PSO_CONDITION_LOC:
331 //
332 // Condition location
333 //
334 CurDimmMask = Buffer[4];
335 Condition &= ( ((Buffer[2] & (1 << (NBPtr->MCTPtr->SocketId))) != 0) &&
336 ((Buffer[3] & (1 << (NBPtr->ChannelPtr->ChannelID))) != 0) &&
337 ((CurDimmMask & DimmMask) != 0) );
338 break;
339
340 case PSO_CONDITION_SPD:
341 //
342 // Condition SPD
343 //
344 TmpCond = FALSE;
345 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i ++) {
346 if ( ((DimmMask & CurDimmMask) & ((UINT16) (1 << i))) != 0) {
347 if (TechPtr->GetDimmSpdBuffer (TechPtr, &SpdBufferPtr, i)) {
348 TmpCond |= ( (SpdBufferPtr[Buffer[2]] & Buffer[3]) == Buffer[4]);
349 }
350 }
351 }
352 Condition &= TmpCond;
353 break;
354
355 case PSO_CONDITION_REG:
356 //
357 // Condition Register - unsupported at this time
358 //
359 break;
360
361 default:
362 ASSERT (FALSE);
363 } // End Condition Switch
364 break;
365
366 case PSO_DO_ACTION:
367 ASSERT (Buffer != NULL);
368 //
369 // Performing Action
370 //
371 if ((Buffer[PSO_TYPE] < PSO_ACTION_MIN) || (Buffer[PSO_TYPE] > PSO_ACTION_MAX)) {
372 State = PSO_COMPLETE;
373 }
374 if (Buffer[PSO_TYPE] == PsoAction) {
375 switch (Buffer[PSO_TYPE]) {
376 case PSO_ACTION_ODT:
377 Result = MemPSODoActionODT (NBPtr, &Buffer[PSO_DATA]);
378 break;
379 case PSO_ACTION_ADDRTMG:
380 Result = MemPSODoActionAddrTmg (NBPtr, &Buffer[PSO_DATA]);
381 break;
382 case PSO_ACTION_ODCCONTROL:
383 Result = MemPSODoActionODCControl (NBPtr, &Buffer[PSO_DATA]);
384 break;
385 case PSO_ACTION_SLEWRATE:
386 Result = MemPSODoActionSlewRate (NBPtr, &Buffer[PSO_DATA]);
387 break;
388 case PSO_ACTION_SPEEDLIMIT:
389 Result = MemPSODoActionGetFreqLimit (NBPtr, &Buffer[PSO_DATA]);
390 break;
391 case PSO_ACTION_REG:
392 break;
393 default:
394 ASSERT (FALSE);
395 } // End Action Switch
396 //
397 // If Action was performed, mark complete.
398 //
399 if (Result) {
400 State = PSO_COMPLETE;
401 }
402 }// End Action
403
404 //
405 // Point to the next PSO Entry
406 //
407 Buffer += (Buffer[PSO_LENGTH] + 2);
408 break;
409
410 case PSO_COMPLETE:
411 //
412 // Completed processing of this request
413 //
414 break;
415
416 default:
417 ASSERT (FALSE);
418 } // End State Switch
419
420 } // End While
421
422 return Result;
423}
424
425/*----------------------------------------------------------------------------
426 * LOCAL FUNCTIONS
427 *
428 *----------------------------------------------------------------------------
429 */
430
431/* -----------------------------------------------------------------------------*/
432/**
433 * Perform ODT Platform Override
434 *
435 * @param[in] NBPtr - Pointer to Current NBBlock
436 * @param[in] Buffer - Pointer to the Action Command Data (w/o Type and Len)
437 *
438 * @return BOOLEAN - TRUE : Action was performed
439 * FALSE: Action was not performed
440 *
441 * ----------------------------------------------------------------------------
442 */
443BOOLEAN
444STATIC
445MemPSODoActionODT (
446 IN OUT MEM_NB_BLOCK *NBPtr,
447 IN UINT8 *Buffer
448 )
449{
450 BOOLEAN Result;
451 UINT32 Speed;
452 UINT8 Dimms;
453 UINT8 i;
454 UINT8 QR_Dimms;
455 Result = FALSE;
456 Speed = ((UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66));
457 Dimms = NBPtr->ChannelPtr->Dimms;
458 QR_Dimms = 0;
459 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
460 if (((NBPtr->ChannelPtr->DimmQrPresent & (UINT16) (1 << i)) != 0) && (i < 2)) {
461 QR_Dimms ++;
462 }
463 }
464 if ((Speed & ((UINT32 *) Buffer)[0]) != 0) {
465 if ((((UINT8) (1 << (Dimms - 1)) & Buffer[4]) != 0) || (Buffer[4] == ANY_NUM)) {
466 if (((QR_Dimms == 0) && (Buffer[5] == NO_DIMM)) ||
467 ((QR_Dimms > 0) && (((UINT8) (1 << (QR_Dimms - 1)) & Buffer[5]) != 0)) ||
468 (Buffer[5] == ANY_NUM)) {
469 NBPtr->PsPtr->DramTerm = Buffer[6];
470 NBPtr->PsPtr->QR_DramTerm = Buffer[7];
471 NBPtr->PsPtr->DynamicDramTerm = Buffer[8];
472 Result = TRUE;
473 IDS_HDT_CONSOLE (MEM_FLOW, " Platform Override: DramTerm:%02x, QRDramTerm:%02x, DynDramTerm:%02x\n", Buffer[6], Buffer[7], Buffer[8]);
474 }
475 }
476 }
477 return Result;
478 }
479
480 /* -----------------------------------------------------------------------------*/
481/**
482 * Perform Address Timing Platform Override
483 *
484 * @param[in] NBPtr - Pointer to Current NBBlock
485 * @param[in] Buffer - Pointer to the Action Command Data (w/o Type and Len)
486 *
487 * @return BOOLEAN - TRUE : Action was performed
488 * FALSE: Action was not performed
489 *
490 * ----------------------------------------------------------------------------
491 */
492BOOLEAN
493STATIC
494MemPSODoActionAddrTmg (
495 IN OUT MEM_NB_BLOCK *NBPtr,
496 IN UINT8 *Buffer
497 )
498{
499 BOOLEAN Result;
500 CH_DEF_STRUCT *ChannelPtr;
501 UINT32 Speed;
502 UINT16 DimmConfig;
503
504 Result = FALSE;
505 ChannelPtr = NBPtr->ChannelPtr;
506 Speed = ((UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66));
507 DimmConfig = *(UINT16 *) &(Buffer[4]);
508
509 if ((Speed & ((UINT32 *) Buffer)[0]) != 0) {
510 if (MemCheckRankType (ChannelPtr, DimmConfig)) {
511 ChannelPtr->DctAddrTmg = *(UINT32*) &(Buffer[6]);
512 Result = TRUE;
513 IDS_HDT_CONSOLE (MEM_FLOW, " Platform Override: Address Timing:%08x\n", *(UINT32*) &(Buffer[6]));
514 }
515 }
516 return Result;
517 }
518
519 /* -----------------------------------------------------------------------------*/
520/**
521 * Perform Drive Strength Platform Override
522 *
523 * @param[in] NBPtr - Pointer to Current NBBlock
524 * @param[in] Buffer - Pointer to the Action Command Data (w/o Type and Len)
525 *
526 * @return BOOLEAN - TRUE : Action was performed
527 * FALSE: Action was not performed
528 *
529 * ----------------------------------------------------------------------------
530 */
531BOOLEAN
532STATIC
533MemPSODoActionODCControl (
534 IN OUT MEM_NB_BLOCK *NBPtr,
535 IN UINT8 *Buffer
536 )
537{
538 BOOLEAN Result;
539 CH_DEF_STRUCT *ChannelPtr;
540 UINT32 Speed;
541 UINT16 DimmConfig;
542
543 Result = FALSE;
544 ChannelPtr = NBPtr->ChannelPtr;
545 Speed = ((UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66));
546 DimmConfig = *(UINT16 *) &(Buffer[4]);
547
548 if ((Speed & ((UINT32 *) Buffer)[0]) != 0) {
549 if (MemCheckRankType (ChannelPtr, DimmConfig)) {
550 ChannelPtr->DctOdcCtl = *(UINT32*) &(Buffer[6]);
551 Result = TRUE;
552 IDS_HDT_CONSOLE (MEM_FLOW, " Platform Override: ODC Control:%08x\n", *(UINT32*)&(Buffer[6]));
553 }
554 }
555 return Result;
556 }
557
558 /* -----------------------------------------------------------------------------*/
559/**
560 * Perform Slew Rate Platform Override
561 *
562 * @param[in] NBPtr - Pointer to Current NBBlock
563 * @param[in] Buffer - Pointer to the Action Command Data (w/o Type and Len)
564 *
565 * @return BOOLEAN - TRUE : Action was performed
566 * FALSE: Action was not performed
567 *
568 * ----------------------------------------------------------------------------
569 */
570BOOLEAN
571STATIC
572MemPSODoActionSlewRate (
573 IN OUT MEM_NB_BLOCK *NBPtr,
574 IN UINT8 *Buffer
575 )
576{
577 BOOLEAN Result;
578 CH_DEF_STRUCT *ChannelPtr;
579 UINT32 Speed;
580 UINT16 DimmConfig;
581
582 Result = FALSE;
583 ChannelPtr = NBPtr->ChannelPtr;
584 Speed = ((UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66));
585 DimmConfig = *(UINT16 *) &(Buffer[4]);
586
587 if ((Speed & ((UINT32 *) Buffer)[0]) != 0) {
588 if (MemCheckRankType (ChannelPtr, DimmConfig)) {
589 MemNSetBitFieldNb (NBPtr, BFD3Cmp0NCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp0NCal );
590 MemNSetBitFieldNb (NBPtr, BFD3Cmp0PCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp0PCal );
591 MemNSetBitFieldNb (NBPtr, BFD3Cmp1NCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp1NCal );
592 MemNSetBitFieldNb (NBPtr, BFD3Cmp1PCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp1PCal );
593 MemNSetBitFieldNb (NBPtr, BFD3Cmp2NCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp2NCal );
594 MemNSetBitFieldNb (NBPtr, BFD3Cmp2PCal, ((D3_CMP_CAL *) &(Buffer[6]))->D3Cmp2PCal );
595 Result = TRUE;
596 IDS_HDT_CONSOLE (MEM_FLOW, " Platform Override: Slew Rate:%08x\n", *(UINT32 *) &(Buffer[6]));
597 }
598 }
599 return Result;
600 }
601
602/* -----------------------------------------------------------------------------*/
603/**
604 *
605 * This function overrides the POR supported speed for a specific config
606 *
607 * @param[in] NBPtr - Pointer to Current NBBlock
608 * @param[in] Buffer - Pointer to the Action Command Data (w/o Type and Len)
609 *
610 * @return BOOLEAN - TRUE : Action was performed
611 * FALSE: Action was not performed
612 *
613 */
614BOOLEAN
615STATIC
616MemPSODoActionGetFreqLimit (
617 IN OUT MEM_NB_BLOCK *NBPtr,
618 IN UINT8 *Buffer
619 )
620{
621 BOOLEAN Result;
622 CH_DEF_STRUCT *ChannelPtr;
623 DCT_STRUCT *DCTPtr;
624 UINT16 DimmConfig;
625 UINT16 SpeedLimit;
626
627 Result = FALSE;
628 ChannelPtr = NBPtr->ChannelPtr;
629 DCTPtr = NBPtr->DCTPtr;
630 DimmConfig = *(UINT16*) &(Buffer[0]);
631 SpeedLimit = 0;
632 //
633 // Match number of dimms, then Rank Type
634 //
635 if (ChannelPtr->Dimms == Buffer[2]) {
636 if (MemCheckRankType (ChannelPtr, DimmConfig)) {
637 //
638 // Select speed based on current voltage
639 //
640 if (NBPtr->RefPtr->DDR3Voltage == VOLT1_5) {
641 SpeedLimit = *(UINT16*) &(Buffer[3]);
642 } else if (NBPtr->RefPtr->DDR3Voltage == VOLT1_25) {
643 SpeedLimit = *(UINT16*) &(Buffer[7]);
644 } else {
645 SpeedLimit = *(UINT16*) &(Buffer[5]);
646 }
647 //
648 // Set the Speed limit
649 //
650 if (DCTPtr->Timings.TargetSpeed > SpeedLimit) {
651 DCTPtr->Timings.TargetSpeed = SpeedLimit;
652 }
653 Result = TRUE;
654 IDS_HDT_CONSOLE (MEM_FLOW, " Platform Override: Max Memory Speed for Channel %d: %d\n", NBPtr->Channel, SpeedLimit);
655 }
656 }
657 return Result;
658}
659
660 /* -----------------------------------------------------------------------------*/
661/**
662 *
663 * This function matches a particular Rank Type Mask to the installed
664 * DIMM configuration on the provided channel.
665 *
666 * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
667 * @param[in] RankType Mask of rank type to match
668 *
669 * @return BOOLEAN - TRUE : Rank types match
670 * FALSE: Rank types do not match
671 *
672 */
673BOOLEAN
674STATIC
675MemCheckRankType (
676 IN CH_DEF_STRUCT *CurrentChannel,
677 IN UINT16 RankType
678 )
679{
680 BOOLEAN Result;
681 UINT8 i;
682 UINT16 DIMMRankType;
683
684 DIMMRankType = MemAGetPsRankType (CurrentChannel);
685 Result = TRUE;
686 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
687 if ( ((DIMMRankType & (0x0F << (i << 2))) + (RankType & (0x0F << (i << 2)))) != 0) {
688 Result &= (((DIMMRankType & (0x0F << (i << 2))) & ( RankType & ( 0x0F << ( i << 2)))) != 0);
689 }
690 if (!Result) {
691 break;
692 }
693 }
694 return Result;
695}