AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Feature / cpuPstateLeveling.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU Pstate Leveling Function.
6  *
7  * Contains code to level the Pstates in a multi-socket system
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
13  *
14  */
15 /*****************************************************************************
16  *
17  * Copyright (C) 2012 Advanced Micro Devices, Inc.
18  * All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are met:
22  *     * Redistributions of source code must retain the above copyright
23  *       notice, this list of conditions and the following disclaimer.
24  *     * Redistributions in binary form must reproduce the above copyright
25  *       notice, this list of conditions and the following disclaimer in the
26  *       documentation and/or other materials provided with the distribution.
27  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
28  *       its contributors may be used to endorse or promote products derived
29  *       from this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  *
42  ******************************************************************************
43  *----------------------------------------------------------------------------
44  */
45
46
47 /*
48  *----------------------------------------------------------------------------
49  *                                MODULES USED
50  *
51  *----------------------------------------------------------------------------
52  */
53 #include "AGESA.h"
54 #include "amdlib.h"
55 #include "OptionPstate.h"
56 #include "cpuLateInit.h"
57 #include "cpuRegisters.h"
58 #include "cpuPostInit.h"
59 #include "Ids.h"
60 #include "cpuFamilyTranslation.h"
61 #include "cpuPstateTables.h"
62 #include "cpuApicUtilities.h"
63 #include "cpuServices.h"
64 #include "GeneralServices.h"
65 #include "Filecode.h"
66 CODE_GROUP (G1_PEICC)
67 RDATA_GROUP (G2_PEI)
68
69 #define FILECODE PROC_CPU_FEATURE_CPUPSTATELEVELING_FILECODE
70
71 /*----------------------------------------------------------------------------
72  *                          DEFINITIONS AND MACROS
73  *
74  *----------------------------------------------------------------------------
75  */
76 extern OPTION_PSTATE_POST_CONFIGURATION    OptionPstatePostConfiguration;  // global user config record
77 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
78
79 /*----------------------------------------------------------------------------
80  *                           TYPEDEFS AND STRUCTURES
81  *
82  *----------------------------------------------------------------------------
83  */
84
85 /*----------------------------------------------------------------------------
86  *                        PROTOTYPES OF LOCAL FUNCTIONS
87  *
88  *----------------------------------------------------------------------------
89  */
90 AGESA_STATUS
91 PutAllCoreInPState0 (
92   IN OUT   PSTATE_LEVELING    *PStateBufferPtr,
93   IN       AMD_CONFIG_PARAMS  *StdHeader
94   );
95
96 AGESA_STATUS
97 StartPstateMsrModify (
98   IN       S_CPU_AMD_PSTATE    *CpuAmdPState,
99   IN       AMD_CONFIG_PARAMS   *StdHeader
100   );
101
102 VOID
103 STATIC
104 PutCoreInPState0 (
105   IN       VOID   *PStateBuffer,
106   IN       AMD_CONFIG_PARAMS *StdHeader
107   );
108
109 AGESA_STATUS
110 PStateLevelingStub (
111   IN OUT   S_CPU_AMD_PSTATE   *PStateStrucPtr,
112   IN       AMD_CONFIG_PARAMS  *StdHeader
113   );
114
115 AGESA_STATUS
116 PStateLevelingMain (
117   IN OUT   S_CPU_AMD_PSTATE   *PStateStrucPtr,
118   IN       AMD_CONFIG_PARAMS  *StdHeader
119   );
120
121 VOID
122 CorePstateRegModify (
123   IN       VOID               *CpuAmdPState,
124   IN       AMD_CONFIG_PARAMS  *StdHeader
125   );
126
127
128
129 /**
130  *---------------------------------------------------------------------------------------
131  *
132  *  PStateLeveling
133  *
134  *  Description:
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.
137  *
138  *  Parameters:
139  *    @param[in,out]    *PStateStrucPtr
140  *    @param[in]        *StdHeader
141  *
142  *    @retval          AGESA_STATUS
143  *
144  *---------------------------------------------------------------------------------------
145  **/
146 AGESA_STATUS
147 PStateLeveling (
148   IN OUT   S_CPU_AMD_PSTATE   *PStateStrucPtr,
149   IN       AMD_CONFIG_PARAMS  *StdHeader
150   )
151 {
152   AGESA_TESTPOINT (TpProcCpuEntryPstateLeveling, StdHeader);
153   return ((*(OptionPstatePostConfiguration.PstateLeveling)) (PStateStrucPtr, StdHeader));
154   // Note: Split config struct into PEI/DXE halves. This one is PEI.
155 }
156
157 /**--------------------------------------------------------------------------------------
158  *
159  *  PStateLevelingStub
160  *
161  *  Description:
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.
166  *
167  *  Parameters:
168  *    @param[in,out]    *PStateStrucPtr
169  *    @param[in]        *StdHeader
170  *
171  *    @retval         AGESA_STATUS
172  *
173  *---------------------------------------------------------------------------------------
174  **/
175 AGESA_STATUS
176 PStateLevelingStub (
177   IN OUT   S_CPU_AMD_PSTATE   *PStateStrucPtr,
178   IN       AMD_CONFIG_PARAMS  *StdHeader
179   )
180 {
181   return  AGESA_UNSUPPORTED;
182 }
183
184 /**--------------------------------------------------------------------------------------
185  *
186  *  PStateLevelingMain
187  *
188  *  Description:
189  *     This is the common routine for creating the ACPI information tables.
190  *
191  *  Parameters:
192  *    @param[in,out]    *PStateStrucPtr
193  *    @param[in]        *StdHeader
194  *
195  *    @retval         AGESA_STATUS
196  *
197  *---------------------------------------------------------------------------------------
198  **/
199 AGESA_STATUS
200 PStateLevelingMain (
201   IN OUT   S_CPU_AMD_PSTATE   *PStateStrucPtr,
202   IN       AMD_CONFIG_PARAMS  *StdHeader
203   )
204 {
205   UINT32                   i;
206   UINT32                   k;
207   UINT32                   m;
208   UINT32                   TotalIterations;
209   UINT32                   LogicalSocketCount;
210   UINT32                   TempVar_a;
211   UINT32                   TempVar_b;
212   UINT32                   TempVar_c;
213   UINT32                   TempVar_d;
214   UINT32                   TempVar_e;
215   UINT32                   TempVar_f;
216   PCI_ADDR                 PciAddress;
217
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];
224
225   BOOLEAN                  TempFlag1;
226   BOOLEAN                  TempFlag2;
227   BOOLEAN                  TempFlag3;
228   BOOLEAN                  TempFlag4;
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;
237   AGESA_STATUS             Status;
238
239   TempFlag1 = FALSE;
240   TempFlag2 = FALSE;
241   TempFlag3 = FALSE;
242   TempFlag4 = FALSE;
243   AllCoresHaveHtcCapEquToZeroFlag = FALSE;
244   AllCoreHaveMaxOnePStateFlag = FALSE;
245   PstateMaxValEquToPstateHtcLimitFlag = FALSE;
246   AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE;
247   PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE;
248   PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
249   Status = AGESA_SUCCESS;
250
251   if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) {
252     PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
253     PStateBufferPtr[0].InitStruct = 1;
254     return AGESA_UNSUPPORTED;
255   }
256
257   LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem;
258   ASSERT (LogicalSocketCount <= MAX_SOCKETS_SUPPORTED);
259
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);
267     }
268
269     // Check if core frequency and power are same across all sockets.
270     TempFlag1 = FALSE;
271     for (i = 1; i < LogicalSocketCount; i++) {
272       CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
273       if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) {
274         TempFlag1 = TRUE;
275         break;
276       }
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)) {
283           TempFlag1 = TRUE;
284           break; // Come out of the inner FOR loop
285         }
286       }
287       if (TempFlag1) {
288         break; // Come out of the outer FOR loop
289       }
290     }
291
292     if (!TempFlag1) {
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;
299     } else {
300       PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE;
301     }
302
303     // 1_b) & 1_c)
304     TempFlag1 = FALSE;
305     TempFlag2 = FALSE;
306     for (i = 0; i < LogicalSocketCount; i++) {
307       CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
308       if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == TempSwP0Array[i]) {
309         TempFlag1 = TRUE;
310       } else {
311         TempFlag2 = TRUE;
312       }
313       if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) {
314         TempFlag3 = TRUE;
315       } else {
316         TempFlag4 = TRUE;
317       }
318
319       if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
320            PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) {
321         PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
322       }
323
324       if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue ==
325           PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
326         PstateMaxValEquToPstateHtcLimitFlag = TRUE;
327       }
328
329       if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
330         AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
331       }
332     }
333
334     // Do general setup of flags, that we may use later
335     // Implementation of (1_b)
336     if (TempFlag1 && TempFlag2) {
337       //
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).
340       //
341       PStateBufferPtr[0].InitStruct = 1;
342       PStateBufferPtr[0].CreateAcpiTables = 0;
343       PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
344       return AGESA_UNSUPPORTED;
345     } else if (TempFlag1 && !TempFlag2) {
346       //
347       //all processors have only 1 enabled P-state
348       //
349       AllCoreHaveMaxOnePStateFlag = TRUE;
350       PStateBufferPtr[0].OnlyOneEnabledPState = TRUE;
351     }
352
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;
360     }
361
362     if (TempFlag3) {
363       //
364       //If code run to here means that all processors do not have HTC_CAPABLE.
365       //
366       AllCoresHaveHtcCapEquToZeroFlag = TRUE;
367     }
368
369     //--------------------------------------------------------------------------------
370     // S T E P - 2
371     //--------------------------------------------------------------------------------
372     // Now run the PState Leveling Algorithm which will create mixed CPU P-State
373     // Tables.
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;
389
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;
394       }
395
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;
400       }
401     }
402
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;
410     }
411
412     // 2_a)
413     if (!AllCoreHaveMaxOnePStateFlag) {
414       //--------------------------------------------------------------------------
415       // STEP - 3
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) {
434         // 3_a)
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);
446                 // Bits 30:28
447                 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
448                 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
449
450                 // Set F3x68[StcPstateLimit] = 001b
451                 PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG;
452                 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
453                 // Bits 28:30
454                 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
455                 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
456               }
457             }
458             // Set LocalBuffer
459             PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1;
460             if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) {
461               PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
462             }
463
464             if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) {
465               PstateMaxValEquToPstateHtcLimitFlag = TRUE;
466             }
467           }
468
469           if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
470             AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
471           }
472         }
473
474         // 3_b) and 3_d)
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;
486             }
487
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;
492             }
493           }
494         }
495
496         // 3_c) and 3_e)
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;
504         }
505       } // if(AllCoresHaveHtcCapEquToZeroFlag)
506
507
508       //--------------------------------------------------------------------------
509       // STEP - 4
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
519       //      value.
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
524       //      value.
525
526       // 4_a)
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;
533           }
534           //--------------------------------------------------------------------------
535           // STEP - 5
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])
540
541           // Use this value of HtcPstateLimit to program the
542           // F3xDC[pStateMaxValue]
543           TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
544           TempVar_e <<= 8;
545           // Bits 10:8
546
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);
554             }
555           }//End of step 5
556         }
557       }// End of 4_a)
558
559       // 4_b) and 4_d)
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;
565
566       for (i = 0; i < LogicalSocketCount; i++) {
567         CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
568         TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
569         if (TempVar_d >
570             PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
571           TempVar_d =
572           PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
573         }
574
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;
579         }
580       }
581
582       // 4_c) and 4_e)
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;
590       }
591
592
593       //--------------------------------------------------------------------------
594       // STEP - 6
595       //--------------------------------------------------------------------------
596       // Match the CPU COF and power for upper intermediate performance
597       // P-state(s):
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.
616
617       // 6_a)
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
624               // structure values
625               PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
626             }
627           }
628         }
629       }
630       // 6_b)
631       else {
632         // Identify Lowest Frequency and Highest Power
633         TotalIterations = 0;
634         TempFlag1 = TRUE;
635
636         for (i = 0; i < LogicalSocketCount; i++) {
637           CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
638           TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1;
639         }
640
641         do {
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]) {
647                 TempFlag1 = FALSE;
648                 break;
649               }
650             }
651           } else {
652             TempFlag1 = FALSE;
653           }
654           if (TempFlag1) {
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;
659
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]) {
667                     TempFlag1 = FALSE;
668                     break;
669                   }
670                 }//end while
671               } else {
672                 TempFlag1 = FALSE;
673               }
674
675             } //end for LogicalSocketCount
676           }
677
678           if (TempFlag1) {
679             for (i = 0; i < LogicalSocketCount; i++) {
680               //
681               //Compare
682               //
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;
686               }
687
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;
692               }
693             }
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;
702             }
703           } else {
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;
708               }
709             }
710           }
711
712           TotalIterations++;
713         } while (TempFlag1);
714
715       } // else
716
717       //--------------------------------------------------------------------------
718       // STEP - 7
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
727       //      numbered step.
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.
742
743
744       // 7_a)
745       if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) {
746         for (i = 0; i < LogicalSocketCount; i++) {
747           CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
748
749           for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
750               k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
751               k--) {
752             if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
753                  PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) {
754               PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
755             }
756           }
757         }
758       }
759
760       // 7_b)
761       else {
762         // Identify Lowest Frequency and Highest Power
763
764         TotalIterations = 0;
765         TempFlag1 = TRUE;
766
767         for (i = 0; i < LogicalSocketCount; i++) {
768           CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
769           TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
770         }
771
772         do {
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) {
778                 TempFlag1 = FALSE;
779                 break;
780               }
781             }
782           } else {
783             TempFlag1 = FALSE;
784           }
785           if (TempFlag1) {
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;
790
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) {
798                     TempFlag1 = FALSE;
799                     break;
800                   }
801                 }//end while
802               } else {
803                 TempFlag1 = FALSE;
804               }
805             } //end for LogicalSocketCount
806           }
807
808           if (TempFlag1) {
809             for (i = 0; i < LogicalSocketCount; i++) {
810               //
811               //Compare
812               //
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;
816               }
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;
821               }
822             }
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;
831             }
832           } else {
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;
837               }
838             }
839           }
840           TotalIterations++;
841         } while (TempFlag1);
842       } // else
843     } // if(!AllCoreHaveMaxOnePStateFlag)
844
845     PStateBufferPtr[0].InitStruct = 1;
846   } // CurrentCore
847
848
849   // Update the pState MSRs
850   // This can be done only by individual core
851   StartPstateMsrModify (PStateStrucPtr, StdHeader);
852
853   //----------------------------------------------------------------------------------
854   // STEP - 8
855   //----------------------------------------------------------------------------------
856   // Place all cores into a valid COF and VID configuration corresponding to an
857   // enabled P-state:
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].
865   //
866   PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
867
868   return AGESA_SUCCESS;
869 }
870
871
872 /*----------------------------------------------------------------------------
873  *                              LOCAL FUNCTIONS
874  *
875  *----------------------------------------------------------------------------
876  */
877
878 /**
879  *---------------------------------------------------------------------------------------
880  *
881  *  PutAllCoreInPState0
882  *
883  *  Description:
884  *    This function will put core pstate to p0.
885  *
886  *  Parameters:
887  *    @param[in,out]    *PStateBufferPtr
888  *    @param[in]        *StdHeader
889  *
890  *    @retval          AGESA_STATUS
891  *
892  *---------------------------------------------------------------------------------------
893  **/
894 AGESA_STATUS
895 PutAllCoreInPState0 (
896   IN OUT   PSTATE_LEVELING    *PStateBufferPtr,
897   IN       AMD_CONFIG_PARAMS  *StdHeader
898   )
899 {
900   AP_TASK                 TaskPtr;
901   UINT32                  BscSocket;
902   UINT32                  Ignored;
903   UINT32                  BscCoreNum;
904   UINT32                  Core;
905   UINT32                  Socket;
906   UINT32                  NumberOfSockets;
907   UINT32                  NumberOfCores;
908   AGESA_STATUS            IgnoredSts;
909
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;
915
916   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
917   NumberOfSockets = GetPlatformNumberOfSockets ();
918
919   PutCoreInPState0 (PStateBufferPtr, StdHeader);
920
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);
926         }
927       }
928     }
929   }
930
931   return AGESA_SUCCESS;
932 }
933
934 /**
935  *---------------------------------------------------------------------------------------
936  *
937  *  CorePstateRegModify
938  *
939  *  Description:
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.
942  *
943  *  Parameters:
944  *    @param[in,out]    *CpuAmdPState
945  *    @param[in]        *StdHeader
946  *
947  *    @retval          VOID
948  *
949  *---------------------------------------------------------------------------------------
950  **/
951 VOID
952 CorePstateRegModify (
953   IN       VOID               *CpuAmdPState,
954   IN       AMD_CONFIG_PARAMS  *StdHeader
955   )
956 {
957   PSTATE_CPU_FAMILY_SERVICES   *FamilySpecificServices;
958   FamilySpecificServices = NULL;
959
960   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilySpecificServices, StdHeader);
961   ASSERT (FamilySpecificServices != NULL)
962   FamilySpecificServices->SetPStateLevelReg  (FamilySpecificServices, (S_CPU_AMD_PSTATE *) CpuAmdPState, StdHeader);
963 }
964
965
966 /*---------------------------------------------------------------------------------------*/
967 /**
968  * This function will set msr on all cores of all nodes.
969  *
970  * @param[in]     CpuAmdPState  Pointer to S_CPU_AMD_PSTATE.
971  * @param[in]     StdHeader     Header for library and services.
972  *
973  * @retval        AGESA_SUCCESS  Always succeeds
974  *
975  */
976 AGESA_STATUS
977 StartPstateMsrModify (
978   IN       S_CPU_AMD_PSTATE    *CpuAmdPState,
979   IN       AMD_CONFIG_PARAMS   *StdHeader
980   )
981 {
982   AP_TASK                 TaskPtr;
983   UINT32                  BscSocket;
984   UINT32                  Ignored;
985   UINT32                  BscCoreNum;
986   UINT32                  Core;
987   UINT32                  Socket;
988   UINT32                  NumberOfSockets;
989   UINT32                  NumberOfCores;
990   AGESA_STATUS            IgnoredSts;
991
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;
997
998   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
999   NumberOfSockets = GetPlatformNumberOfSockets ();
1000
1001   CorePstateRegModify (CpuAmdPState, StdHeader);
1002
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);
1008         }
1009       }
1010     }
1011   }
1012
1013   return AGESA_SUCCESS;
1014 }
1015
1016
1017 /**
1018  *---------------------------------------------------------------------------------------
1019  *
1020  *  CpuGetPStateLevelStructure
1021  *
1022  *  Description:
1023  *    Based on the LogicalSocketNumber, this function will return a pointer
1024  *      point to the accurate offset of the PSTATE_LEVELING structure.
1025  *
1026  *  Parameters:
1027  *    @param[in,out]          *PStateBufferPtr
1028  *    @param[in]              *CpuAmdPState
1029  *    @param[in]              LogicalSocketNumber
1030  *    @param[in]              *StdHeader
1031  *
1032  *    @retval         VOID
1033  *
1034  *---------------------------------------------------------------------------------------
1035  **/
1036 AGESA_STATUS
1037 CpuGetPStateLevelStructure (
1038      OUT   PSTATE_LEVELING     **PStateBufferPtr,
1039   IN       S_CPU_AMD_PSTATE    *CpuAmdPState,
1040   IN       UINT32              LogicalSocketNumber,
1041   IN       AMD_CONFIG_PARAMS   *StdHeader
1042   )
1043 {
1044   PSTATE_LEVELING         *PStateBufferPtrTmp;
1045   UINT32                  i;
1046
1047   if (LogicalSocketNumber > CpuAmdPState->TotalSocketInSystem) {
1048     return AGESA_UNSUPPORTED;
1049   }
1050
1051   PStateBufferPtrTmp = CpuAmdPState->PStateLevelingStruc;
1052
1053   for (i = 1; i <= LogicalSocketNumber; i++) {
1054     PStateBufferPtrTmp = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtrTmp + ((UINTN) PStateBufferPtrTmp->PStateLevelingSizeOfBytes));
1055   }
1056
1057   *PStateBufferPtr = PStateBufferPtrTmp;
1058
1059   return AGESA_SUCCESS;
1060 }
1061
1062
1063 /**
1064  *---------------------------------------------------------------------------------------
1065  *
1066  *  PutCoreInPState0
1067  *
1068  *  Description:
1069  *    This function will take the CPU core into P0
1070  *
1071  *  Parameters:
1072  *    @param[in]         *PStateBuffer
1073  *    @param[in]         *StdHeader
1074  *
1075  *    @retval         VOID
1076  *
1077  *---------------------------------------------------------------------------------------
1078  **/
1079 VOID
1080 STATIC
1081 PutCoreInPState0 (
1082   IN       VOID   *PStateBuffer,
1083   IN       AMD_CONFIG_PARAMS *StdHeader
1084   )
1085 {
1086   CPU_SPECIFIC_SERVICES   *FamilySpecificServices;
1087   PSTATE_LEVELING         *PStateBufferPtr;
1088
1089   PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
1090
1091   if ((PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1 ) ||
1092      (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_2)) {
1093     return;
1094   }
1095
1096   GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1097
1098   FamilySpecificServices->TransitionPstate  (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);
1099 }