blob: a7269afba4c4735cec43181b9fda1d57e087cda6 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $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: 35664 $ @e \$Date: 2010-07-28 20:02:15 +0800 (Wed, 28 Jul 2010) $
13 *
14 */
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47
48/*
49 *----------------------------------------------------------------------------
50 * MODULES USED
51 *
52 *----------------------------------------------------------------------------
53 */
54#include "AGESA.h"
55#include "amdlib.h"
56#include "OptionPstate.h"
57#include "cpuLateInit.h"
58#include "cpuRegisters.h"
59#include "cpuPostInit.h"
60#include "Ids.h"
61#include "cpuFamilyTranslation.h"
62#include "cpuPstateTables.h"
63#include "cpuApicUtilities.h"
64#include "cpuServices.h"
65#include "GeneralServices.h"
66#include "Filecode.h"
67CODE_GROUP (G1_PEICC)
68RDATA_GROUP (G1_PEICC)
69
70#define FILECODE PROC_CPU_FEATURE_CPUPSTATELEVELING_FILECODE
71
72/*----------------------------------------------------------------------------
73 * DEFINITIONS AND MACROS
74 *
75 *----------------------------------------------------------------------------
76 */
77extern OPTION_PSTATE_POST_CONFIGURATION OptionPstatePostConfiguration; // global user config record
78extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
79
80/*----------------------------------------------------------------------------
81 * TYPEDEFS AND STRUCTURES
82 *
83 *----------------------------------------------------------------------------
84 */
85
86/*----------------------------------------------------------------------------
87 * PROTOTYPES OF LOCAL FUNCTIONS
88 *
89 *----------------------------------------------------------------------------
90 */
91AGESA_STATUS
92PutAllCoreInPState0 (
93 IN OUT PSTATE_LEVELING *PStateBufferPtr,
94 IN AMD_CONFIG_PARAMS *StdHeader
95 );
96
97AGESA_STATUS
98StartPstateMsrModify (
99 IN S_CPU_AMD_PSTATE *CpuAmdPState,
100 IN AMD_CONFIG_PARAMS *StdHeader
101 );
102
103VOID
104STATIC
105PutCoreInPState0 (
106 IN VOID *PStateBuffer,
107 IN AMD_CONFIG_PARAMS *StdHeader
108 );
109
efdesign9884cbce22011-08-04 12:09:17 -0600110AGESA_STATUS
111PStateLevelingStub (
112 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
113 IN AMD_CONFIG_PARAMS *StdHeader
114 );
115
116AGESA_STATUS
117PStateLevelingMain (
118 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
119 IN AMD_CONFIG_PARAMS *StdHeader
120 );
121
122VOID
123CorePstateRegModify (
124 IN VOID *CpuAmdPState,
125 IN AMD_CONFIG_PARAMS *StdHeader
126 );
127
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000128
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 **/
146AGESA_STATUS
147PStateLeveling (
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 **/
175AGESA_STATUS
176PStateLevelingStub (
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 **/
199AGESA_STATUS
200PStateLevelingMain (
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
224 BOOLEAN TempFlag1;
225 BOOLEAN TempFlag2;
226 BOOLEAN TempFlag3;
227 BOOLEAN TempFlag4;
228 BOOLEAN AllCoresHaveHtcCapEquToZeroFlag;
229 BOOLEAN AllCoreHaveMaxOnePStateFlag;
230 BOOLEAN PstateMaxValEquToPstateHtcLimitFlag;
231 BOOLEAN AtLeastOneCoreHasPstateHtcLimitEquToOneFlag;
232 BOOLEAN PstateMaxValMinusHtcPstateLimitLessThan2Flag;
233 PSTATE_LEVELING *PStateBufferPtr;
234 PSTATE_LEVELING *PStateBufferPtrTmp;
235 UINT32 MaxPstateInNode;
236 AGESA_STATUS Status;
237
238 TempFlag1 = FALSE;
239 TempFlag2 = FALSE;
240 TempFlag3 = FALSE;
241 TempFlag4 = FALSE;
242 AllCoresHaveHtcCapEquToZeroFlag = FALSE;
243 AllCoreHaveMaxOnePStateFlag = FALSE;
244 PstateMaxValEquToPstateHtcLimitFlag = FALSE;
245 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE;
246 PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE;
247 PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
248 Status = AGESA_SUCCESS;
249
250 if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) {
251 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
252 PStateBufferPtr[0].InitStruct = 1;
253 return AGESA_UNSUPPORTED;
254 }
255
256 LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem;
257
258 // This section of code will execute only for "core 0" i.e. BSP
259 // Read P-States of all the cores.
260 if (PStateBufferPtr[0].InitStruct == 0) {
261 // Check if core frequency and power are same across all sockets.
262 TempFlag1 = FALSE;
263 for (i = 1; i < LogicalSocketCount; i++) {
264 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
265 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) {
266 TempFlag1 = TRUE;
267 break;
268 }
269 MaxPstateInNode = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
270 for (k = 0; k <= MaxPstateInNode; k++) {
271 if ((PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[k].CoreFreq !=
272 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq) ||
273 (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[k].Power !=
274 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].Power)) {
275 TempFlag1 = TRUE;
276 break; // Come out of the inner FOR loop
277 }
278 }
279 if (TempFlag1) {
280 break; // Come out of the outer FOR loop
281 }
282 }
283
284 if (!TempFlag1) {
285 // No need to do pStateLeveling, or writing to pState MSR registers
286 // if all CPUs have Identical PStates
287 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
288 PStateBufferPtr[0].InitStruct = 1;
289 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
290 return AGESA_UNSUPPORTED;
291 } else {
292 PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE;
293 }
294
295 // 1_b) & 1_c)
296 TempFlag1 = FALSE;
297 TempFlag2 = FALSE;
298 for (i = 0; i < LogicalSocketCount; i++) {
299 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
300 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 0) {
301 TempFlag1 = TRUE;
302 } else {
303 TempFlag2 = TRUE;
304 }
305 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) {
306 TempFlag3 = TRUE;
307 } else {
308 TempFlag4 = TRUE;
309 }
310
311 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
312 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) {
313 PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
314 }
315
316 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue ==
317 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
318 PstateMaxValEquToPstateHtcLimitFlag = TRUE;
319 }
320
321 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
322 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
323 }
324 }
325
326 // Do general setup of flags, that we may use later
327 // Implementation of (1_b)
328 if (TempFlag1 && TempFlag2) {
329 //
330 //Processors with only one enabled P-state (F3xDC[PstateMaxVal]=000b) cannot be mixed in a system with
331 //processors with more than one enabled P-state (F3xDC[PstateMaxVal]!=000b).
332 //
333 PStateBufferPtr[0].InitStruct = 1;
334 PStateBufferPtr[0].CreateAcpiTables = 0;
335 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
336 return AGESA_UNSUPPORTED;
337 } else if (TempFlag1 && !TempFlag2) {
338 //
339 //all processors have only 1 enabled P-state
340 //
341 AllCoreHaveMaxOnePStateFlag = TRUE;
342 PStateBufferPtr[0].OnlyOneEnabledPState = TRUE;
343 }
344
345 // Processors with F3xE8[HTC_CAPABLE] = 1 can not be
346 // mixed in system with processors with F3xE8[HTC_CAPABLE] = 0.
347 if (TempFlag3 && TempFlag4) {
348 PStateBufferPtr[0].InitStruct = 1;
349 PStateBufferPtr[0].CreateAcpiTables = 0;
350 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
351 return AGESA_UNSUPPORTED;
352 }
353
354 if (TempFlag3) {
355 //
356 //If code run to here means that all processors do not have HTC_CAPABLE.
357 //
358 AllCoresHaveHtcCapEquToZeroFlag = TRUE;
359 }
360
361 //--------------------------------------------------------------------------------
362 // S T E P - 2
363 //--------------------------------------------------------------------------------
364 // Now run the PState Leveling Algorithm which will create mixed CPU P-State
365 // Tables.
366 // Follow the algorithm in the latest BKDG
367 // -------------------------------------------------------------------------------
368 // Match P0 CPU COF for all CPU cores to the lowest P0 CPU COF value in the
369 // coherent fabric, and match P0 power for all CPU cores to the highest P0 power
370 // value in the coherent fabric.
371 // 2_a) If all processors have only 1 enabled P-State BIOS must write the
372 // appropriate CpuFid value resulting from the matched CPU COF to all
373 // copies of MSRC001_0070[CpuFid], and exit the sequence (No further
374 // steps are executed)
375 //--------------------------------------------------------------------------------
376 // Identify the lowest P0 Frequency and maximum P0 Power
377 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[0].CoreFreq;
378 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[0].Power;
379 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[0].IddValue;
380 TempVar_b = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[0].IddDiv;
381
382 for (i = 0; i < LogicalSocketCount; i++) {
383 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
384 if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].CoreFreq) {
385 TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].CoreFreq;
386 }
387
388 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].Power) {
389 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].Power;
390 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddValue;
391 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddDiv;
392 }
393 }
394
395 // Set P0 Frequency and Power for all CPUs
396 for (i = 0; i < LogicalSocketCount; i++) {
397 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
398 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].CoreFreq = TempVar_d;
399 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].Power = TempVar_e;
400 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddValue = TempVar_a;
401 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddDiv = TempVar_b;
402 }
403
404 // 2_a)
405 if (!AllCoreHaveMaxOnePStateFlag) {
406 //--------------------------------------------------------------------------
407 // STEP - 3
408 //--------------------------------------------------------------------------
409 // Match the CPU COF and power for P-states used by HTC. Skip to step 4
410 // is any processor reports F3xE8[HTC_Capable] = 0;
411 // 3_a) Set F3x64[HtcPstateLimit] = 001b and F3x68[StcPstateLimit] = 001b for
412 // processors with F3x64[HtcPstateLimit] = 000b.
413 // 3_b) Identify the lowest CPU COF for all processors in the P-state
414 // pointed to by [The Hardware Thermal Control (HTC) Register]
415 // F3x64[HtcPstateLimit]
416 // 3_c) Modify the CPU COF pointed to by [The Hardware Thermal Control
417 // (HTC) Register] F3x64[HtcPstateLimit] for all processors to the
418 // previously identified lowest CPU COF value.
419 // 3_d) Identify the highest power for all processors in the P-state
420 // pointed to by [The Hardware Thermal Control (HTC) Register]
421 // F3x64[HtcPstateLimit].
422 // 3_e) Modify the power pointed to by [The Hardware Thermal Control (HTC)
423 // Register] F3x64[HtcPstateLimit] to the previously identified
424 // highest power value.
425 if (!AllCoresHaveHtcCapEquToZeroFlag) {
426 // 3_a)
427 for (i = 0; i < LogicalSocketCount; i++) {
428 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
429 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 0) {
430 // To Be Done (Set Htc and Stc PstateLimit values)
431 // for this CPU (using PCI address space)
432 for (k = 0; k < (UINT8)GetPlatformNumberOfModules (); k++) {
433 if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, k, &PciAddress, &Status)) {
434 // Set F3x64[HtcPstateLimit] = 001b
435 PciAddress.Address.Function = FUNC_3;
436 PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
437 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
438 // Bits 30:28
439 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
440 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
441
442 // Set F3x68[StcPstateLimit] = 001b
443 PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG;
444 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
445 // Bits 28:30
446 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
447 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
448 }
449 }
450 // Set LocalBuffer
451 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1;
452 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) {
453 PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
454 }
455
456 if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) {
457 PstateMaxValEquToPstateHtcLimitFlag = TRUE;
458 }
459 }
460
461 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
462 AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
463 }
464 }
465
466 // 3_b) and 3_d)
467 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit;
468 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
469 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
470 TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
471 TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
472 for (i = 0; i < LogicalSocketCount; i++) {
473 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
474 for (k = 0; k < 1; k++) {
475 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
476 if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
477 TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
478 }
479
480 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
481 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
482 TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
483 TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
484 }
485 }
486 }
487
488 // 3_c) and 3_e)
489 for (i = 0; i < LogicalSocketCount; i++) {
490 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
491 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
492 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
493 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
494 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
495 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
496 }
497 } // if(AllCoresHaveHtcCapEquToZeroFlag)
498
499
500 //--------------------------------------------------------------------------
501 // STEP - 4
502 //--------------------------------------------------------------------------
503 // Match the CPU COF and power for the lowest performance P-state:
504 // 4_a) If F3xDC[PstateMaxVal] = F3x64[HtcPstateLimit] for any processor,
505 // set PstateEn = 0 for all the P-states greater than
506 // F3x64[HtcPstateLimit] for all processors.
507 // 4_b) Identify the lowest CPU COF for all processors in the P-state
508 // pointed to by F3xDC[PstateMaxVal].
509 // 4_c) Modify the CPU COF for all processors in the P-state pointed to by
510 // F3xDC[PstateMaxVal] to the previously identified lowest CPU COF
511 // value.
512 // 4_d) Identify the highest power for all processors in the P-state
513 // pointed to by F3xDC[PstateMaxVal].
514 // 4_e) Modify the power for all processors in the P-state pointed to by
515 // F3xDC[PstateMaxVal] to the previously identified highest power
516 // value.
517
518 // 4_a)
519 if (PstateMaxValEquToPstateHtcLimitFlag) {
520 for (i = 0; i < LogicalSocketCount; i++) {
521 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
522 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit + 1;
523 for (k = TempVar_b; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++) {
524 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
525 }
526 //--------------------------------------------------------------------------
527 // STEP - 5
528 //--------------------------------------------------------------------------
529 // 5_a) Modify F3xDC[PstateMaxVal] to indicate the lowest performance
530 // P-state with PstateEn set for each processor (Step 4 can disable
531 // P-states pointed to by F3xDC[PstateMaxVal])
532
533 // Use this value of HtcPstateLimit to program the
534 // F3xDC[pStateMaxValue]
535 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
536 TempVar_e <<= 8;
537 // Bits 10:8
538
539 for (m = 0; m < (UINT8)GetPlatformNumberOfModules (); m++) {
540 if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, m, &PciAddress, &Status)) {
541 PciAddress.Address.Function = FUNC_3;
542 PciAddress.Address.Register = CLOCK_POWER_TIMING_CTRL2_REG;
543 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
544 TempVar_d = (TempVar_d & 0xFFFFF8FF) | TempVar_e;
545 LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
546 }
547 }//End of step 5
548 }
549 }// End of 4_a)
550
551 // 4_b) and 4_d)
552 TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue;
553 TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
554 TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
555 TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
556 TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
557
558 for (i = 0; i < LogicalSocketCount; i++) {
559 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
560 TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
561 if (TempVar_d >
562 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
563 TempVar_d =
564 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
565 }
566
567 if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
568 TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
569 TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
570 TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
571 }
572 }
573
574 // 4_c) and 4_e)
575 for (i = 0; i < LogicalSocketCount; i++) {
576 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
577 TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
578 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
579 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
580 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
581 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
582 }
583
584
585 //--------------------------------------------------------------------------
586 // STEP - 6
587 //--------------------------------------------------------------------------
588 // Match the CPU COF and power for upper intermediate performance
589 // P-state(s):
590 // Upper intermediate PStates = PStates between (Not including) P0 and
591 // F3x64[HtcPstateLimit]
592 // 6_a) If F3x64[HtcPstateLimit] = 001b for any processor, set PstateEn = 0
593 // for enabled upper intermediate P-states for all processors with
594 // F3x64[HtcPstateLimit] > 001b and skip the remaining actions for
595 // this numbered step.
596 // 6_b) Define each of the available upper intermediate P-states; for each
597 // processor concurrently evaluate the following loop; when any
598 // processor falls out of the loop (runs out of available upper
599 // intermediate Pstates) all other processors have their remaining
600 // upper intermediate P-states invalidated (PstateEn = 0);
601 // for (i = F3x64[HtcPstateLimit] - 1; i > 0; i--)
602 // - Identify the lowest CPU COF for P(i).
603 // - Identify the highest power for P(i).
604 // - Modify P(i) CPU COF for all processors to the previously
605 // identified lowest CPU COF value.
606 // - Modify P(i) power for all processors to the previously
607 // identified highest power value.
608
609 // 6_a)
610 if (AtLeastOneCoreHasPstateHtcLimitEquToOneFlag) {
611 for (i = 0; i < LogicalSocketCount; i++) {
612 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
613 for (k = 1; k < (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit); k++) {
614 if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit > 1) {
615 // Make a function call to clear the
616 // structure values
617 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
618 }
619 }
620 }
621 }
622 // 6_b)
623 else {
624 // Identify Lowest Frequency and Highest Power
625 TotalIterations = 0;
626 TempFlag1 = TRUE;
627
628 for (i = 0; i < LogicalSocketCount; i++) {
629 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
630 TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1;
631 }
632
633 do {
634 //For first socket, try to find a candidate
635 if (TempSocketPiArray[0] != 0) {
636 while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
637 TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
638 if (TempSocketPiArray[0] == 0) {
639 TempFlag1 = FALSE;
640 break;
641 }
642 }
643 } else {
644 TempFlag1 = FALSE;
645 }
646 if (TempFlag1) {
647 TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
648 TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
649 TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
650 TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
651
652 //Try to find next candidate
653 for (i = 1; i < LogicalSocketCount; i++) {
654 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
655 if (TempSocketPiArray[i] != 0) {
656 while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
657 TempSocketPiArray[i]--;
658 if (TempSocketPiArray[i] == 0) {
659 TempFlag1 = FALSE;
660 break;
661 }
662 }//end while
663 } else {
664 TempFlag1 = FALSE;
665 }
666
667 } //end for LogicalSocketCount
668 }
669
670 if (TempFlag1) {
671 for (i = 0; i < LogicalSocketCount; i++) {
672 //
673 //Compare
674 //
675 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
676 if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
677 TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
678 }
679
680 if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
681 TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
682 TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
683 TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
684 }
685 }
686 // Modify (Pi) CPU COF and Power for all the CPUs
687 for (i = 0; i < LogicalSocketCount; i++) {
688 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
689 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
690 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
691 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
692 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
693 TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
694 }
695 } else {
696 for (i = 0; i < LogicalSocketCount; i++) {
697 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
698 for (m = TempSocketPiArray[i]; m > 0; m--) {
699 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
700 }
701 }
702 }
703
704 TotalIterations++;
705 } while (TempFlag1);
706
707 } // else
708
709 //--------------------------------------------------------------------------
710 // STEP - 7
711 //--------------------------------------------------------------------------
712 // Match the CPU COF and power for lower intermediate performance P - state(s)
713 // Lower Intermediate Pstates = Pstates between (not including)
714 // F3x64[HtcPstateLimit] and F3xDC[PstateMaxVal]
715 // 7_a) If F3xDC[PstateMaxVal] - F3x64[HtcPstateLimit] < 2 for any
716 // processor, set PstateEn = 0 for enabled lower intermediate P - states
717 // for all processors with (F3xDC[PstateMaxVal] -
718 // F3x64[HtcPstateLimit] > 1) and skip the remaining actions for this
719 // numbered step.
720 // 7_b) Define each of the available lower intermediate P-states; for each
721 // processor concurrently evaluate the following loop; when any
722 // processor falls out of the loop (runs out of available lower
723 // intermediate Pstates) all other processors have their remaining
724 // lower intermediate P-states invalidated (PstateEn = 0);
725 // for (i = F3xDC[PstateMaxVal]-1; i > F3x64[HtcPstateLimit]; i--)
726 // - Identify the lowest CPU COF for P-states between
727 // (not including) F3x64[HtcPstateLimit] and P(i).
728 // - Identify the highest power for P-states between
729 // (not including) F3x64[HtcPstateLimit] and P(i).
730 // - Modify P(i) CPU COF for all processors to the previously
731 // identified lowest CPU COF value.
732 // - Modify P(i) power for all processors to the previously
733 // identified highest power value.
734
735
736 // 7_a)
737 if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) {
738 for (i = 0; i < LogicalSocketCount; i++) {
739 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
740
741 for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
742 k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
743 k--) {
744 if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
745 PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) {
746 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
747 }
748 }
749 }
750 }
751
752 // 7_b)
753 else {
754 // Identify Lowest Frequency and Highest Power
755
756 TotalIterations = 0;
757 TempFlag1 = TRUE;
758
759 for (i = 0; i < LogicalSocketCount; i++) {
760 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
761 TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
762 }
763
764 do {
765 //For first socket, try to find a candidate
766 if (TempSocketPiArray[0] != PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
767 while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
768 TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
769 if (TempSocketPiArray[0] == PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
770 TempFlag1 = FALSE;
771 break;
772 }
773 }
774 } else {
775 TempFlag1 = FALSE;
776 }
777 if (TempFlag1) {
778 TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
779 TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
780 TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
781 TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
782
783 //Try to find next candidate
784 for (i = 1; i < LogicalSocketCount; i++) {
785 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
786 if (TempSocketPiArray[i] != PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
787 while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
788 TempSocketPiArray[i]--;
789 if (TempSocketPiArray[i] == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
790 TempFlag1 = FALSE;
791 break;
792 }
793 }//end while
794 } else {
795 TempFlag1 = FALSE;
796 }
797 } //end for LogicalSocketCount
798 }
799
800 if (TempFlag1) {
801 for (i = 0; i < LogicalSocketCount; i++) {
802 //
803 //Compare
804 //
805 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
806 if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
807 TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
808 }
809 if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
810 TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
811 TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
812 TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
813 }
814 }
815 // Modify (Pi) CPU COF and Power for all the CPUs
816 for (i = 0; i < LogicalSocketCount; i++) {
817 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
818 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
819 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
820 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
821 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
822 TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
823 }
824 } else {
825 for (i = 0; i < LogicalSocketCount; i++) {
826 CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
827 for (m = TempSocketPiArray[i]; m > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; m--) {
828 PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
829 }
830 }
831 }
832 TotalIterations++;
833 } while (TempFlag1);
834 } // else
835 } // if(!AllCoreHaveMaxOnePStateFlag)
836
837 PStateBufferPtr[0].InitStruct = 1;
838 } // CurrentCore
839
840
841 // Update the pState MSRs
842 // This can be done only by individual core
843 StartPstateMsrModify (PStateStrucPtr, StdHeader);
844
845 //----------------------------------------------------------------------------------
846 // STEP - 8
847 //----------------------------------------------------------------------------------
848 // Place all cores into a valid COF and VID configuration corresponding to an
849 // enabled P-state:
850 // 8_a) Select an enabled P-state != to the P-state pointed to by
851 // MSRC001_0063[CurPstate] for each core.
852 // 8_b) Transition all cores to the selected P-states by writing the Control value
853 // from the_PSS object corresponding to the selected P-state to
854 // MSRC001_0062[PstateCmd].
855 // 8_c) Wait for all cores to report the Status value from the _PSS object
856 // corresponding to the selected P-state in MSRC001_0063[CurPstate].
857 //
858 PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
859
860 return AGESA_SUCCESS;
861}
862
863
864/*----------------------------------------------------------------------------
865 * LOCAL FUNCTIONS
866 *
867 *----------------------------------------------------------------------------
868 */
869
870/**
871 *---------------------------------------------------------------------------------------
872 *
873 * PutAllCoreInPState0
874 *
875 * Description:
876 * This function will put core pstate to p0.
877 *
878 * Parameters:
879 * @param[in,out] *PStateBufferPtr
880 * @param[in] *StdHeader
881 *
882 * @retval AGESA_STATUS
883 *
884 *---------------------------------------------------------------------------------------
885 **/
886AGESA_STATUS
887PutAllCoreInPState0 (
888 IN OUT PSTATE_LEVELING *PStateBufferPtr,
889 IN AMD_CONFIG_PARAMS *StdHeader
890 )
891{
892 AP_TASK TaskPtr;
893 UINT32 BscSocket;
894 UINT32 Ignored;
efdesign9884cbce22011-08-04 12:09:17 -0600895 UINT32 BscCoreNum;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000896 UINT32 Core;
897 UINT32 Socket;
898 UINT32 NumberOfSockets;
899 UINT32 NumberOfCores;
900 AGESA_STATUS IgnoredSts;
901
902 TaskPtr.FuncAddress.PfApTaskI = PutCoreInPState0;
903 TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PSTATE_LEVELING);
904 TaskPtr.ExeFlags = WAIT_FOR_CORE;
905 TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
906 TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
907
efdesign9884cbce22011-08-04 12:09:17 -0600908 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000909 NumberOfSockets = GetPlatformNumberOfSockets ();
910
911 PutCoreInPState0 (PStateBufferPtr, StdHeader);
912
913 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
914 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
915 for (Core = 0; Core < NumberOfCores; Core++) {
efdesign9884cbce22011-08-04 12:09:17 -0600916 if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000917 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
918 }
919 }
920 }
921 }
922
923 return AGESA_SUCCESS;
924}
925
926/**
927 *---------------------------------------------------------------------------------------
928 *
929 * CorePstateRegModify
930 *
931 * Description:
932 * This function will setting the Pstate MSR to each APs base on Pstate Buffer.
933 * Note: This function should be called for every core in the system.
934 *
935 * Parameters:
936 * @param[in,out] *CpuAmdPState
937 * @param[in] *StdHeader
938 *
939 * @retval VOID
940 *
941 *---------------------------------------------------------------------------------------
942 **/
943VOID
944CorePstateRegModify (
945 IN VOID *CpuAmdPState,
946 IN AMD_CONFIG_PARAMS *StdHeader
947 )
948{
949 PSTATE_CPU_FAMILY_SERVICES *FamilySpecificServices;
950 FamilySpecificServices = NULL;
951
efdesign9884cbce22011-08-04 12:09:17 -0600952 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (const VOID **)&FamilySpecificServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000953 ASSERT (FamilySpecificServices != NULL)
954 FamilySpecificServices->SetPStateLevelReg (FamilySpecificServices, (S_CPU_AMD_PSTATE *) CpuAmdPState, StdHeader);
955}
956
957
958/*---------------------------------------------------------------------------------------*/
959/**
960 * This function will set msr on all cores of all nodes.
961 *
962 * @param[in] CpuAmdPState Pointer to S_CPU_AMD_PSTATE.
963 * @param[in] StdHeader Header for library and services.
964 *
965 * @retval AGESA_SUCCESS Always succeeds
966 *
967 */
968AGESA_STATUS
969StartPstateMsrModify (
970 IN S_CPU_AMD_PSTATE *CpuAmdPState,
971 IN AMD_CONFIG_PARAMS *StdHeader
972 )
973{
974 AP_TASK TaskPtr;
975 UINT32 BscSocket;
976 UINT32 Ignored;
efdesign9884cbce22011-08-04 12:09:17 -0600977 UINT32 BscCoreNum;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000978 UINT32 Core;
979 UINT32 Socket;
980 UINT32 NumberOfSockets;
981 UINT32 NumberOfCores;
982 AGESA_STATUS IgnoredSts;
983
984 TaskPtr.FuncAddress.PfApTaskI = CorePstateRegModify;
985 TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) (CpuAmdPState->SizeOfBytes / 4 + 1);
986 TaskPtr.ExeFlags = WAIT_FOR_CORE;
987 TaskPtr.DataTransfer.DataPtr = CpuAmdPState;
988 TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
989
efdesign9884cbce22011-08-04 12:09:17 -0600990 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000991 NumberOfSockets = GetPlatformNumberOfSockets ();
992
993 CorePstateRegModify (CpuAmdPState, StdHeader);
994
995 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
996 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
997 for (Core = 0; Core < NumberOfCores; Core++) {
efdesign9884cbce22011-08-04 12:09:17 -0600998 if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000999 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
1000 }
1001 }
1002 }
1003 }
1004
1005 return AGESA_SUCCESS;
1006}
1007
1008
1009/**
1010 *---------------------------------------------------------------------------------------
1011 *
1012 * CpuGetPStateLevelStructure
1013 *
1014 * Description:
1015 * Based on the LogicalSocketNumber, this function will return a pointer
1016 * point to the accurate offset of the PSTATE_LEVELING structure.
1017 *
1018 * Parameters:
1019 * @param[in,out] *PStateBufferPtr
1020 * @param[in] *CpuAmdPState
1021 * @param[in] LogicalSocketNumber
1022 * @param[in] *StdHeader
1023 *
1024 * @retval VOID
1025 *
1026 *---------------------------------------------------------------------------------------
1027 **/
1028AGESA_STATUS
1029CpuGetPStateLevelStructure (
1030 OUT PSTATE_LEVELING **PStateBufferPtr,
1031 IN S_CPU_AMD_PSTATE *CpuAmdPState,
1032 IN UINT32 LogicalSocketNumber,
1033 IN AMD_CONFIG_PARAMS *StdHeader
1034 )
1035{
1036 PSTATE_LEVELING *PStateBufferPtrTmp;
1037 UINT32 i;
1038
1039 if (LogicalSocketNumber > CpuAmdPState->TotalSocketInSystem) {
1040 return AGESA_UNSUPPORTED;
1041 }
1042
1043 PStateBufferPtrTmp = CpuAmdPState->PStateLevelingStruc;
1044
1045 for (i = 1; i <= LogicalSocketNumber; i++) {
1046 PStateBufferPtrTmp = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtrTmp + ((UINTN) PStateBufferPtrTmp->PStateLevelingSizeOfBytes));
1047 }
1048
1049 *PStateBufferPtr = PStateBufferPtrTmp;
1050
1051 return AGESA_SUCCESS;
1052}
1053
1054
1055/**
1056 *---------------------------------------------------------------------------------------
1057 *
1058 * PutCoreInPState0
1059 *
1060 * Description:
1061 * This function will take the CPU core into P0
1062 *
1063 * Parameters:
1064 * @param[in] *PStateBuffer
1065 * @param[in] *StdHeader
1066 *
1067 * @retval VOID
1068 *
1069 *---------------------------------------------------------------------------------------
1070 **/
1071VOID
1072STATIC
1073PutCoreInPState0 (
1074 IN VOID *PStateBuffer,
1075 IN AMD_CONFIG_PARAMS *StdHeader
1076 )
1077{
1078 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1079 PSTATE_LEVELING *PStateBufferPtr;
1080
1081 PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
1082
1083 if ((PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1 ) ||
1084 (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_2)) {
1085 return;
1086 }
1087
efdesign9884cbce22011-08-04 12:09:17 -06001088 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001089
1090 FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);
1091}