| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * AMD PSTATE, ACPI table related API functions. |
| * |
| * Contains code that generates the _PSS, _PCT, and other ACPI tables. |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: CPU |
| * @e \$Revision: 55600 $ @e \$Date: 2011-06-23 12:39:18 -0600 (Thu, 23 Jun 2011) $ |
| * |
| */ |
| /***************************************************************************** |
| * |
| * Copyright (C) 2012 Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| ****************************************************************************** |
| */ |
| |
| |
| /* |
| *---------------------------------------------------------------------------- |
| * MODULES USED |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "amdlib.h" |
| #include "OptionPstate.h" |
| #include "cpuLateInit.h" |
| #include "cpuRegisters.h" |
| #include "cpuFamilyTranslation.h" |
| #include "GeneralServices.h" |
| #include "cpuServices.h" |
| #include "heapManager.h" |
| #include "Ids.h" |
| #include "Filecode.h" |
| #include "GeneralServices.h" |
| #include "cpuPstateTables.h" |
| #include "cpuFeatures.h" |
| #include "cpuIoCstate.h" |
| CODE_GROUP (G3_DXE) |
| RDATA_GROUP (G3_DXE) |
| |
| #define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE |
| /*---------------------------------------------------------------------------- |
| * DEFINITIONS AND MACROS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| extern OPTION_PSTATE_LATE_CONFIGURATION OptionPstateLateConfiguration; // global user config record |
| extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable; |
| extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable; |
| |
| STATIC ACPI_TABLE_HEADER ROMDATA CpuSsdtHdrStruct = |
| { |
| {'S','S','D','T'}, |
| 0, |
| 1, |
| 0, |
| {'A','M','D',' ',' ',' '}, |
| {'P','O','W','E','R','N','O','W'}, |
| 1, |
| {'A','M','D',' '}, |
| 1 |
| }; |
| |
| |
| /*---------------------------------------------------------------------------- |
| * TYPEDEFS AND STRUCTURES |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------- |
| * PROTOTYPES OF LOCAL FUNCTIONS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| UINT32 |
| STATIC |
| CalAcpiTablesSize ( |
| IN S_CPU_AMD_PSTATE *AmdPstatePtr, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ); |
| |
| AGESA_STATUS |
| GenerateSsdtStub ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN OUT VOID **SsdtPtr |
| ); |
| |
| UINT32 |
| CreateAcpiTablesStub ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ); |
| |
| UINT32 |
| CreatePStateAcpiTables ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ); |
| |
| UINT32 |
| CreateCStateAcpiTables ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ); |
| |
| AGESA_STATUS |
| GenerateSsdt ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN OUT VOID **SsdtPtr |
| ); |
| |
| /** |
| *--------------------------------------------------------------------------------------- |
| * |
| * CalAcpiTablesSize |
| * |
| * Description: |
| * This function will calculate the size of ACPI PState tables |
| * |
| * Parameters: |
| * @param[in] *AmdPstatePtr |
| * @param[in] *PlatformConfig |
| * @param[in] *StdHeader |
| * |
| * @retval UINT32 |
| * |
| *--------------------------------------------------------------------------------------- |
| */ |
| UINT32 |
| STATIC |
| CalAcpiTablesSize ( |
| IN S_CPU_AMD_PSTATE *AmdPstatePtr, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT32 ScopeSize; |
| UINT32 CoreCount; |
| UINT32 SocketCount; |
| UINT32 MaxCoreNumberInCurrentSocket; |
| UINT32 MaxSocketNumberInSystem; |
| UINT32 MaxPstateNumberInCurrentCore; |
| UINT32 CstateAcpiObjSize; |
| PSTATE_LEVELING *PStateLevelingBufferStructPtr; |
| IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices; |
| |
| ScopeSize = sizeof (ACPI_TABLE_HEADER); |
| CstateAcpiObjSize = 0; |
| IoCstateFamilyServices = NULL; |
| |
| PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc; |
| MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem; |
| |
| if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) { |
| GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader); |
| // If we're supporting multiple families, only proceed when IO Cstate family services are available |
| if (IoCstateFamilyServices != NULL) { |
| CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader); |
| } |
| } |
| |
| for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) { |
| MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode; |
| for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) { |
| MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1; |
| |
| ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core |
| ScopeSize += CstateAcpiObjSize; // C-State ACPI objects size per core |
| |
| // Add P-State ACPI Objects size per core |
| if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) { |
| ScopeSize += (PCT_STRUCT_SIZE + |
| PSS_HEADER_STRUCT_SIZE + |
| (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) + |
| XPSS_HEADER_STRUCT_SIZE + |
| (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) + |
| PSD_HEADER_STRUCT_SIZE + |
| PSD_BODY_STRUCT_SIZE + |
| PPC_HEADER_BODY_STRUCT_SIZE); |
| } |
| } |
| ScopeSize += MaxCoreNumberInCurrentSocket; |
| PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES))); |
| } |
| AmdPstatePtr->SizeOfBytes = ScopeSize; |
| |
| return ScopeSize; |
| } |
| |
| /**-------------------------------------------------------------------------------------- |
| * |
| * GenerateSsdtStub |
| * |
| * Description: |
| * This is the default routine for use when both PState and CState option is NOT |
| * requested. The option install process will create and fill the transfer vector |
| * with the address of the proper routine (Main or Stub). The link optimizer will |
| * strip out of the .DLL the routine that is not used. |
| * |
| * Parameters: |
| * @param[in] StdHeader Handle to config for library and services |
| * @param[in] PlatformConfig Contains the power cap parameter |
| * @param[in,out] SsdtPtr ACPI SSDT table pointer |
| * |
| * @retval AGESA_STATUS |
| * |
| *--------------------------------------------------------------------------------------- |
| **/ |
| AGESA_STATUS |
| GenerateSsdtStub ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN OUT VOID **SsdtPtr |
| ) |
| { |
| return AGESA_UNSUPPORTED; |
| } |
| |
| /** |
| *--------------------------------------------------------------------------------------- |
| * |
| * GenerateSsdt |
| * |
| * Description: |
| * This function will populate the SSDT with ACPI P-States and C-States Objects, whenever |
| * necessary |
| * This function should be called only from BSP |
| * |
| * Parameters: |
| * @param[in] StdHeader Handle to config for library and services |
| * @param[in] PlatformConfig Contains the power cap parameter |
| * @param[in,out] SsdtPtr ACPI SSDT pointer |
| * |
| * @retval AGESA_STATUS |
| * |
| *--------------------------------------------------------------------------------------- |
| */ |
| AGESA_STATUS |
| GenerateSsdt ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN OUT VOID **SsdtPtr |
| ) |
| { |
| UINT32 i; |
| UINT32 j; |
| UINT32 TempVar8_a; |
| UINT32 CurrSize; |
| UINT32 TempVar_a; |
| UINT32 TempVar_b; |
| UINT32 ScopeSize; |
| UINT32 CoreCount; |
| UINT32 SocketCount; |
| UINT32 MaxCorePerNode; |
| UINT8 LocalApicId; |
| UINT8 *IntermediatePtr; |
| AGESA_STATUS AgesaStatus; |
| LOCATE_HEAP_PTR LocateHeapParams; |
| ALLOCATE_HEAP_PARAMS AllocateHeapParams; |
| S_CPU_AMD_PSTATE *AmdPstatePtr; |
| PSTATE_LEVELING *PStateLevelingBufferStructPtr; |
| SCOPE *ScopeAcpiTablesStructPtr; |
| SCOPE *ScopeAcpiTablesStructPtrTemp; |
| |
| AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader); |
| |
| ASSERT (IsBsp (StdHeader, &AgesaStatus)); |
| |
| // If P-State and C-State ACPI tables do not need to be generated, exit this routine |
| if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) { |
| AgesaStatus = AGESA_UNSUPPORTED; |
| return AgesaStatus; |
| } |
| |
| // Initialize data variables |
| ScopeSize = 0; |
| CoreCount = 0; |
| LocalApicId = 0; |
| CurrSize = 0; |
| |
| // Locate P-State data buffer |
| LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE; |
| AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader); |
| if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) { |
| return AGESA_ERROR; |
| } |
| AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader); |
| |
| AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr; |
| PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc; |
| |
| // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL |
| if (*SsdtPtr == NULL) { |
| //Do not know the actual size.. pre-calculate it. |
| AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader); |
| AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE; |
| AllocateHeapParams.Persist = HEAP_SYSTEM_MEM; |
| |
| AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader); |
| if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) { |
| return AGESA_ERROR; |
| } |
| AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader); |
| *SsdtPtr = AllocateHeapParams.BufferPtr; |
| } |
| |
| IDS_HDT_CONSOLE (CPU_TRACE, " SSDT is created\n"); |
| |
| // Copy SSDT header into allocated buffer |
| LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader); |
| IntermediatePtr = (UINT8 *) *SsdtPtr; |
| ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)]; |
| |
| SocketCount = AmdPstatePtr->TotalSocketInSystem; |
| |
| // Generate name scope and ACPI objects for every core in the system |
| for (i = 0; i < SocketCount; i++) { |
| MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode; |
| for (j = 0; j < MaxCorePerNode; j++) { |
| CoreCount++; |
| // Set Name Scope for CPU0, 1, 2, ..... n |
| // CPU0 to CPUn will name as C000 to Cnnn |
| // ----------------------------------------- |
| ScopeAcpiTablesStructPtr->ScopeOpcode = SCOPE_OPCODE; |
| // This value will be filled at the end of this function |
| // Since at this time, we don't know how many Pstates we |
| // would have |
| ScopeAcpiTablesStructPtr->ScopeLength = 0; |
| ScopeAcpiTablesStructPtr->ScopeValue1 = SCOPE_VALUE1; |
| ScopeAcpiTablesStructPtr->ScopeValue2 = SCOPE_VALUE2; |
| ScopeAcpiTablesStructPtr->ScopeNamePt1a__ = SCOPE_NAME__; |
| if (PlatformConfig->ProcessorScopeInSb) { |
| ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_S; |
| ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_B; |
| } else { |
| ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_P; |
| ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_R; |
| } |
| ScopeAcpiTablesStructPtr->ScopeNamePt1b__ = SCOPE_NAME__; |
| ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z')) |
| ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \ |
| ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \ |
| (PlatformConfig->ProcessorScopeName1 == '_')) |
| |
| ScopeAcpiTablesStructPtr->ScopeNamePt2a_C = PlatformConfig->ProcessorScopeName0; |
| ScopeAcpiTablesStructPtr->ScopeNamePt2a_P = PlatformConfig->ProcessorScopeName1; |
| |
| TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F; |
| ScopeAcpiTablesStructPtr->ScopeNamePt2a_U = (UINT8) (SCOPE_NAME_0 + TempVar8_a); |
| |
| TempVar8_a = (CoreCount - 1) & 0x0F; |
| if (TempVar8_a < 0xA) { |
| ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_0 + TempVar8_a); |
| } else { |
| ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA); |
| } |
| // Increment and typecast the pointer |
| ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr; |
| ScopeAcpiTablesStructPtrTemp++; |
| |
| // Get the Local Apic Id for each core |
| LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j; |
| |
| // Create P-State ACPI Objects |
| CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader)); |
| |
| // Create C-State ACPI Objects |
| CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader)); |
| |
| // Now update the SCOPE Length field |
| { |
| CurrSize += (SCOPE_STRUCT_SIZE - 1); |
| ScopeSize += CurrSize; |
| |
| TempVar_b = ((CurrSize << 4) & 0x0000FF00); |
| TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040); |
| TempVar_a = TempVar_b; |
| ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a; |
| CurrSize = 0; |
| } |
| |
| ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp; |
| } |
| //Calculate next node buffer address |
| PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES))); |
| } |
| //Update SSDT header Checksum |
| ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER)); |
| ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader); |
| |
| return AGESA_SUCCESS; |
| } |
| |
| /**-------------------------------------------------------------------------------------- |
| * |
| * CreateAcpiTablesStub |
| * |
| * Description: |
| * This is the default routine for use when the P-State or C-State option is NOT |
| * requested. The option install process will create and fill the transfer vector |
| * with the address of the proper routine (Main or Stub). The link optimizer will |
| * strip out of the .DLL the routine that is not used. |
| * |
| * Parameters: |
| * @param[in] PlatformConfig Platform operational characteristics; power cap |
| * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information |
| * @param[in,out] SsdtPtr ACPI SSDT table pointer |
| * @param[in] LocalApicId Local Apic Id |
| * @param[in] StdHeader Handle to config for library and services |
| * |
| * @retval Size of generated ACPI objects |
| * |
| *--------------------------------------------------------------------------------------- |
| **/ |
| UINT32 |
| CreateAcpiTablesStub ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| return 0; |
| } |
| |
| |
| /**-------------------------------------------------------------------------------------- |
| * |
| * CreatePStateAcpiTables |
| * |
| * Description: |
| * This is the common routine for creating ACPI P-State objects |
| * |
| * Parameters: |
| * @param[in] PlatformConfig Platform operational characteristics; power cap |
| * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information |
| * @param[in,out] SsdtPtr ACPI SSDT table pointer |
| * @param[in] LocalApicId Local Apic Id |
| * @param[in] StdHeader Handle to config for library and services |
| * |
| * @retval Size of generated ACPI P-States objects |
| * |
| *--------------------------------------------------------------------------------------- |
| **/ |
| UINT32 |
| CreatePStateAcpiTables ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 PstateCapLevelSupport; |
| UINT8 PStateMaxValueOnCurrentCore; |
| BOOLEAN PstateCapEnable; |
| BOOLEAN PstateCapLevelSupportDetermined; |
| BOOLEAN IsPsdDependent; |
| UINT32 k; |
| UINT32 TempVar_a; |
| UINT32 TempVar_b; |
| UINT32 TempVar_c; |
| UINT32 PstateCapInputMilliWatts; |
| UINT32 CurrSize; |
| UINT32 PstateCount; |
| UINT32 CoreCount1; |
| UINT32 TransAndBusMastLatency; |
| AGESA_STATUS IgnoredStatus; |
| PCI_ADDR PciAddress; |
| PCT_HEADER_BODY *pPctAcpiTables; |
| PSS_HEADER *pPssHeaderAcpiTables; |
| PSS_BODY *pPssBodyAcpiTables; |
| XPSS_HEADER *pXpssHeaderAcpiTables; |
| XPSS_BODY *pXpssBodyAcpiTables; |
| PSD_HEADER *pPsdHeaderAcpiTables; |
| PSD_BODY *pPsdBodyAcpiTables; |
| PPC_HEADER_BODY *pPpcAcpiTables; |
| PSTATE_CPU_FAMILY_SERVICES *FamilyServices; |
| |
| CurrSize = 0; |
| PstateCount = 0; |
| PstateCapEnable = FALSE; |
| PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP; |
| PstateCapLevelSupportDetermined = TRUE; |
| PstateCapInputMilliWatts = PlatformConfig->PowerCeiling; |
| IsPsdDependent = !(PlatformConfig->ForcePstateIndependent); |
| TransAndBusMastLatency = 0; |
| |
| if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) { |
| pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr; |
| |
| //Check Pstate Capability |
| if (PstateCapInputMilliWatts != 0) { |
| PstateCapEnable = TRUE; |
| PstateCapLevelSupportDetermined = FALSE; |
| } |
| |
| PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue; |
| if (OptionPstateLateConfiguration.CfgPstatePct) { |
| // Set _PCT Table |
| // -------------- |
| pPctAcpiTables->NameOpcode = NAME_OPCODE; |
| pPctAcpiTables->PctName_a__ = PCT_NAME__; |
| pPctAcpiTables->PctName_a_P = PCT_NAME_P; |
| pPctAcpiTables->PctName_a_C = PCT_NAME_C; |
| pPctAcpiTables->PctName_a_T = PCT_NAME_T; |
| pPctAcpiTables->Value1 = PCT_VALUE1; |
| pPctAcpiTables->Value2 = PCT_VALUE2; |
| pPctAcpiTables->Value3 = PCT_VALUE3; |
| pPctAcpiTables->GenericRegDescription1 = GENERIC_REG_DESCRIPTION; |
| pPctAcpiTables->Length1 = PCT_LENGTH; |
| pPctAcpiTables->AddressSpaceId1 = PCT_ADDRESS_SPACE_ID; |
| pPctAcpiTables->RegisterBitWidth1 = PCT_REGISTER_BIT_WIDTH; |
| pPctAcpiTables->RegisterBitOffset1 = PCT_REGISTER_BIT_OFFSET; |
| pPctAcpiTables->Reserved1 = PCT_RESERVED; |
| pPctAcpiTables->ControlRegAddressLo = PCT_CONTROL_REG_LO; |
| pPctAcpiTables->ControlRegAddressHi = PCT_CONTROL_REG_HI; |
| pPctAcpiTables->Value4 = PCT_VALUE4; |
| pPctAcpiTables->Value5 = PCT_VALUE5; |
| pPctAcpiTables->GenericRegDescription2 = GENERIC_REG_DESCRIPTION; |
| pPctAcpiTables->Length2 = PCT_LENGTH; |
| pPctAcpiTables->AddressSpaceId2 = PCT_ADDRESS_SPACE_ID; |
| pPctAcpiTables->RegisterBitWidth2 = PCT_REGISTER_BIT_WIDTH; |
| pPctAcpiTables->RegisterBitOffset2 = PCT_REGISTER_BIT_OFFSET; |
| pPctAcpiTables->Reserved2 = PCT_RESERVED; |
| pPctAcpiTables->StatusRegAddressLo = PCT_STATUS_REG_LO; |
| pPctAcpiTables->StatusRegAddressHi = PCT_STATUS_REG_HI; |
| pPctAcpiTables->Value6 = PCT_VALUE6; |
| |
| // Increment and then typecast the pointer |
| pPctAcpiTables++; |
| CurrSize += PCT_STRUCT_SIZE; |
| |
| *SsdtPtr = pPctAcpiTables; |
| } // end of OptionPstateLateConfiguration.CfgPstatePct |
| |
| pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables; |
| pPssBodyAcpiTables = (PSS_BODY *) pPctAcpiTables; |
| if (OptionPstateLateConfiguration.CfgPstatePss) { |
| // Set _PSS Header |
| // Note: Set pssLength and numOfItemsInPss later |
| //--------------------------------------------------- |
| pPssHeaderAcpiTables->NameOpcode = NAME_OPCODE; |
| pPssHeaderAcpiTables->PssName_a__ = PSS_NAME__; |
| pPssHeaderAcpiTables->PssName_a_P = PSS_NAME_P; |
| pPssHeaderAcpiTables->PssName_a_S = PSS_NAME_S; |
| pPssHeaderAcpiTables->PssName_b_S = PSS_NAME_S; |
| pPssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| |
| pPssHeaderAcpiTables++; |
| pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables; |
| // Restore the pPssHeaderAcpiTables |
| pPssHeaderAcpiTables--; |
| |
| // Set _PSS Body |
| //--------------- |
| PstateCount = 0; |
| |
| // Calculate PCI address for socket only |
| GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus); |
| TransAndBusMastLatency = 0; |
| GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader); |
| ASSERT (FamilyServices != NULL) |
| FamilyServices->GetPstateLatency ( FamilyServices, |
| PStateLevelingBuffer, |
| &PciAddress, |
| &TransAndBusMastLatency, |
| StdHeader); |
| |
| for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { |
| if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) { |
| pPssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| pPssBodyAcpiTables->PkgLength = PSS_PKG_LENGTH; |
| pPssBodyAcpiTables->NumOfElements = PSS_NUM_OF_ELEMENTS; |
| pPssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->Frequency = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq; |
| pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->Power = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power; |
| |
| if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) { |
| PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; |
| PstateCapLevelSupportDetermined = TRUE; |
| } |
| |
| pPssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency; |
| pPssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency; |
| pPssBodyAcpiTables->DwordPrefixOpcode5 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->Control = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; |
| pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE; |
| pPssBodyAcpiTables->Status = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; |
| |
| pPssBodyAcpiTables++; |
| PstateCount++; |
| } |
| } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++) |
| |
| if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) { |
| PstateCapLevelSupport = PStateMaxValueOnCurrentCore; |
| } |
| |
| // Set _PSS Header again |
| // Now Set pssLength and numOfItemsInPss |
| //--------------------------------------- |
| TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3; |
| TempVar_b = TempVar_a; |
| TempVar_c = ((TempVar_b << 4) & 0x0000FF00); |
| TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040); |
| TempVar_a = (UINT16) TempVar_c; |
| |
| pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a; |
| pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount; |
| CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE)); |
| |
| *SsdtPtr = pPssBodyAcpiTables; |
| } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss |
| |
| // Set XPSS Table |
| //--------------- |
| // Typecast the pointer |
| pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables; |
| pXpssBodyAcpiTables = (XPSS_BODY *) pPssBodyAcpiTables; |
| if (OptionPstateLateConfiguration.CfgPstateXpss) { |
| // Set XPSS Header |
| // Note: Set the pssLength and numOfItemsInPss later |
| //--------------------------------------------------- |
| pXpssHeaderAcpiTables->NameOpcode = NAME_OPCODE; |
| pXpssHeaderAcpiTables->XpssName_a_X = PSS_NAME_X; |
| pXpssHeaderAcpiTables->XpssName_a_P = PSS_NAME_P; |
| pXpssHeaderAcpiTables->XpssName_a_S = PSS_NAME_S; |
| pXpssHeaderAcpiTables->XpssName_b_S = PSS_NAME_S; |
| pXpssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| |
| // Increment and then typecast the pointer |
| pXpssHeaderAcpiTables++; |
| pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables; |
| // Restore the pXpssHeaderAcpiTables |
| pXpssHeaderAcpiTables--; |
| |
| // Set XPSS Body |
| //--------------- |
| for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { |
| if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) { |
| pXpssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| pXpssBodyAcpiTables->PkgLength = XPSS_PKG_LENGTH; |
| pXpssBodyAcpiTables->NumOfElements = XPSS_NUM_OF_ELEMENTS; |
| pXpssBodyAcpiTables->XpssValueTbd = 04; |
| pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; |
| pXpssBodyAcpiTables->Frequency = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq; |
| pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; |
| pXpssBodyAcpiTables->Power = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power; |
| pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; |
| pXpssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency; |
| pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE; |
| pXpssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency; |
| pXpssBodyAcpiTables->ControlBuffer = XPSS_ACPI_BUFFER; |
| pXpssBodyAcpiTables->ControlLo = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; |
| pXpssBodyAcpiTables->ControlHi = 0; |
| pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER; |
| pXpssBodyAcpiTables->StatusLo = |
| PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber; |
| pXpssBodyAcpiTables->StatusHi = 0; |
| pXpssBodyAcpiTables->ControlMaskBuffer = XPSS_ACPI_BUFFER; |
| pXpssBodyAcpiTables->ControlMaskLo = 0; |
| pXpssBodyAcpiTables->ControlMaskHi = 0; |
| pXpssBodyAcpiTables->StatusMaskBuffer = XPSS_ACPI_BUFFER; |
| pXpssBodyAcpiTables->StatusMaskLo = 0; |
| pXpssBodyAcpiTables->StatusMaskHi = 0; |
| |
| pXpssBodyAcpiTables++; |
| } |
| } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++) |
| |
| // Set XPSS Header again |
| // Now set pssLength and numOfItemsInPss |
| //--------------------------------------- |
| TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3; |
| TempVar_b = TempVar_a; |
| TempVar_c = ((TempVar_b << 4) & 0x0000FF00); |
| TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040); |
| TempVar_a = (UINT16) TempVar_c; |
| |
| pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a; |
| pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount; |
| CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE)); |
| |
| *SsdtPtr = pXpssBodyAcpiTables; |
| } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss |
| |
| // Set _PSD Table |
| //--------------- |
| // Typecast the pointer |
| pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables; |
| pPsdBodyAcpiTables = (PSD_BODY *) pXpssBodyAcpiTables; |
| // Get Total Cores Per Node |
| if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) { |
| GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader); |
| ASSERT (FamilyServices != NULL) |
| if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) && |
| FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) { |
| // Set _PSD Header |
| //---------------- |
| pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE; |
| pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH; |
| pPsdHeaderAcpiTables->Value1 = PSD_VALUE1; |
| pPsdHeaderAcpiTables->PsdName_a__ = PSD_NAME__; |
| pPsdHeaderAcpiTables->PsdName_a_P = PSD_NAME_P; |
| pPsdHeaderAcpiTables->PsdName_a_S = PSD_NAME_S; |
| pPsdHeaderAcpiTables->PsdName_a_D = PSD_NAME_D; |
| |
| // Typecast the pointer |
| pPsdHeaderAcpiTables++; |
| CurrSize += PSD_HEADER_STRUCT_SIZE; |
| pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables; |
| |
| pPsdHeaderAcpiTables--; |
| // Set _PSD Body |
| //-------------- |
| pPsdBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE; |
| pPsdBodyAcpiTables->PkgLength = PSD_PKG_LENGTH; |
| pPsdBodyAcpiTables->NumOfEntries = NUM_OF_ENTRIES; |
| pPsdBodyAcpiTables->BytePrefixOpcode1 = BYTE_PREFIX_OPCODE; |
| pPsdBodyAcpiTables->PsdNumOfEntries = PSD_NUM_OF_ENTRIES; |
| pPsdBodyAcpiTables->BytePrefixOpcode2 = BYTE_PREFIX_OPCODE; |
| pPsdBodyAcpiTables->PsdRevision = PSD_REVISION; |
| pPsdBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE; |
| |
| IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader); |
| |
| if (IsPsdDependent) { |
| pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN; |
| pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL; |
| pPsdBodyAcpiTables->NumOfProcessors = CoreCount1; |
| } else { |
| switch (GetComputeUnitMapping (StdHeader)) { |
| case AllCoresMapping: |
| // All cores are in their own compute unit. |
| pPsdBodyAcpiTables->DependencyDomain = LocalApicId; |
| pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY; |
| pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS; |
| break; |
| case EvenCoresMapping: |
| // Cores are paired in compute units. |
| pPsdBodyAcpiTables->DependencyDomain = (LocalApicId >> 1) & PSD_DOMAIN_COMPUTE_UNIT_MASK; |
| pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL; |
| pPsdBodyAcpiTables->NumOfProcessors = PSD_CORE_NUM_PER_COMPUTE_UNIT; |
| break; |
| default: |
| ASSERT (FALSE); |
| } |
| } |
| pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; |
| pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; |
| |
| pPsdBodyAcpiTables++; |
| *SsdtPtr = pPsdBodyAcpiTables; |
| CurrSize += PSD_BODY_STRUCT_SIZE; |
| } |
| }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd) |
| // Typecast the pointer |
| |
| pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables; |
| |
| // Set _PPC Table |
| //--------------- |
| if (OptionPstateLateConfiguration.CfgPstatePpc) { |
| // Name (PPCV, value) |
| pPpcAcpiTables->NameOpcode = NAME_OPCODE; |
| pPpcAcpiTables->PpcName_a_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_b_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_a_C = PPC_NAME_C; |
| pPpcAcpiTables->PpcName_a_V = PPC_NAME_V; |
| pPpcAcpiTables->Value1 = PPC_VALUE1; |
| pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport; |
| // Method (_PPC) { return (PPCV) } |
| pPpcAcpiTables->MethodOpcode = METHOD_OPCODE; |
| pPpcAcpiTables->PpcLength = PPC_METHOD_LENGTH; |
| pPpcAcpiTables->PpcName_a__ = PPC_NAME__; |
| pPpcAcpiTables->PpcName_c_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_d_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_b_C = PPC_NAME_C; |
| pPpcAcpiTables->MethodFlags = PPC_METHOD_FLAGS; |
| pPpcAcpiTables->ReturnOpcode = RETURN_OPCODE; |
| pPpcAcpiTables->PpcName_e_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_f_P = PPC_NAME_P; |
| pPpcAcpiTables->PpcName_c_C = PPC_NAME_C; |
| pPpcAcpiTables->PpcName_b_V = PPC_NAME_V; |
| |
| CurrSize += PPC_HEADER_BODY_STRUCT_SIZE; |
| // Increment and typecast the pointer |
| pPpcAcpiTables++; |
| *SsdtPtr = pPpcAcpiTables; |
| }// end of OptionPstateLateConfiguration.CfgPstatePpc |
| } |
| return CurrSize; |
| } |
| |
| /**-------------------------------------------------------------------------------------- |
| * |
| * CreateCStateAcpiTables |
| * |
| * Description: |
| * This is the common routine for creating ACPI C-State objects |
| * |
| * Parameters: |
| * @param[in] PlatformConfig Platform operational characteristics; power cap |
| * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information |
| * @param[in,out] SsdtPtr ACPI SSDT table pointer |
| * @param[in] LocalApicId Local Apic Id |
| * @param[in] StdHeader Handle to config for library and services |
| * |
| * @retval Size of ACPI C-States objects generated |
| * |
| *--------------------------------------------------------------------------------------- |
| **/ |
| UINT32 |
| CreateCStateAcpiTables ( |
| IN PLATFORM_CONFIGURATION *PlatformConfig, |
| IN PSTATE_LEVELING *PStateLevelingBuffer, |
| IN OUT VOID **SsdtPtr, |
| IN UINT8 LocalApicId, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT32 ObjSize; |
| IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices; |
| |
| ObjSize = 0; |
| |
| if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) { |
| GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader); |
| // If we're supporting multiple families, only proceed when IO Cstate family services are available |
| if (IoCstateFamilyServices != NULL) { |
| IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader); |
| ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader); |
| } |
| } |
| return ObjSize; |
| } |