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: 55600 $ @e \$Date: 2011-06-23 12:39:18 -0600 (Thu, 23 Jun 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ******************************************************************************
47 *----------------------------------------------------------------------------
50 *----------------------------------------------------------------------------
54 #include "OptionPstate.h"
55 #include "cpuLateInit.h"
56 #include "cpuRegisters.h"
57 #include "cpuFamilyTranslation.h"
58 #include "GeneralServices.h"
59 #include "cpuServices.h"
60 #include "heapManager.h"
63 #include "GeneralServices.h"
64 #include "cpuPstateTables.h"
65 #include "cpuFeatures.h"
66 #include "cpuIoCstate.h"
70 #define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE
71 /*----------------------------------------------------------------------------
72 * DEFINITIONS AND MACROS
74 *----------------------------------------------------------------------------
76 extern OPTION_PSTATE_LATE_CONFIGURATION OptionPstateLateConfiguration; // global user config record
77 extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
78 extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable;
80 STATIC ACPI_TABLE_HEADER ROMDATA CpuSsdtHdrStruct =
86 {'A','M','D',' ',' ',' '},
87 {'P','O','W','E','R','N','O','W'},
94 /*----------------------------------------------------------------------------
95 * TYPEDEFS AND STRUCTURES
97 *----------------------------------------------------------------------------
100 /*----------------------------------------------------------------------------
101 * PROTOTYPES OF LOCAL FUNCTIONS
103 *----------------------------------------------------------------------------
108 IN S_CPU_AMD_PSTATE *AmdPstatePtr,
109 IN PLATFORM_CONFIGURATION *PlatformConfig,
110 IN AMD_CONFIG_PARAMS *StdHeader
115 IN AMD_CONFIG_PARAMS *StdHeader,
116 IN PLATFORM_CONFIGURATION *PlatformConfig,
117 IN OUT VOID **SsdtPtr
121 CreateAcpiTablesStub (
122 IN PLATFORM_CONFIGURATION *PlatformConfig,
123 IN PSTATE_LEVELING *PStateLevelingBuffer,
124 IN OUT VOID **SsdtPtr,
125 IN UINT8 LocalApicId,
126 IN AMD_CONFIG_PARAMS *StdHeader
130 CreatePStateAcpiTables (
131 IN PLATFORM_CONFIGURATION *PlatformConfig,
132 IN PSTATE_LEVELING *PStateLevelingBuffer,
133 IN OUT VOID **SsdtPtr,
134 IN UINT8 LocalApicId,
135 IN AMD_CONFIG_PARAMS *StdHeader
139 CreateCStateAcpiTables (
140 IN PLATFORM_CONFIGURATION *PlatformConfig,
141 IN PSTATE_LEVELING *PStateLevelingBuffer,
142 IN OUT VOID **SsdtPtr,
143 IN UINT8 LocalApicId,
144 IN AMD_CONFIG_PARAMS *StdHeader
149 IN AMD_CONFIG_PARAMS *StdHeader,
150 IN PLATFORM_CONFIGURATION *PlatformConfig,
151 IN OUT VOID **SsdtPtr
155 *---------------------------------------------------------------------------------------
160 * This function will calculate the size of ACPI PState tables
163 * @param[in] *AmdPstatePtr
164 * @param[in] *PlatformConfig
165 * @param[in] *StdHeader
169 *---------------------------------------------------------------------------------------
174 IN S_CPU_AMD_PSTATE *AmdPstatePtr,
175 IN PLATFORM_CONFIGURATION *PlatformConfig,
176 IN AMD_CONFIG_PARAMS *StdHeader
182 UINT32 MaxCoreNumberInCurrentSocket;
183 UINT32 MaxSocketNumberInSystem;
184 UINT32 MaxPstateNumberInCurrentCore;
185 UINT32 CstateAcpiObjSize;
186 PSTATE_LEVELING *PStateLevelingBufferStructPtr;
187 IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
189 ScopeSize = sizeof (ACPI_TABLE_HEADER);
190 CstateAcpiObjSize = 0;
191 IoCstateFamilyServices = NULL;
193 PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
194 MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem;
196 if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
197 GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader);
198 // If we're supporting multiple families, only proceed when IO Cstate family services are available
199 if (IoCstateFamilyServices != NULL) {
200 CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
204 for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) {
205 MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode;
206 for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) {
207 MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1;
209 ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core
210 ScopeSize += CstateAcpiObjSize; // C-State ACPI objects size per core
212 // Add P-State ACPI Objects size per core
213 if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
214 ScopeSize += (PCT_STRUCT_SIZE +
215 PSS_HEADER_STRUCT_SIZE +
216 (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) +
217 XPSS_HEADER_STRUCT_SIZE +
218 (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) +
219 PSD_HEADER_STRUCT_SIZE +
220 PSD_BODY_STRUCT_SIZE +
221 PPC_HEADER_BODY_STRUCT_SIZE);
224 ScopeSize += MaxCoreNumberInCurrentSocket;
225 PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
227 AmdPstatePtr->SizeOfBytes = ScopeSize;
232 /**--------------------------------------------------------------------------------------
237 * This is the default routine for use when both PState and CState option is NOT
238 * requested. The option install process will create and fill the transfer vector
239 * with the address of the proper routine (Main or Stub). The link optimizer will
240 * strip out of the .DLL the routine that is not used.
243 * @param[in] StdHeader Handle to config for library and services
244 * @param[in] PlatformConfig Contains the power cap parameter
245 * @param[in,out] SsdtPtr ACPI SSDT table pointer
247 * @retval AGESA_STATUS
249 *---------------------------------------------------------------------------------------
253 IN AMD_CONFIG_PARAMS *StdHeader,
254 IN PLATFORM_CONFIGURATION *PlatformConfig,
255 IN OUT VOID **SsdtPtr
258 return AGESA_UNSUPPORTED;
262 *---------------------------------------------------------------------------------------
267 * This function will populate the SSDT with ACPI P-States and C-States Objects, whenever
269 * This function should be called only from BSP
272 * @param[in] StdHeader Handle to config for library and services
273 * @param[in] PlatformConfig Contains the power cap parameter
274 * @param[in,out] SsdtPtr ACPI SSDT pointer
276 * @retval AGESA_STATUS
278 *---------------------------------------------------------------------------------------
282 IN AMD_CONFIG_PARAMS *StdHeader,
283 IN PLATFORM_CONFIGURATION *PlatformConfig,
284 IN OUT VOID **SsdtPtr
296 UINT32 MaxCorePerNode;
298 UINT8 *IntermediatePtr;
299 AGESA_STATUS AgesaStatus;
300 LOCATE_HEAP_PTR LocateHeapParams;
301 ALLOCATE_HEAP_PARAMS AllocateHeapParams;
302 S_CPU_AMD_PSTATE *AmdPstatePtr;
303 PSTATE_LEVELING *PStateLevelingBufferStructPtr;
304 SCOPE *ScopeAcpiTablesStructPtr;
305 SCOPE *ScopeAcpiTablesStructPtrTemp;
307 AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader);
309 ASSERT (IsBsp (StdHeader, &AgesaStatus));
311 // If P-State and C-State ACPI tables do not need to be generated, exit this routine
312 if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
313 AgesaStatus = AGESA_UNSUPPORTED;
317 // Initialize data variables
323 // Locate P-State data buffer
324 LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
325 AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader);
326 if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) {
329 AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader);
331 AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr;
332 PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
334 // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL
335 if (*SsdtPtr == NULL) {
336 //Do not know the actual size.. pre-calculate it.
337 AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader);
338 AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE;
339 AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
341 AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader);
342 if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) {
345 AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader);
346 *SsdtPtr = AllocateHeapParams.BufferPtr;
349 IDS_HDT_CONSOLE (CPU_TRACE, " SSDT is created\n");
351 // Copy SSDT header into allocated buffer
352 LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
353 IntermediatePtr = (UINT8 *) *SsdtPtr;
354 ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)];
356 SocketCount = AmdPstatePtr->TotalSocketInSystem;
358 // Generate name scope and ACPI objects for every core in the system
359 for (i = 0; i < SocketCount; i++) {
360 MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode;
361 for (j = 0; j < MaxCorePerNode; j++) {
363 // Set Name Scope for CPU0, 1, 2, ..... n
364 // CPU0 to CPUn will name as C000 to Cnnn
365 // -----------------------------------------
366 ScopeAcpiTablesStructPtr->ScopeOpcode = SCOPE_OPCODE;
367 // This value will be filled at the end of this function
368 // Since at this time, we don't know how many Pstates we
370 ScopeAcpiTablesStructPtr->ScopeLength = 0;
371 ScopeAcpiTablesStructPtr->ScopeValue1 = SCOPE_VALUE1;
372 ScopeAcpiTablesStructPtr->ScopeValue2 = SCOPE_VALUE2;
373 ScopeAcpiTablesStructPtr->ScopeNamePt1a__ = SCOPE_NAME__;
374 if (PlatformConfig->ProcessorScopeInSb) {
375 ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_S;
376 ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_B;
378 ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_P;
379 ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_R;
381 ScopeAcpiTablesStructPtr->ScopeNamePt1b__ = SCOPE_NAME__;
382 ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z'))
383 ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \
384 ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \
385 (PlatformConfig->ProcessorScopeName1 == '_'))
387 ScopeAcpiTablesStructPtr->ScopeNamePt2a_C = PlatformConfig->ProcessorScopeName0;
388 ScopeAcpiTablesStructPtr->ScopeNamePt2a_P = PlatformConfig->ProcessorScopeName1;
390 TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F;
391 ScopeAcpiTablesStructPtr->ScopeNamePt2a_U = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
393 TempVar8_a = (CoreCount - 1) & 0x0F;
394 if (TempVar8_a < 0xA) {
395 ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
397 ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA);
399 // Increment and typecast the pointer
400 ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr;
401 ScopeAcpiTablesStructPtrTemp++;
403 // Get the Local Apic Id for each core
404 LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j;
406 // Create P-State ACPI Objects
407 CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
409 // Create C-State ACPI Objects
410 CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
412 // Now update the SCOPE Length field
414 CurrSize += (SCOPE_STRUCT_SIZE - 1);
415 ScopeSize += CurrSize;
417 TempVar_b = ((CurrSize << 4) & 0x0000FF00);
418 TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040);
419 TempVar_a = TempVar_b;
420 ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a;
424 ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp;
426 //Calculate next node buffer address
427 PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
429 //Update SSDT header Checksum
430 ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER));
431 ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader);
433 return AGESA_SUCCESS;
436 /**--------------------------------------------------------------------------------------
438 * CreateAcpiTablesStub
441 * This is the default routine for use when the P-State or C-State option is NOT
442 * requested. The option install process will create and fill the transfer vector
443 * with the address of the proper routine (Main or Stub). The link optimizer will
444 * strip out of the .DLL the routine that is not used.
447 * @param[in] PlatformConfig Platform operational characteristics; power cap
448 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
449 * @param[in,out] SsdtPtr ACPI SSDT table pointer
450 * @param[in] LocalApicId Local Apic Id
451 * @param[in] StdHeader Handle to config for library and services
453 * @retval Size of generated ACPI objects
455 *---------------------------------------------------------------------------------------
458 CreateAcpiTablesStub (
459 IN PLATFORM_CONFIGURATION *PlatformConfig,
460 IN PSTATE_LEVELING *PStateLevelingBuffer,
461 IN OUT VOID **SsdtPtr,
462 IN UINT8 LocalApicId,
463 IN AMD_CONFIG_PARAMS *StdHeader
470 /**--------------------------------------------------------------------------------------
472 * CreatePStateAcpiTables
475 * This is the common routine for creating ACPI P-State objects
478 * @param[in] PlatformConfig Platform operational characteristics; power cap
479 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
480 * @param[in,out] SsdtPtr ACPI SSDT table pointer
481 * @param[in] LocalApicId Local Apic Id
482 * @param[in] StdHeader Handle to config for library and services
484 * @retval Size of generated ACPI P-States objects
486 *---------------------------------------------------------------------------------------
489 CreatePStateAcpiTables (
490 IN PLATFORM_CONFIGURATION *PlatformConfig,
491 IN PSTATE_LEVELING *PStateLevelingBuffer,
492 IN OUT VOID **SsdtPtr,
493 IN UINT8 LocalApicId,
494 IN AMD_CONFIG_PARAMS *StdHeader
497 UINT8 PstateCapLevelSupport;
498 UINT8 PStateMaxValueOnCurrentCore;
499 BOOLEAN PstateCapEnable;
500 BOOLEAN PstateCapLevelSupportDetermined;
501 BOOLEAN IsPsdDependent;
506 UINT32 PstateCapInputMilliWatts;
510 UINT32 TransAndBusMastLatency;
511 AGESA_STATUS IgnoredStatus;
513 PCT_HEADER_BODY *pPctAcpiTables;
514 PSS_HEADER *pPssHeaderAcpiTables;
515 PSS_BODY *pPssBodyAcpiTables;
516 XPSS_HEADER *pXpssHeaderAcpiTables;
517 XPSS_BODY *pXpssBodyAcpiTables;
518 PSD_HEADER *pPsdHeaderAcpiTables;
519 PSD_BODY *pPsdBodyAcpiTables;
520 PPC_HEADER_BODY *pPpcAcpiTables;
521 PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
525 PstateCapEnable = FALSE;
526 PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP;
527 PstateCapLevelSupportDetermined = TRUE;
528 PstateCapInputMilliWatts = PlatformConfig->PowerCeiling;
529 IsPsdDependent = !(PlatformConfig->ForcePstateIndependent);
530 TransAndBusMastLatency = 0;
532 if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
533 pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr;
535 //Check Pstate Capability
536 if (PstateCapInputMilliWatts != 0) {
537 PstateCapEnable = TRUE;
538 PstateCapLevelSupportDetermined = FALSE;
541 PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue;
542 if (OptionPstateLateConfiguration.CfgPstatePct) {
545 pPctAcpiTables->NameOpcode = NAME_OPCODE;
546 pPctAcpiTables->PctName_a__ = PCT_NAME__;
547 pPctAcpiTables->PctName_a_P = PCT_NAME_P;
548 pPctAcpiTables->PctName_a_C = PCT_NAME_C;
549 pPctAcpiTables->PctName_a_T = PCT_NAME_T;
550 pPctAcpiTables->Value1 = PCT_VALUE1;
551 pPctAcpiTables->Value2 = PCT_VALUE2;
552 pPctAcpiTables->Value3 = PCT_VALUE3;
553 pPctAcpiTables->GenericRegDescription1 = GENERIC_REG_DESCRIPTION;
554 pPctAcpiTables->Length1 = PCT_LENGTH;
555 pPctAcpiTables->AddressSpaceId1 = PCT_ADDRESS_SPACE_ID;
556 pPctAcpiTables->RegisterBitWidth1 = PCT_REGISTER_BIT_WIDTH;
557 pPctAcpiTables->RegisterBitOffset1 = PCT_REGISTER_BIT_OFFSET;
558 pPctAcpiTables->Reserved1 = PCT_RESERVED;
559 pPctAcpiTables->ControlRegAddressLo = PCT_CONTROL_REG_LO;
560 pPctAcpiTables->ControlRegAddressHi = PCT_CONTROL_REG_HI;
561 pPctAcpiTables->Value4 = PCT_VALUE4;
562 pPctAcpiTables->Value5 = PCT_VALUE5;
563 pPctAcpiTables->GenericRegDescription2 = GENERIC_REG_DESCRIPTION;
564 pPctAcpiTables->Length2 = PCT_LENGTH;
565 pPctAcpiTables->AddressSpaceId2 = PCT_ADDRESS_SPACE_ID;
566 pPctAcpiTables->RegisterBitWidth2 = PCT_REGISTER_BIT_WIDTH;
567 pPctAcpiTables->RegisterBitOffset2 = PCT_REGISTER_BIT_OFFSET;
568 pPctAcpiTables->Reserved2 = PCT_RESERVED;
569 pPctAcpiTables->StatusRegAddressLo = PCT_STATUS_REG_LO;
570 pPctAcpiTables->StatusRegAddressHi = PCT_STATUS_REG_HI;
571 pPctAcpiTables->Value6 = PCT_VALUE6;
573 // Increment and then typecast the pointer
575 CurrSize += PCT_STRUCT_SIZE;
577 *SsdtPtr = pPctAcpiTables;
578 } // end of OptionPstateLateConfiguration.CfgPstatePct
580 pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables;
581 pPssBodyAcpiTables = (PSS_BODY *) pPctAcpiTables;
582 if (OptionPstateLateConfiguration.CfgPstatePss) {
584 // Note: Set pssLength and numOfItemsInPss later
585 //---------------------------------------------------
586 pPssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
587 pPssHeaderAcpiTables->PssName_a__ = PSS_NAME__;
588 pPssHeaderAcpiTables->PssName_a_P = PSS_NAME_P;
589 pPssHeaderAcpiTables->PssName_a_S = PSS_NAME_S;
590 pPssHeaderAcpiTables->PssName_b_S = PSS_NAME_S;
591 pPssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
593 pPssHeaderAcpiTables++;
594 pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables;
595 // Restore the pPssHeaderAcpiTables
596 pPssHeaderAcpiTables--;
602 // Calculate PCI address for socket only
603 GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus);
604 TransAndBusMastLatency = 0;
605 GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader);
606 ASSERT (FamilyServices != NULL)
607 FamilyServices->GetPstateLatency ( FamilyServices,
608 PStateLevelingBuffer,
610 &TransAndBusMastLatency,
613 for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
614 if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
615 pPssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
616 pPssBodyAcpiTables->PkgLength = PSS_PKG_LENGTH;
617 pPssBodyAcpiTables->NumOfElements = PSS_NUM_OF_ELEMENTS;
618 pPssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
619 pPssBodyAcpiTables->Frequency =
620 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
621 pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
622 pPssBodyAcpiTables->Power =
623 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
625 if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) {
626 PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
627 PstateCapLevelSupportDetermined = TRUE;
630 pPssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
631 pPssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
632 pPssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
633 pPssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
634 pPssBodyAcpiTables->DwordPrefixOpcode5 = DWORD_PREFIX_OPCODE;
635 pPssBodyAcpiTables->Control =
636 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
637 pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE;
638 pPssBodyAcpiTables->Status =
639 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
641 pPssBodyAcpiTables++;
644 } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
646 if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) {
647 PstateCapLevelSupport = PStateMaxValueOnCurrentCore;
650 // Set _PSS Header again
651 // Now Set pssLength and numOfItemsInPss
652 //---------------------------------------
653 TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3;
654 TempVar_b = TempVar_a;
655 TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
656 TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
657 TempVar_a = (UINT16) TempVar_c;
659 pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a;
660 pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount;
661 CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE));
663 *SsdtPtr = pPssBodyAcpiTables;
664 } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss
668 // Typecast the pointer
669 pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables;
670 pXpssBodyAcpiTables = (XPSS_BODY *) pPssBodyAcpiTables;
671 if (OptionPstateLateConfiguration.CfgPstateXpss) {
673 // Note: Set the pssLength and numOfItemsInPss later
674 //---------------------------------------------------
675 pXpssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
676 pXpssHeaderAcpiTables->XpssName_a_X = PSS_NAME_X;
677 pXpssHeaderAcpiTables->XpssName_a_P = PSS_NAME_P;
678 pXpssHeaderAcpiTables->XpssName_a_S = PSS_NAME_S;
679 pXpssHeaderAcpiTables->XpssName_b_S = PSS_NAME_S;
680 pXpssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
682 // Increment and then typecast the pointer
683 pXpssHeaderAcpiTables++;
684 pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables;
685 // Restore the pXpssHeaderAcpiTables
686 pXpssHeaderAcpiTables--;
690 for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
691 if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
692 pXpssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
693 pXpssBodyAcpiTables->PkgLength = XPSS_PKG_LENGTH;
694 pXpssBodyAcpiTables->NumOfElements = XPSS_NUM_OF_ELEMENTS;
695 pXpssBodyAcpiTables->XpssValueTbd = 04;
696 pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
697 pXpssBodyAcpiTables->Frequency =
698 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
699 pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
700 pXpssBodyAcpiTables->Power =
701 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
702 pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
703 pXpssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
704 pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
705 pXpssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
706 pXpssBodyAcpiTables->ControlBuffer = XPSS_ACPI_BUFFER;
707 pXpssBodyAcpiTables->ControlLo =
708 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
709 pXpssBodyAcpiTables->ControlHi = 0;
710 pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER;
711 pXpssBodyAcpiTables->StatusLo =
712 PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
713 pXpssBodyAcpiTables->StatusHi = 0;
714 pXpssBodyAcpiTables->ControlMaskBuffer = XPSS_ACPI_BUFFER;
715 pXpssBodyAcpiTables->ControlMaskLo = 0;
716 pXpssBodyAcpiTables->ControlMaskHi = 0;
717 pXpssBodyAcpiTables->StatusMaskBuffer = XPSS_ACPI_BUFFER;
718 pXpssBodyAcpiTables->StatusMaskLo = 0;
719 pXpssBodyAcpiTables->StatusMaskHi = 0;
721 pXpssBodyAcpiTables++;
723 } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
725 // Set XPSS Header again
726 // Now set pssLength and numOfItemsInPss
727 //---------------------------------------
728 TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3;
729 TempVar_b = TempVar_a;
730 TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
731 TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
732 TempVar_a = (UINT16) TempVar_c;
734 pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a;
735 pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount;
736 CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE));
738 *SsdtPtr = pXpssBodyAcpiTables;
739 } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss
743 // Typecast the pointer
744 pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables;
745 pPsdBodyAcpiTables = (PSD_BODY *) pXpssBodyAcpiTables;
746 // Get Total Cores Per Node
747 if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) {
748 GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader);
749 ASSERT (FamilyServices != NULL)
750 if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) &&
751 FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) {
754 pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE;
755 pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
756 pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH;
757 pPsdHeaderAcpiTables->Value1 = PSD_VALUE1;
758 pPsdHeaderAcpiTables->PsdName_a__ = PSD_NAME__;
759 pPsdHeaderAcpiTables->PsdName_a_P = PSD_NAME_P;
760 pPsdHeaderAcpiTables->PsdName_a_S = PSD_NAME_S;
761 pPsdHeaderAcpiTables->PsdName_a_D = PSD_NAME_D;
763 // Typecast the pointer
764 pPsdHeaderAcpiTables++;
765 CurrSize += PSD_HEADER_STRUCT_SIZE;
766 pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables;
768 pPsdHeaderAcpiTables--;
771 pPsdBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
772 pPsdBodyAcpiTables->PkgLength = PSD_PKG_LENGTH;
773 pPsdBodyAcpiTables->NumOfEntries = NUM_OF_ENTRIES;
774 pPsdBodyAcpiTables->BytePrefixOpcode1 = BYTE_PREFIX_OPCODE;
775 pPsdBodyAcpiTables->PsdNumOfEntries = PSD_NUM_OF_ENTRIES;
776 pPsdBodyAcpiTables->BytePrefixOpcode2 = BYTE_PREFIX_OPCODE;
777 pPsdBodyAcpiTables->PsdRevision = PSD_REVISION;
778 pPsdBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
780 IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader);
782 if (IsPsdDependent) {
783 pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN;
784 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL;
785 pPsdBodyAcpiTables->NumOfProcessors = CoreCount1;
787 switch (GetComputeUnitMapping (StdHeader)) {
788 case AllCoresMapping:
789 // All cores are in their own compute unit.
790 pPsdBodyAcpiTables->DependencyDomain = LocalApicId;
791 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY;
792 pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS;
794 case EvenCoresMapping:
795 // Cores are paired in compute units.
796 pPsdBodyAcpiTables->DependencyDomain = (LocalApicId >> 1) & PSD_DOMAIN_COMPUTE_UNIT_MASK;
797 pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL;
798 pPsdBodyAcpiTables->NumOfProcessors = PSD_CORE_NUM_PER_COMPUTE_UNIT;
804 pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
805 pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
807 pPsdBodyAcpiTables++;
808 *SsdtPtr = pPsdBodyAcpiTables;
809 CurrSize += PSD_BODY_STRUCT_SIZE;
811 }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd)
812 // Typecast the pointer
814 pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables;
818 if (OptionPstateLateConfiguration.CfgPstatePpc) {
819 // Name (PPCV, value)
820 pPpcAcpiTables->NameOpcode = NAME_OPCODE;
821 pPpcAcpiTables->PpcName_a_P = PPC_NAME_P;
822 pPpcAcpiTables->PpcName_b_P = PPC_NAME_P;
823 pPpcAcpiTables->PpcName_a_C = PPC_NAME_C;
824 pPpcAcpiTables->PpcName_a_V = PPC_NAME_V;
825 pPpcAcpiTables->Value1 = PPC_VALUE1;
826 pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport;
827 // Method (_PPC) { return (PPCV) }
828 pPpcAcpiTables->MethodOpcode = METHOD_OPCODE;
829 pPpcAcpiTables->PpcLength = PPC_METHOD_LENGTH;
830 pPpcAcpiTables->PpcName_a__ = PPC_NAME__;
831 pPpcAcpiTables->PpcName_c_P = PPC_NAME_P;
832 pPpcAcpiTables->PpcName_d_P = PPC_NAME_P;
833 pPpcAcpiTables->PpcName_b_C = PPC_NAME_C;
834 pPpcAcpiTables->MethodFlags = PPC_METHOD_FLAGS;
835 pPpcAcpiTables->ReturnOpcode = RETURN_OPCODE;
836 pPpcAcpiTables->PpcName_e_P = PPC_NAME_P;
837 pPpcAcpiTables->PpcName_f_P = PPC_NAME_P;
838 pPpcAcpiTables->PpcName_c_C = PPC_NAME_C;
839 pPpcAcpiTables->PpcName_b_V = PPC_NAME_V;
841 CurrSize += PPC_HEADER_BODY_STRUCT_SIZE;
842 // Increment and typecast the pointer
844 *SsdtPtr = pPpcAcpiTables;
845 }// end of OptionPstateLateConfiguration.CfgPstatePpc
850 /**--------------------------------------------------------------------------------------
852 * CreateCStateAcpiTables
855 * This is the common routine for creating ACPI C-State objects
858 * @param[in] PlatformConfig Platform operational characteristics; power cap
859 * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
860 * @param[in,out] SsdtPtr ACPI SSDT table pointer
861 * @param[in] LocalApicId Local Apic Id
862 * @param[in] StdHeader Handle to config for library and services
864 * @retval Size of ACPI C-States objects generated
866 *---------------------------------------------------------------------------------------
869 CreateCStateAcpiTables (
870 IN PLATFORM_CONFIGURATION *PlatformConfig,
871 IN PSTATE_LEVELING *PStateLevelingBuffer,
872 IN OUT VOID **SsdtPtr,
873 IN UINT8 LocalApicId,
874 IN AMD_CONFIG_PARAMS *StdHeader
878 IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
882 if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
883 GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader);
884 // If we're supporting multiple families, only proceed when IO Cstate family services are available
885 if (IoCstateFamilyServices != NULL) {
886 IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader);
887 ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);