5 * AMD PSTATE, ACPI table related API functions.
7 * Contains code that generates the _PSS, _PCT, and other ACPI tables.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 35136 $ @e \$Date: 2010-07-16 11:29:48 +0800 (Fri, 16 Jul 2010) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * 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.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * 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.
43 * ***************************************************************************
49 *----------------------------------------------------------------------------
52 *----------------------------------------------------------------------------
56 #include "OptionPstate.h"
57 #include "cpuLateInit.h"
58 #include "cpuRegisters.h"
59 #include "cpuFamilyTranslation.h"
60 #include "GeneralServices.h"
61 #include "cpuServices.h"
62 #include "heapManager.h"
65 #include "GeneralServices.h"
66 #include "cpuPstateTables.h"
67 #include "cpuFeatures.h"
68 #include "cpuIoCstate.h"
72 #define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE
73 /*----------------------------------------------------------------------------
74 * DEFINITIONS AND MACROS
76 *----------------------------------------------------------------------------
78 extern OPTION_PSTATE_LATE_CONFIGURATION OptionPstateLateConfiguration; // global user config record
79 extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
80 extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable;
82 STATIC ACPI_TABLE_HEADER ROMDATA CpuSsdtHdrStruct =
88 {'A','M','D',' ',' ',' '},
89 {'P','O','W','E','R','N','O','W'},
96 /*----------------------------------------------------------------------------
97 * TYPEDEFS AND STRUCTURES
99 *----------------------------------------------------------------------------
102 /*----------------------------------------------------------------------------
103 * PROTOTYPES OF LOCAL FUNCTIONS
105 *----------------------------------------------------------------------------
110 IN S_CPU_AMD_PSTATE *AmdPstatePtr,
111 IN PLATFORM_CONFIGURATION *PlatformConfig,
112 IN AMD_CONFIG_PARAMS *StdHeader
117 IN AMD_CONFIG_PARAMS *StdHeader,
118 IN PLATFORM_CONFIGURATION *PlatformConfig,
119 IN OUT VOID **SsdtPtr
123 CreateAcpiTablesStub (
124 IN PLATFORM_CONFIGURATION *PlatformConfig,
125 IN PSTATE_LEVELING *PStateLevelingBuffer,
126 IN OUT VOID **SsdtPtr,
127 IN UINT8 LocalApicId,
128 IN AMD_CONFIG_PARAMS *StdHeader
132 CreatePStateAcpiTables (
133 IN PLATFORM_CONFIGURATION *PlatformConfig,
134 IN PSTATE_LEVELING *PStateLevelingBuffer,
135 IN OUT VOID **SsdtPtr,
136 IN UINT8 LocalApicId,
137 IN AMD_CONFIG_PARAMS *StdHeader
141 CreateCStateAcpiTables (
142 IN PLATFORM_CONFIGURATION *PlatformConfig,
143 IN PSTATE_LEVELING *PStateLevelingBuffer,
144 IN OUT VOID **SsdtPtr,
145 IN UINT8 LocalApicId,
146 IN AMD_CONFIG_PARAMS *StdHeader
150 *---------------------------------------------------------------------------------------
155 * This function will calculate the size of ACPI PState tables
158 * @param[in] *AmdPstatePtr
159 * @param[in] *PlatformConfig
160 * @param[in] *StdHeader
164 *---------------------------------------------------------------------------------------
168 IN S_CPU_AMD_PSTATE *AmdPstatePtr,
169 IN PLATFORM_CONFIGURATION *PlatformConfig,
170 IN AMD_CONFIG_PARAMS *StdHeader
176 UINT32 MaxCoreNumberInCurrentSocket;
177 UINT32 MaxSocketNumberInSystem;
178 UINT32 MaxPstateNumberInCurrentCore;
179 UINT32 CstateAcpiObjSize;
180 PSTATE_LEVELING *PStateLevelingBufferStructPtr;
181 IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
183 ScopeSize = sizeof (ACPI_TABLE_HEADER);
184 CstateAcpiObjSize = 0;
185 IoCstateFamilyServices = NULL;
187 PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
188 MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem;
190 if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
191 GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (const VOID **)&IoCstateFamilyServices, StdHeader);
192 // If we're supporting multiple families, only proceed when IO Cstate family services are available
193 if (IoCstateFamilyServices != NULL) {
194 CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
198 for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) {
199 MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode;
200 for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) {
201 MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1;
203 ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core
204 ScopeSize += CstateAcpiObjSize; // C-State ACPI objects size per core
206 // Add P-State ACPI Objects size per core
207 if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
208 ScopeSize += (PCT_STRUCT_SIZE +
209 PSS_HEADER_STRUCT_SIZE +
210 (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) +
211 XPSS_HEADER_STRUCT_SIZE +
212 (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) +
213 PSD_HEADER_STRUCT_SIZE +
214 PSD_BODY_STRUCT_SIZE +
215 PPC_HEADER_BODY_STRUCT_SIZE);
218 ScopeSize += MaxCoreNumberInCurrentSocket;
219 PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
221 AmdPstatePtr->SizeOfBytes = ScopeSize;
226 /**--------------------------------------------------------------------------------------
231 * This is the default routine for use when both PState and CState option is NOT
232 * requested. The option install process will create and fill the transfer vector
233 * with the address of the proper routine (Main or Stub). The link optimizer will
234 * strip out of the .DLL the routine that is not used.
237 * @param[in] StdHeader Handle to config for library and services
238 * @param[in] PlatformConfig Contains the power cap parameter
239 * @param[in,out] SsdtPtr ACPI SSDT table pointer
241 * @retval AGESA_STATUS
243 *---------------------------------------------------------------------------------------
247 IN AMD_CONFIG_PARAMS *StdHeader,
248 IN PLATFORM_CONFIGURATION *PlatformConfig,
249 IN OUT VOID **SsdtPtr
252 return AGESA_UNSUPPORTED;
256 *---------------------------------------------------------------------------------------
261 * This function will populate the SSDT with ACPI P-States and C-States Objects, whenever
263 * This function should be called only from BSP
266 * @param[in] StdHeader Handle to config for library and services
267 * @param[in] PlatformConfig Contains the power cap parameter
268 * @param[in,out] SsdtPtr ACPI SSDT pointer
270 * @retval AGESA_STATUS
272 *---------------------------------------------------------------------------------------
276 IN AMD_CONFIG_PARAMS *StdHeader,
277 IN PLATFORM_CONFIGURATION *PlatformConfig,
278 IN OUT VOID **SsdtPtr
290 UINT32 MaxCorePerNode;
292 UINT8 *IntermediatePtr;
293 AGESA_STATUS AgesaStatus;
294 LOCATE_HEAP_PTR LocateHeapParams;
295 ALLOCATE_HEAP_PARAMS AllocateHeapParams;
296 S_CPU_AMD_PSTATE *AmdPstatePtr;
297 PSTATE_LEVELING *PStateLevelingBufferStructPtr;
298 SCOPE *ScopeAcpiTablesStructPtr;
299 SCOPE *ScopeAcpiTablesStructPtrTemp;
301 AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader);
303 ASSERT (IsBsp (StdHeader, &AgesaStatus));
305 // If P-State and C-State ACPI tables do not need to be generated, exit this routine
306 if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
307 AgesaStatus = AGESA_UNSUPPORTED;
311 // Initialize data variables
317 // Locate P-State data buffer
318 LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
319 AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader);
320 if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) {
323 AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader);
325 AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr;
326 PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
328 // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL
329 if (*SsdtPtr == NULL) {
330 //Do not know the actual size.. pre-calculate it.
331 AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader);
332 AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE;
333 AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
335 AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader);
336 if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) {
339 AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader);
340 *SsdtPtr = AllocateHeapParams.BufferPtr;
343 IDS_HDT_CONSOLE (CPU_TRACE, " SSDT is created\n");
345 // Copy SSDT header into allocated buffer
346 LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
347 IntermediatePtr = (UINT8 *) *SsdtPtr;
348 ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)];
350 SocketCount = AmdPstatePtr->TotalSocketInSystem;
352 // Generate name scope and ACPI objects for every core in the system
353 for (i = 0; i < SocketCount; i++) {
354 MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode;
355 for (j = 0; j < MaxCorePerNode; j++) {
357 // Set Name Scope for CPU0, 1, 2, ..... n
358 // CPU0 to CPUn will name as C000 to Cnnn
359 // -----------------------------------------
360 ScopeAcpiTablesStructPtr->ScopeOpcode = SCOPE_OPCODE;
361 // This value will be filled at the end of this function
362 // Since at this time, we don't know how many Pstates we
364 ScopeAcpiTablesStructPtr->ScopeLength = 0;
365 ScopeAcpiTablesStructPtr->ScopeValue1 = SCOPE_VALUE1;
366 ScopeAcpiTablesStructPtr->ScopeValue2 = SCOPE_VALUE2;
367 ScopeAcpiTablesStructPtr->ScopeNamePt1a__ = SCOPE_NAME__;
368 if (PlatformConfig->ProcessorScopeInSb) {
369 ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_S;
370 ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_B;
372 ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_P;
373 ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_R;
375 ScopeAcpiTablesStructPtr->ScopeNamePt1b__ = SCOPE_NAME__;
376 ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z'))
377 ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \
378 ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \
379 (PlatformConfig->ProcessorScopeName1 == '_'))
381 ScopeAcpiTablesStructPtr->ScopeNamePt2a_C = PlatformConfig->ProcessorScopeName0;
382 ScopeAcpiTablesStructPtr->ScopeNamePt2a_P = PlatformConfig->ProcessorScopeName1;
384 TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F;
385 ScopeAcpiTablesStructPtr->ScopeNamePt2a_U = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
387 TempVar8_a = (CoreCount - 1) & 0x0F;
388 if (TempVar8_a < 0xA) {
389 ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
391 ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA);
393 // Increment and typecast the pointer
394 ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr;
395 ScopeAcpiTablesStructPtrTemp++;
397 // Get the Local Apic Id for each core
398 LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j;
400 // Create P-State ACPI Objects
401 CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
403 // Create C-State ACPI Objects
404 CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
406 // Now update the SCOPE Length field
408 CurrSize += (SCOPE_STRUCT_SIZE - 1);
409 ScopeSize += CurrSize;
411 TempVar_b = ((CurrSize << 4) & 0x0000FF00);
412 TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040);
413 TempVar_a = TempVar_b;
414 ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a;
418 ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp;
420 //Calculate next node buffer address
421 PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
423 //Update SSDT header Checksum
424 ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER));
425 ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader);
427 return AGESA_SUCCESS;
430 /**--------------------------------------------------------------------------------------
432 * CreateAcpiTablesStub
435 * This is the default routine for use when the P-State or C-State option is NOT
436 * requested. The option install process will create and fill the transfer vector
437 * with the address of the proper routine (Main or Stub). The link optimizer will
438 * strip out of the .DLL the routine that is not used.
441 * @param[in] PlatformConfig Platform operational characteristics; power cap
442 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
443 * @param[in,out] SsdtPtr ACPI SSDT table pointer
444 * @param[in] LocalApicId Local Apic Id
445 * @param[in] StdHeader Handle to config for library and services
447 * @retval Size of generated ACPI objects
449 *---------------------------------------------------------------------------------------
452 CreateAcpiTablesStub (
453 IN PLATFORM_CONFIGURATION *PlatformConfig,
454 IN PSTATE_LEVELING *PStateLevelingBuffer,
455 IN OUT VOID **SsdtPtr,
456 IN UINT8 LocalApicId,
457 IN AMD_CONFIG_PARAMS *StdHeader
464 /**--------------------------------------------------------------------------------------
466 * CreatePStateAcpiTables
469 * This is the common routine for creating ACPI P-State objects
472 * @param[in] PlatformConfig Platform operational characteristics; power cap
473 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
474 * @param[in,out] SsdtPtr ACPI SSDT table pointer
475 * @param[in] LocalApicId Local Apic Id
476 * @param[in] StdHeader Handle to config for library and services
478 * @retval Size of generated ACPI P-States objects
480 *---------------------------------------------------------------------------------------
483 CreatePStateAcpiTables (
484 IN PLATFORM_CONFIGURATION *PlatformConfig,
485 IN PSTATE_LEVELING *PStateLevelingBuffer,
486 IN OUT VOID **SsdtPtr,
487 IN UINT8 LocalApicId,
488 IN AMD_CONFIG_PARAMS *StdHeader
491 UINT8 PstateCapLevelSupport;
492 UINT8 PStateMaxValueOnCurrentCore;
493 BOOLEAN PstateCapEnable;
494 BOOLEAN PstateCapLevelSupportDetermined;
495 BOOLEAN IsPsdDependent;
500 UINT32 PstateCapInputMilliWatts;
504 UINT32 TransAndBusMastLatency;
505 AGESA_STATUS IgnoredStatus;
507 PCT_HEADER_BODY *pPctAcpiTables;
508 PSS_HEADER *pPssHeaderAcpiTables;
509 PSS_BODY *pPssBodyAcpiTables;
510 XPSS_HEADER *pXpssHeaderAcpiTables;
511 XPSS_BODY *pXpssBodyAcpiTables;
512 PSD_HEADER *pPsdHeaderAcpiTables;
513 PSD_BODY *pPsdBodyAcpiTables;
514 PPC_HEADER_BODY *pPpcAcpiTables;
515 PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
519 PstateCapEnable = FALSE;
520 PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP;
521 PstateCapLevelSupportDetermined = TRUE;
522 PstateCapInputMilliWatts = PlatformConfig->PowerCeiling;
523 IsPsdDependent = !(PlatformConfig->ForcePstateIndependent);
524 TransAndBusMastLatency = 0;
526 if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
527 pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr;
529 //Check Pstate Capability
530 if (PstateCapInputMilliWatts != 0) {
531 PstateCapEnable = TRUE;
532 PstateCapLevelSupportDetermined = FALSE;
535 PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue;
536 if (OptionPstateLateConfiguration.CfgPstatePct) {
539 pPctAcpiTables->NameOpcode = NAME_OPCODE;
540 pPctAcpiTables->PctName_a__ = PCT_NAME__;
541 pPctAcpiTables->PctName_a_P = PCT_NAME_P;
542 pPctAcpiTables->PctName_a_C = PCT_NAME_C;
543 pPctAcpiTables->PctName_a_T = PCT_NAME_T;
544 pPctAcpiTables->Value1 = PCT_VALUE1;
545 pPctAcpiTables->Value2 = PCT_VALUE2;
546 pPctAcpiTables->Value3 = PCT_VALUE3;
547 pPctAcpiTables->GenericRegDescription1 = GENERIC_REG_DESCRIPTION;
548 pPctAcpiTables->Length1 = PCT_LENGTH;
549 pPctAcpiTables->AddressSpaceId1 = PCT_ADDRESS_SPACE_ID;
550 pPctAcpiTables->RegisterBitWidth1 = PCT_REGISTER_BIT_WIDTH;
551 pPctAcpiTables->RegisterBitOffset1 = PCT_REGISTER_BIT_OFFSET;
552 pPctAcpiTables->Reserved1 = PCT_RESERVED;
553 pPctAcpiTables->ControlRegAddressLo = PCT_CONTROL_REG_LO;
554 pPctAcpiTables->ControlRegAddressHi = PCT_CONTROL_REG_HI;
555 pPctAcpiTables->Value4 = PCT_VALUE4;
556 pPctAcpiTables->Value5 = PCT_VALUE5;
557 pPctAcpiTables->GenericRegDescription2 = GENERIC_REG_DESCRIPTION;
558 pPctAcpiTables->Length2 = PCT_LENGTH;
559 pPctAcpiTables->AddressSpaceId2 = PCT_ADDRESS_SPACE_ID;
560 pPctAcpiTables->RegisterBitWidth2 = PCT_REGISTER_BIT_WIDTH;
561 pPctAcpiTables->RegisterBitOffset2 = PCT_REGISTER_BIT_OFFSET;
562 pPctAcpiTables->Reserved2 = PCT_RESERVED;
563 pPctAcpiTables->StatusRegAddressLo = PCT_STATUS_REG_LO;
564 pPctAcpiTables->StatusRegAddressHi = PCT_STATUS_REG_HI;
565 pPctAcpiTables->Value6 = PCT_VALUE6;
567 // Increment and then typecast the pointer
569 CurrSize += PCT_STRUCT_SIZE;
571 *SsdtPtr = pPctAcpiTables;
572 } // end of OptionPstateLateConfiguration.CfgPstatePct
574 pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables;
575 pPssBodyAcpiTables = (PSS_BODY *) pPctAcpiTables;
576 if (OptionPstateLateConfiguration.CfgPstatePss) {
578 // Note: Set pssLength and numOfItemsInPss later
579 //---------------------------------------------------
580 pPssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
581 pPssHeaderAcpiTables->PssName_a__ = PSS_NAME__;
582 pPssHeaderAcpiTables->PssName_a_P = PSS_NAME_P;
583 pPssHeaderAcpiTables->PssName_a_S = PSS_NAME_S;
584 pPssHeaderAcpiTables->PssName_b_S = PSS_NAME_S;
585 pPssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
587 pPssHeaderAcpiTables++;
588 pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables;
589 // Restore the pPssHeaderAcpiTables
590 pPssHeaderAcpiTables--;
596 // Calculate PCI address for socket only
597 GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus);
598 TransAndBusMastLatency = 0;
599 GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (const VOID **)&FamilyServices, StdHeader);
600 ASSERT (FamilyServices != NULL)
601 FamilyServices->GetPstateLatency ( FamilyServices,
602 PStateLevelingBuffer,
604 &TransAndBusMastLatency,
607 for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
608 if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
609 pPssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
610 pPssBodyAcpiTables->PkgLength = PSS_PKG_LENGTH;
611 pPssBodyAcpiTables->NumOfElements = PSS_NUM_OF_ELEMENTS;
612 pPssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
613 pPssBodyAcpiTables->Frequency =
614 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
615 pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
616 pPssBodyAcpiTables->Power =
617 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
619 if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) {
620 PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
621 PstateCapLevelSupportDetermined = TRUE;
624 pPssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
625 pPssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
626 pPssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
627 pPssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
628 pPssBodyAcpiTables->DwordPrefixOpcode5 = DWORD_PREFIX_OPCODE;
629 pPssBodyAcpiTables->Control =
630 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
631 pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE;
632 pPssBodyAcpiTables->Status =
633 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
635 pPssBodyAcpiTables++;
638 } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
640 if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) {
641 PstateCapLevelSupport = PStateMaxValueOnCurrentCore;
644 // Set _PSS Header again
645 // Now Set pssLength and numOfItemsInPss
646 //---------------------------------------
647 TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3;
648 TempVar_b = TempVar_a;
649 TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
650 TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
651 TempVar_a = (UINT16) TempVar_c;
653 pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a;
654 pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount;
655 CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE));
657 *SsdtPtr = pPssBodyAcpiTables;
658 } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss
662 // Typecast the pointer
663 pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables;
664 pXpssBodyAcpiTables = (XPSS_BODY *) pPssBodyAcpiTables;
665 if (OptionPstateLateConfiguration.CfgPstateXpss) {
667 // Note: Set the pssLength and numOfItemsInPss later
668 //---------------------------------------------------
669 pXpssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
670 pXpssHeaderAcpiTables->XpssName_a_X = PSS_NAME_X;
671 pXpssHeaderAcpiTables->XpssName_a_P = PSS_NAME_P;
672 pXpssHeaderAcpiTables->XpssName_a_S = PSS_NAME_S;
673 pXpssHeaderAcpiTables->XpssName_b_S = PSS_NAME_S;
674 pXpssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
676 // Increment and then typecast the pointer
677 pXpssHeaderAcpiTables++;
678 pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables;
679 // Restore the pXpssHeaderAcpiTables
680 pXpssHeaderAcpiTables--;
684 for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
685 if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
686 pXpssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
687 pXpssBodyAcpiTables->PkgLength = XPSS_PKG_LENGTH;
688 pXpssBodyAcpiTables->NumOfElements = XPSS_NUM_OF_ELEMENTS;
689 pXpssBodyAcpiTables->XpssValueTbd = 04;
690 pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
691 pXpssBodyAcpiTables->Frequency =
692 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
693 pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
694 pXpssBodyAcpiTables->Power =
695 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
696 pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
697 pXpssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
698 pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
699 pXpssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
700 pXpssBodyAcpiTables->ControlBuffer = XPSS_ACPI_BUFFER;
701 pXpssBodyAcpiTables->ControlLo =
702 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
703 pXpssBodyAcpiTables->ControlHi = 0;
704 pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER;
705 pXpssBodyAcpiTables->StatusLo =
706 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
707 pXpssBodyAcpiTables->StatusHi = 0;
708 pXpssBodyAcpiTables->ControlMaskBuffer = XPSS_ACPI_BUFFER;
709 pXpssBodyAcpiTables->ControlMaskLo = 0;
710 pXpssBodyAcpiTables->ControlMaskHi = 0;
711 pXpssBodyAcpiTables->StatusMaskBuffer = XPSS_ACPI_BUFFER;
712 pXpssBodyAcpiTables->StatusMaskLo = 0;
713 pXpssBodyAcpiTables->StatusMaskHi = 0;
715 pXpssBodyAcpiTables++;
717 } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
719 // Set XPSS Header again
720 // Now set pssLength and numOfItemsInPss
721 //---------------------------------------
722 TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3;
723 TempVar_b = TempVar_a;
724 TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
725 TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
726 TempVar_a = (UINT16) TempVar_c;
728 pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a;
729 pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount;
730 CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE));
732 *SsdtPtr = pXpssBodyAcpiTables;
733 } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss
737 // Typecast the pointer
738 pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables;
739 pPsdBodyAcpiTables = (PSD_BODY *) pXpssBodyAcpiTables;
740 // Get Total Cores Per Node
741 if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) {
742 GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (const VOID **)&FamilyServices, StdHeader);
743 ASSERT (FamilyServices != NULL)
744 if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) &&
745 FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) {
748 pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE;
749 pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
750 pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH;
751 pPsdHeaderAcpiTables->Value1 = PSD_VALUE1;
752 pPsdHeaderAcpiTables->PsdName_a__ = PSD_NAME__;
753 pPsdHeaderAcpiTables->PsdName_a_P = PSD_NAME_P;
754 pPsdHeaderAcpiTables->PsdName_a_S = PSD_NAME_S;
755 pPsdHeaderAcpiTables->PsdName_a_D = PSD_NAME_D;
757 // Typecast the pointer
758 pPsdHeaderAcpiTables++;
759 CurrSize += PSD_HEADER_STRUCT_SIZE;
760 pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables;
762 pPsdHeaderAcpiTables--;
765 pPsdBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
766 pPsdBodyAcpiTables->PkgLength = PSD_PKG_LENGTH;
767 pPsdBodyAcpiTables->NumOfEntries = NUM_OF_ENTRIES;
768 pPsdBodyAcpiTables->BytePrefixOpcode1 = BYTE_PREFIX_OPCODE;
769 pPsdBodyAcpiTables->PsdNumOfEntries = PSD_NUM_OF_ENTRIES;
770 pPsdBodyAcpiTables->BytePrefixOpcode2 = BYTE_PREFIX_OPCODE;
771 pPsdBodyAcpiTables->PsdRevision = PSD_REVISION;
772 pPsdBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
774 IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader);
776 if (IsPsdDependent) {
777 pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN;
778 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL;
779 pPsdBodyAcpiTables->NumOfProcessors = CoreCount1;
781 switch (GetComputeUnitMapping (StdHeader)) {
782 case AllCoresMapping:
783 // All cores are in their own compute unit.
784 pPsdBodyAcpiTables->DependencyDomain = LocalApicId;
785 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY;
786 pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS;
788 case EvenCoresMapping:
789 // Cores are paired in compute units.
790 pPsdBodyAcpiTables->DependencyDomain = (LocalApicId >> 1) & PSD_DOMAIN_COMPUTE_UNIT_MASK;
791 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL;
792 pPsdBodyAcpiTables->NumOfProcessors = PSD_CORE_NUM_PER_COMPUTE_UNIT;
798 pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
799 pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
801 pPsdBodyAcpiTables++;
802 *SsdtPtr = pPsdBodyAcpiTables;
803 CurrSize += PSD_BODY_STRUCT_SIZE;
805 }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd)
806 // Typecast the pointer
808 pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables;
812 if (OptionPstateLateConfiguration.CfgPstatePpc) {
813 pPpcAcpiTables->NameOpcode = NAME_OPCODE;
814 pPpcAcpiTables->PpcName_a__ = PPC_NAME__;
815 pPpcAcpiTables->PpcName_a_P = PPC_NAME_P;
816 pPpcAcpiTables->PpcName_b_P = PPC_NAME_P;
817 pPpcAcpiTables->PpcName_a_C = PPC_NAME_C;
818 pPpcAcpiTables->Value1 = PPC_VALUE1;
820 pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport;
821 CurrSize += PPC_HEADER_BODY_STRUCT_SIZE;
822 // Increment and typecast the pointer
824 *SsdtPtr = pPpcAcpiTables;
825 }// end of OptionPstateLateConfiguration.CfgPstatePpc
830 /**--------------------------------------------------------------------------------------
832 * CreateCStateAcpiTables
835 * This is the common routine for creating ACPI C-State objects
838 * @param[in] PlatformConfig Platform operational characteristics; power cap
839 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
840 * @param[in,out] SsdtPtr ACPI SSDT table pointer
841 * @param[in] LocalApicId Local Apic Id
842 * @param[in] StdHeader Handle to config for library and services
844 * @retval Size of ACPI C-States objects generated
846 *---------------------------------------------------------------------------------------
849 CreateCStateAcpiTables (
850 IN PLATFORM_CONFIGURATION *PlatformConfig,
851 IN PSTATE_LEVELING *PStateLevelingBuffer,
852 IN OUT VOID **SsdtPtr,
853 IN UINT8 LocalApicId,
854 IN AMD_CONFIG_PARAMS *StdHeader
858 IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
862 if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
863 GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (const VOID **)&IoCstateFamilyServices, StdHeader);
864 // If we're supporting multiple families, only proceed when IO Cstate family services are available
865 if (IoCstateFamilyServices != NULL) {
866 IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader);
867 ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);