5 * AMD CPU Pstate Leveling Function.
7 * Contains code to level the Pstates in a multi-socket system
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
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.
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.
42 ******************************************************************************
43 *----------------------------------------------------------------------------
48 *----------------------------------------------------------------------------
51 *----------------------------------------------------------------------------
55 #include "OptionPstate.h"
56 #include "cpuLateInit.h"
57 #include "cpuRegisters.h"
58 #include "cpuPostInit.h"
60 #include "cpuFamilyTranslation.h"
61 #include "cpuPstateTables.h"
62 #include "cpuApicUtilities.h"
63 #include "cpuServices.h"
64 #include "GeneralServices.h"
69 #define FILECODE PROC_CPU_FEATURE_CPUPSTATELEVELING_FILECODE
71 /*----------------------------------------------------------------------------
72 * DEFINITIONS AND MACROS
74 *----------------------------------------------------------------------------
76 extern OPTION_PSTATE_POST_CONFIGURATION OptionPstatePostConfiguration; // global user config record
77 extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
79 /*----------------------------------------------------------------------------
80 * TYPEDEFS AND STRUCTURES
82 *----------------------------------------------------------------------------
85 /*----------------------------------------------------------------------------
86 * PROTOTYPES OF LOCAL FUNCTIONS
88 *----------------------------------------------------------------------------
92 IN OUT PSTATE_LEVELING *PStateBufferPtr,
93 IN AMD_CONFIG_PARAMS *StdHeader
97 StartPstateMsrModify (
98 IN S_CPU_AMD_PSTATE *CpuAmdPState,
99 IN AMD_CONFIG_PARAMS *StdHeader
105 IN VOID *PStateBuffer,
106 IN AMD_CONFIG_PARAMS *StdHeader
111 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
112 IN AMD_CONFIG_PARAMS *StdHeader
117 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
118 IN AMD_CONFIG_PARAMS *StdHeader
122 CorePstateRegModify (
123 IN VOID *CpuAmdPState,
124 IN AMD_CONFIG_PARAMS *StdHeader
130 *---------------------------------------------------------------------------------------
135 * This function will populate the PStateBuffer, after doing the PState Leveling
136 * Note: This function should be called for every core in the system.
139 * @param[in,out] *PStateStrucPtr
140 * @param[in] *StdHeader
142 * @retval AGESA_STATUS
144 *---------------------------------------------------------------------------------------
148 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
149 IN AMD_CONFIG_PARAMS *StdHeader
152 AGESA_TESTPOINT (TpProcCpuEntryPstateLeveling, StdHeader);
153 return ((*(OptionPstatePostConfiguration.PstateLeveling)) (PStateStrucPtr, StdHeader));
154 // Note: Split config struct into PEI/DXE halves. This one is PEI.
157 /**--------------------------------------------------------------------------------------
162 * This is the default routine for use when the PState option is NOT requested.
163 * The option install process will create and fill the transfer vector with
164 * the address of the proper routine (Main or Stub). The link optimizer will
165 * strip out of the .DLL the routine that is not used.
168 * @param[in,out] *PStateStrucPtr
169 * @param[in] *StdHeader
171 * @retval AGESA_STATUS
173 *---------------------------------------------------------------------------------------
177 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
178 IN AMD_CONFIG_PARAMS *StdHeader
181 return AGESA_UNSUPPORTED;
184 /**--------------------------------------------------------------------------------------
189 * This is the common routine for creating the ACPI information tables.
192 * @param[in,out] *PStateStrucPtr
193 * @param[in] *StdHeader
195 * @retval AGESA_STATUS
197 *---------------------------------------------------------------------------------------
201 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
202 IN AMD_CONFIG_PARAMS *StdHeader
208 UINT32 TotalIterations;
209 UINT32 LogicalSocketCount;
218 UINT32 TempFreqArray[20];
219 UINT32 TempPowerArray[20];
220 UINT32 TempIddValueArray[20];
221 UINT32 TempIddDivArray[20];
222 UINT32 TempSocketPiArray[20];
223 UINT32 TempSwP0Array[MAX_SOCKETS_SUPPORTED];
229 BOOLEAN AllCoresHaveHtcCapEquToZeroFlag;
230 BOOLEAN AllCoreHaveMaxOnePStateFlag;
231 BOOLEAN PstateMaxValEquToPstateHtcLimitFlag;
232 BOOLEAN AtLeastOneCoreHasPstateHtcLimitEquToOneFlag;
233 BOOLEAN PstateMaxValMinusHtcPstateLimitLessThan2Flag;
234 PSTATE_LEVELING *PStateBufferPtr;
235 PSTATE_LEVELING *PStateBufferPtrTmp;
236 UINT32 MaxPstateInNode;
243 AllCoresHaveHtcCapEquToZeroFlag = FALSE;
244 AllCoreHaveMaxOnePStateFlag = FALSE;
245 PstateMaxValEquToPstateHtcLimitFlag = FALSE;
246 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE;
247 PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE;
248 PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
249 Status = AGESA_SUCCESS;
251 if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) {
252 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
253 PStateBufferPtr[0].InitStruct = 1;
254 return AGESA_UNSUPPORTED;
257 LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem;
258 ASSERT (LogicalSocketCount <= MAX_SOCKETS_SUPPORTED);
260 // This section of code will execute only for "core 0" i.e. BSP
261 // Read P-States of all the cores.
262 if (PStateBufferPtr[0].InitStruct == 0) {
263 // Determine 'software' P0 indices for each socket
264 for (i = 0; i < LogicalSocketCount; i++) {
265 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
266 TempSwP0Array[i] = (UINT32) (PStateBufferPtrTmp->PStateCoreStruct[0].NumberOfBoostedStates);
269 // Check if core frequency and power are same across all sockets.
271 for (i = 1; i < LogicalSocketCount; i++) {
272 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
273 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) {
277 MaxPstateInNode = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
278 for (k = TempSwP0Array[i]; k <= MaxPstateInNode; k++) {
279 if ((PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[k].CoreFreq !=
280 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq) ||
281 (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[k].Power !=
282 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].Power)) {
284 break; // Come out of the inner FOR loop
288 break; // Come out of the outer FOR loop
293 // No need to do pStateLeveling, or writing to pState MSR registers
294 // if all CPUs have Identical PStates
295 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
296 PStateBufferPtr[0].InitStruct = 1;
297 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
298 return AGESA_UNSUPPORTED;
300 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE;
306 for (i = 0; i < LogicalSocketCount; i++) {
307 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
308 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == TempSwP0Array[i]) {
313 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) {
319 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
320 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) {
321 PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
324 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue ==
325 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
326 PstateMaxValEquToPstateHtcLimitFlag = TRUE;
329 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
330 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
334 // Do general setup of flags, that we may use later
335 // Implementation of (1_b)
336 if (TempFlag1 && TempFlag2) {
338 //Processors with only one enabled P-state (F3xDC[PstateMaxVal]=000b) cannot be mixed in a system with
339 //processors with more than one enabled P-state (F3xDC[PstateMaxVal]!=000b).
341 PStateBufferPtr[0].InitStruct = 1;
342 PStateBufferPtr[0].CreateAcpiTables = 0;
343 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
344 return AGESA_UNSUPPORTED;
345 } else if (TempFlag1 && !TempFlag2) {
347 //all processors have only 1 enabled P-state
349 AllCoreHaveMaxOnePStateFlag = TRUE;
350 PStateBufferPtr[0].OnlyOneEnabledPState = TRUE;
353 // Processors with F3xE8[HTC_CAPABLE] = 1 can not be
354 // mixed in system with processors with F3xE8[HTC_CAPABLE] = 0.
355 if (TempFlag3 && TempFlag4) {
356 PStateBufferPtr[0].InitStruct = 1;
357 PStateBufferPtr[0].CreateAcpiTables = 0;
358 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
359 return AGESA_UNSUPPORTED;
364 //If code run to here means that all processors do not have HTC_CAPABLE.
366 AllCoresHaveHtcCapEquToZeroFlag = TRUE;
369 //--------------------------------------------------------------------------------
371 //--------------------------------------------------------------------------------
372 // Now run the PState Leveling Algorithm which will create mixed CPU P-State
374 // Follow the algorithm in the latest BKDG
375 // -------------------------------------------------------------------------------
376 // Match P0 CPU COF for all CPU cores to the lowest P0 CPU COF value in the
377 // coherent fabric, and match P0 power for all CPU cores to the highest P0 power
378 // value in the coherent fabric.
379 // 2_a) If all processors have only 1 enabled P-State BIOS must write the
380 // appropriate CpuFid value resulting from the matched CPU COF to all
381 // copies of MSRC001_0070[CpuFid], and exit the sequence (No further
382 // steps are executed)
383 //--------------------------------------------------------------------------------
384 // Identify the lowest P0 Frequency and maximum P0 Power
385 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].CoreFreq;
386 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].Power;
387 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddValue;
388 TempVar_b = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddDiv;
390 for (i = 0; i < LogicalSocketCount; i++) {
391 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
392 if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq) {
393 TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq;
396 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power) {
397 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power;
398 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue;
399 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv;
403 // Set P0 Frequency and Power for all CPUs
404 for (i = 0; i < LogicalSocketCount; i++) {
405 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
406 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq = TempVar_d;
407 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power = TempVar_e;
408 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue = TempVar_a;
409 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv = TempVar_b;
413 if (!AllCoreHaveMaxOnePStateFlag) {
414 //--------------------------------------------------------------------------
416 //--------------------------------------------------------------------------
417 // Match the CPU COF and power for P-states used by HTC. Skip to step 4
418 // is any processor reports F3xE8[HTC_Capable] = 0;
419 // 3_a) Set F3x64[HtcPstateLimit] = 001b and F3x68[StcPstateLimit] = 001b for
420 // processors with F3x64[HtcPstateLimit] = 000b.
421 // 3_b) Identify the lowest CPU COF for all processors in the P-state
422 // pointed to by [The Hardware Thermal Control (HTC) Register]
423 // F3x64[HtcPstateLimit]
424 // 3_c) Modify the CPU COF pointed to by [The Hardware Thermal Control
425 // (HTC) Register] F3x64[HtcPstateLimit] for all processors to the
426 // previously identified lowest CPU COF value.
427 // 3_d) Identify the highest power for all processors in the P-state
428 // pointed to by [The Hardware Thermal Control (HTC) Register]
429 // F3x64[HtcPstateLimit].
430 // 3_e) Modify the power pointed to by [The Hardware Thermal Control (HTC)
431 // Register] F3x64[HtcPstateLimit] to the previously identified
432 // highest power value.
433 if (!AllCoresHaveHtcCapEquToZeroFlag) {
435 for (i = 0; i < LogicalSocketCount; i++) {
436 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
437 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 0) {
438 // To Be Done (Set Htc and Stc PstateLimit values)
439 // for this CPU (using PCI address space)
440 for (k = 0; k < (UINT8)GetPlatformNumberOfModules (); k++) {
441 if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, k, &PciAddress, &Status)) {
442 // Set F3x64[HtcPstateLimit] = 001b
443 PciAddress.Address.Function = FUNC_3;
444 PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
445 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
447 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
448 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
450 // Set F3x68[StcPstateLimit] = 001b
451 PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG;
452 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
454 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
455 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
459 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1;
460 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) {
461 PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
464 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) {
465 PstateMaxValEquToPstateHtcLimitFlag = TRUE;
469 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
470 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
475 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit;
476 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
477 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
478 TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
479 TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
480 for (i = 0; i < LogicalSocketCount; i++) {
481 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
482 for (k = 0; k < 1; k++) {
483 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
484 if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
485 TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
488 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
489 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
490 TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
491 TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
497 for (i = 0; i < LogicalSocketCount; i++) {
498 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
499 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
500 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
501 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
502 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
503 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
505 } // if(AllCoresHaveHtcCapEquToZeroFlag)
508 //--------------------------------------------------------------------------
510 //--------------------------------------------------------------------------
511 // Match the CPU COF and power for the lowest performance P-state:
512 // 4_a) If F3xDC[PstateMaxVal] = F3x64[HtcPstateLimit] for any processor,
513 // set PstateEn = 0 for all the P-states greater than
514 // F3x64[HtcPstateLimit] for all processors.
515 // 4_b) Identify the lowest CPU COF for all processors in the P-state
516 // pointed to by F3xDC[PstateMaxVal].
517 // 4_c) Modify the CPU COF for all processors in the P-state pointed to by
518 // F3xDC[PstateMaxVal] to the previously identified lowest CPU COF
520 // 4_d) Identify the highest power for all processors in the P-state
521 // pointed to by F3xDC[PstateMaxVal].
522 // 4_e) Modify the power for all processors in the P-state pointed to by
523 // F3xDC[PstateMaxVal] to the previously identified highest power
527 if (PstateMaxValEquToPstateHtcLimitFlag) {
528 for (i = 0; i < LogicalSocketCount; i++) {
529 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
530 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit + 1;
531 for (k = TempVar_b; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++) {
532 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
534 //--------------------------------------------------------------------------
536 //--------------------------------------------------------------------------
537 // 5_a) Modify F3xDC[PstateMaxVal] to indicate the lowest performance
538 // P-state with PstateEn set for each processor (Step 4 can disable
539 // P-states pointed to by F3xDC[PstateMaxVal])
541 // Use this value of HtcPstateLimit to program the
542 // F3xDC[pStateMaxValue]
543 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
547 for (m = 0; m < (UINT8)GetPlatformNumberOfModules (); m++) {
548 if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, m, &PciAddress, &Status)) {
549 PciAddress.Address.Function = FUNC_3;
550 PciAddress.Address.Register = CLOCK_POWER_TIMING_CTRL2_REG;
551 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
552 TempVar_d = (TempVar_d & 0xFFFFF8FF) | TempVar_e;
553 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
560 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue;
561 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
562 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
563 TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
564 TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
566 for (i = 0; i < LogicalSocketCount; i++) {
567 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
568 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
570 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
572 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
575 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
576 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
577 TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
578 TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
583 for (i = 0; i < LogicalSocketCount; i++) {
584 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
585 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
586 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
587 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
588 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
589 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
593 //--------------------------------------------------------------------------
595 //--------------------------------------------------------------------------
596 // Match the CPU COF and power for upper intermediate performance
598 // Upper intermediate PStates = PStates between (Not including) P0 and
599 // F3x64[HtcPstateLimit]
600 // 6_a) If F3x64[HtcPstateLimit] = 001b for any processor, set PstateEn = 0
601 // for enabled upper intermediate P-states for all processors with
602 // F3x64[HtcPstateLimit] > 001b and skip the remaining actions for
603 // this numbered step.
604 // 6_b) Define each of the available upper intermediate P-states; for each
605 // processor concurrently evaluate the following loop; when any
606 // processor falls out of the loop (runs out of available upper
607 // intermediate Pstates) all other processors have their remaining
608 // upper intermediate P-states invalidated (PstateEn = 0);
609 // for (i = F3x64[HtcPstateLimit] - 1; i > 0; i--)
610 // - Identify the lowest CPU COF for P(i).
611 // - Identify the highest power for P(i).
612 // - Modify P(i) CPU COF for all processors to the previously
613 // identified lowest CPU COF value.
614 // - Modify P(i) power for all processors to the previously
615 // identified highest power value.
618 if (AtLeastOneCoreHasPstateHtcLimitEquToOneFlag) {
619 for (i = 0; i < LogicalSocketCount; i++) {
620 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
621 for (k = TempSwP0Array[i] + 1; k < (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit); k++) {
622 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit > 1) {
623 // Make a function call to clear the
625 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
632 // Identify Lowest Frequency and Highest Power
636 for (i = 0; i < LogicalSocketCount; i++) {
637 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
638 TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1;
642 //For first socket, try to find a candidate
643 if (TempSocketPiArray[0] != TempSwP0Array[0]) {
644 while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
645 TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
646 if (TempSocketPiArray[0] == TempSwP0Array[0]) {
655 TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
656 TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
657 TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
658 TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
660 //Try to find next candidate
661 for (i = 1; i < LogicalSocketCount; i++) {
662 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
663 if (TempSocketPiArray[i] != TempSwP0Array[i]) {
664 while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
665 TempSocketPiArray[i]--;
666 if (TempSocketPiArray[i] == TempSwP0Array[i]) {
675 } //end for LogicalSocketCount
679 for (i = 0; i < LogicalSocketCount; i++) {
683 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
684 if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
685 TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
688 if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
689 TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
690 TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
691 TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
694 // Modify (Pi) CPU COF and Power for all the CPUs
695 for (i = 0; i < LogicalSocketCount; i++) {
696 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
697 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
698 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
699 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
700 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
701 TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
704 for (i = 0; i < LogicalSocketCount; i++) {
705 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
706 for (m = TempSocketPiArray[i]; m > TempSwP0Array[i]; m--) {
707 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
717 //--------------------------------------------------------------------------
719 //--------------------------------------------------------------------------
720 // Match the CPU COF and power for lower intermediate performance P - state(s)
721 // Lower Intermediate Pstates = Pstates between (not including)
722 // F3x64[HtcPstateLimit] and F3xDC[PstateMaxVal]
723 // 7_a) If F3xDC[PstateMaxVal] - F3x64[HtcPstateLimit] < 2 for any
724 // processor, set PstateEn = 0 for enabled lower intermediate P - states
725 // for all processors with (F3xDC[PstateMaxVal] -
726 // F3x64[HtcPstateLimit] > 1) and skip the remaining actions for this
728 // 7_b) Define each of the available lower intermediate P-states; for each
729 // processor concurrently evaluate the following loop; when any
730 // processor falls out of the loop (runs out of available lower
731 // intermediate Pstates) all other processors have their remaining
732 // lower intermediate P-states invalidated (PstateEn = 0);
733 // for (i = F3xDC[PstateMaxVal]-1; i > F3x64[HtcPstateLimit]; i--)
734 // - Identify the lowest CPU COF for P-states between
735 // (not including) F3x64[HtcPstateLimit] and P(i).
736 // - Identify the highest power for P-states between
737 // (not including) F3x64[HtcPstateLimit] and P(i).
738 // - Modify P(i) CPU COF for all processors to the previously
739 // identified lowest CPU COF value.
740 // - Modify P(i) power for all processors to the previously
741 // identified highest power value.
745 if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) {
746 for (i = 0; i < LogicalSocketCount; i++) {
747 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
749 for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
750 k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
752 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
753 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) {
754 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
762 // Identify Lowest Frequency and Highest Power
767 for (i = 0; i < LogicalSocketCount; i++) {
768 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
769 TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
773 //For first socket, try to find a candidate
774 if (TempSocketPiArray[0] != PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
775 while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
776 TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
777 if (TempSocketPiArray[0] == PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
786 TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
787 TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
788 TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
789 TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
791 //Try to find next candidate
792 for (i = 1; i < LogicalSocketCount; i++) {
793 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
794 if (TempSocketPiArray[i] != PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
795 while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
796 TempSocketPiArray[i]--;
797 if (TempSocketPiArray[i] == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
805 } //end for LogicalSocketCount
809 for (i = 0; i < LogicalSocketCount; i++) {
813 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
814 if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
815 TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
817 if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
818 TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
819 TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
820 TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
823 // Modify (Pi) CPU COF and Power for all the CPUs
824 for (i = 0; i < LogicalSocketCount; i++) {
825 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
826 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
827 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
828 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
829 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
830 TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
833 for (i = 0; i < LogicalSocketCount; i++) {
834 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
835 for (m = TempSocketPiArray[i]; m > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; m--) {
836 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
843 } // if(!AllCoreHaveMaxOnePStateFlag)
845 PStateBufferPtr[0].InitStruct = 1;
849 // Update the pState MSRs
850 // This can be done only by individual core
851 StartPstateMsrModify (PStateStrucPtr, StdHeader);
853 //----------------------------------------------------------------------------------
855 //----------------------------------------------------------------------------------
856 // Place all cores into a valid COF and VID configuration corresponding to an
858 // 8_a) Select an enabled P-state != to the P-state pointed to by
859 // MSRC001_0063[CurPstate] for each core.
860 // 8_b) Transition all cores to the selected P-states by writing the Control value
861 // from the_PSS object corresponding to the selected P-state to
862 // MSRC001_0062[PstateCmd].
863 // 8_c) Wait for all cores to report the Status value from the _PSS object
864 // corresponding to the selected P-state in MSRC001_0063[CurPstate].
866 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
868 return AGESA_SUCCESS;
872 /*----------------------------------------------------------------------------
875 *----------------------------------------------------------------------------
879 *---------------------------------------------------------------------------------------
881 * PutAllCoreInPState0
884 * This function will put core pstate to p0.
887 * @param[in,out] *PStateBufferPtr
888 * @param[in] *StdHeader
890 * @retval AGESA_STATUS
892 *---------------------------------------------------------------------------------------
895 PutAllCoreInPState0 (
896 IN OUT PSTATE_LEVELING *PStateBufferPtr,
897 IN AMD_CONFIG_PARAMS *StdHeader
906 UINT32 NumberOfSockets;
907 UINT32 NumberOfCores;
908 AGESA_STATUS IgnoredSts;
910 TaskPtr.FuncAddress.PfApTaskI = PutCoreInPState0;
911 TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PSTATE_LEVELING);
912 TaskPtr.ExeFlags = WAIT_FOR_CORE;
913 TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
914 TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
916 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
917 NumberOfSockets = GetPlatformNumberOfSockets ();
919 PutCoreInPState0 (PStateBufferPtr, StdHeader);
921 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
922 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
923 for (Core = 0; Core < NumberOfCores; Core++) {
924 if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
925 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
931 return AGESA_SUCCESS;
935 *---------------------------------------------------------------------------------------
937 * CorePstateRegModify
940 * This function will setting the Pstate MSR to each APs base on Pstate Buffer.
941 * Note: This function should be called for every core in the system.
944 * @param[in,out] *CpuAmdPState
945 * @param[in] *StdHeader
949 *---------------------------------------------------------------------------------------
952 CorePstateRegModify (
953 IN VOID *CpuAmdPState,
954 IN AMD_CONFIG_PARAMS *StdHeader
957 PSTATE_CPU_FAMILY_SERVICES *FamilySpecificServices;
958 FamilySpecificServices = NULL;
960 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilySpecificServices, StdHeader);
961 ASSERT (FamilySpecificServices != NULL)
962 FamilySpecificServices->SetPStateLevelReg (FamilySpecificServices, (S_CPU_AMD_PSTATE *) CpuAmdPState, StdHeader);
966 /*---------------------------------------------------------------------------------------*/
968 * This function will set msr on all cores of all nodes.
970 * @param[in] CpuAmdPState Pointer to S_CPU_AMD_PSTATE.
971 * @param[in] StdHeader Header for library and services.
973 * @retval AGESA_SUCCESS Always succeeds
977 StartPstateMsrModify (
978 IN S_CPU_AMD_PSTATE *CpuAmdPState,
979 IN AMD_CONFIG_PARAMS *StdHeader
988 UINT32 NumberOfSockets;
989 UINT32 NumberOfCores;
990 AGESA_STATUS IgnoredSts;
992 TaskPtr.FuncAddress.PfApTaskI = CorePstateRegModify;
993 TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) (CpuAmdPState->SizeOfBytes / 4 + 1);
994 TaskPtr.ExeFlags = WAIT_FOR_CORE;
995 TaskPtr.DataTransfer.DataPtr = CpuAmdPState;
996 TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
998 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
999 NumberOfSockets = GetPlatformNumberOfSockets ();
1001 CorePstateRegModify (CpuAmdPState, StdHeader);
1003 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
1004 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
1005 for (Core = 0; Core < NumberOfCores; Core++) {
1006 if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
1007 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
1013 return AGESA_SUCCESS;
1018 *---------------------------------------------------------------------------------------
1020 * CpuGetPStateLevelStructure
1023 * Based on the LogicalSocketNumber, this function will return a pointer
1024 * point to the accurate offset of the PSTATE_LEVELING structure.
1027 * @param[in,out] *PStateBufferPtr
1028 * @param[in] *CpuAmdPState
1029 * @param[in] LogicalSocketNumber
1030 * @param[in] *StdHeader
1034 *---------------------------------------------------------------------------------------
1037 CpuGetPStateLevelStructure (
1038 OUT PSTATE_LEVELING **PStateBufferPtr,
1039 IN S_CPU_AMD_PSTATE *CpuAmdPState,
1040 IN UINT32 LogicalSocketNumber,
1041 IN AMD_CONFIG_PARAMS *StdHeader
1044 PSTATE_LEVELING *PStateBufferPtrTmp;
1047 if (LogicalSocketNumber > CpuAmdPState->TotalSocketInSystem) {
1048 return AGESA_UNSUPPORTED;
1051 PStateBufferPtrTmp = CpuAmdPState->PStateLevelingStruc;
1053 for (i = 1; i <= LogicalSocketNumber; i++) {
1054 PStateBufferPtrTmp = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtrTmp + ((UINTN) PStateBufferPtrTmp->PStateLevelingSizeOfBytes));
1057 *PStateBufferPtr = PStateBufferPtrTmp;
1059 return AGESA_SUCCESS;
1064 *---------------------------------------------------------------------------------------
1069 * This function will take the CPU core into P0
1072 * @param[in] *PStateBuffer
1073 * @param[in] *StdHeader
1077 *---------------------------------------------------------------------------------------
1082 IN VOID *PStateBuffer,
1083 IN AMD_CONFIG_PARAMS *StdHeader
1086 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1087 PSTATE_LEVELING *PStateBufferPtr;
1089 PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
1091 if ((PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1 ) ||
1092 (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_2)) {
1096 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1098 FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);