diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuPstateTables.c')
-rwxr-xr-x | src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuPstateTables.c | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuPstateTables.c b/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuPstateTables.c new file mode 100755 index 0000000000..ed4eb02144 --- /dev/null +++ b/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuPstateTables.c @@ -0,0 +1,821 @@ +/** + * @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: 44323 $ @e \$Date: 2010-12-22 01:24:58 -0700 (Wed, 22 Dec 2010) $ + * + */ +/***************************************************************************** + * + * Copyright (c) 2011, 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 "cpuC6State.h" +#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 C6FamilyServiceTable; + +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 + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +AGESA_STATUS +PStateLevelingMain ( + IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr, + IN AMD_CONFIG_PARAMS *StdHeader + ); +AGESA_STATUS +CreateAcpiTablesMain ( + IN AMD_CONFIG_PARAMS *StdHeader, + IN PLATFORM_CONFIGURATION *PlatformConfig, + IN OUT VOID **SsdtPtr + ); +AGESA_STATUS +CreateAcpiTablesStub ( + 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 + * + *--------------------------------------------------------------------------------------- + */ +STATIC UINT32 +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 CstObjSize; + PSTATE_LEVELING *PStateLevelingBufferStructPtr; + C6_FAMILY_SERVICES *C6FamilyServices; + + ScopeSize = sizeof (ACPI_TABLE_HEADER); + CstObjSize = 0; + C6FamilyServices = NULL; + + PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc; + MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem; + + if (IsFeatureEnabled (C6Cstate, PlatformConfig, StdHeader)) { + GetFeatureServicesOfCurrentCore (&C6FamilyServiceTable, (CONST VOID **)&C6FamilyServices, StdHeader); + CstObjSize = C6FamilyServices->GetAcpiCstObj (); + } + + for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) { + MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode; + for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) { + MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1; + 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) + (SCOPE_STRUCT_SIZE - 1) + + CstObjSize; + + } + 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; +} + +/** + *--------------------------------------------------------------------------------------- + * + * CreateAcpiTables + * + * Description: + * This function will populate the ACPI PState tables + * 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 table pointer + * + * @retval AGESA_STATUS + * + *--------------------------------------------------------------------------------------- + */ +AGESA_STATUS +CreateAcpiTables ( + IN AMD_CONFIG_PARAMS *StdHeader, + IN PLATFORM_CONFIGURATION *PlatformConfig, + IN OUT VOID **SsdtPtr + ) +{ + AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader); + return ((*(OptionPstateLateConfiguration.PstateFeature)) (StdHeader, PlatformConfig, SsdtPtr)); + // Note: Split config struct into PEI/DXE halves. This one is DXE. +} + +/**-------------------------------------------------------------------------------------- + * + * CreateAcpiTablesStub + * + * Description: + * This is the default routine for use when the PState 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 +CreateAcpiTablesStub ( + IN AMD_CONFIG_PARAMS *StdHeader, + IN PLATFORM_CONFIGURATION *PlatformConfig, + IN OUT VOID **SsdtPtr + ) +{ + return AGESA_UNSUPPORTED; +} + +/**-------------------------------------------------------------------------------------- + * + * CreateAcpiTablesMain + * + * Description: + * This is the common routine for creating the ACPI information tables. + * + * 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 +CreateAcpiTablesMain ( + IN AMD_CONFIG_PARAMS *StdHeader, + IN PLATFORM_CONFIGURATION *PlatformConfig, + IN OUT VOID **SsdtPtr + ) +{ + UINT32 i; + UINT32 j; + UINT32 k; + UINT32 TempVar8_a; + UINT32 PStateCount; + UINT32 CoreCount; + UINT32 CoreCount1; + UINT32 SocketCount; + UINT32 ScopeSize; + UINT32 TempVar_a; + UINT32 TempVar_b; + UINT32 TempVar_c; + UINT32 TempVar_d; + PCI_ADDR PciAddress; + UINT32 TransAndBusMastLatency; + UINT32 MaxCorePerNode; + UINT8 PStateMaxValueOnCurrentCore; + UINT8 *IntermediatePtr; + PSTATE_LEVELING *PStateLevelingBufferStructPtr; + AMD_CONFIG_PARAMS *AmdConfigParamsStructPtr; + SCOPE *ScopeAcpiTablesStructPtr; + SCOPE *ScopeAcpiTablesStructPtrTemp; + 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 *pPpcHeaderBodyAcpiTables; + AGESA_BUFFER_PARAMS AgesaBuffer; + LOCATE_HEAP_PTR LocateHeapParams; + S_CPU_AMD_PSTATE *AmdPstatePtr; + BOOLEAN PstateCapEnable; + UINT32 PstateCapInputMilliWatts; + UINT8 PstateCapLevelSupport; + BOOLEAN PstateCapLevelSupportDetermined; + UINT8 LocalApicId; + AGESA_STATUS AgesaStatus; + AGESA_STATUS IgnoredStatus; + CPU_SPECIFIC_SERVICES *FamilySpecificServices; + PSTATE_CPU_FAMILY_SERVICES *FamilyServices; + BOOLEAN IsPsdDependent; + C6_FAMILY_SERVICES *C6FamilyServices; + // + //Initialize local variables + // + AmdConfigParamsStructPtr = StdHeader; + PstateCapEnable = FALSE; + PstateCapInputMilliWatts = PlatformConfig->PowerCeiling; + PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP; + PstateCapLevelSupportDetermined = TRUE; + LocalApicId = 0; + AgesaStatus = AGESA_SUCCESS; + TempVar_c = 0; + ScopeAcpiTablesStructPtrTemp = NULL; + TransAndBusMastLatency = 0; + PStateCount = 0; + IsPsdDependent = !(PlatformConfig->ForcePstateIndependent); + FamilyServices = NULL; + C6FamilyServices = NULL; + + ASSERT (IsBsp (StdHeader, &IgnoredStatus)); + + // + //Locate P-state gathered data heap. + // + 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; + + // + // Check if we need to create ACPI tables + // + if (PStateLevelingBufferStructPtr[0].CreateAcpiTables == 0) { + return AGESA_UNSUPPORTED; + } + + // + //Allocate rough buffer for AcpiTable, if AcpiPstateBufferPtr is NULL + // + if (*SsdtPtr == NULL) { + AgesaBuffer.StdHeader = *StdHeader; + // + //Do not know the actual size.. pre-calculate it. + // + AgesaBuffer.BufferLength = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader); + AgesaBuffer.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE; + + AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader); + if (AgesaAllocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) { + return AGESA_ERROR; + } + AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader); + *SsdtPtr = AgesaBuffer.BufferPointer; + } + + //SSDT header + LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader); + + IntermediatePtr = (UINT8 *) *SsdtPtr; + ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)]; + + SocketCount = AmdPstatePtr->TotalSocketInSystem; + + // Initialize data variables + ScopeSize = 0; + CoreCount = 0; + for (i = 0; i < SocketCount; i++) { + + MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode; + + for (j = 0; j < MaxCorePerNode; j++) { + + // + //Check Pstate Capability enable + // + if (PstateCapInputMilliWatts != 0) { + PstateCapEnable = TRUE; + PstateCapLevelSupportDetermined = FALSE; + } + + PStateMaxValueOnCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue; + + 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 + // + ScopeAcpiTablesStructPtr++; + pPctAcpiTables = (PCT_HEADER_BODY *) ScopeAcpiTablesStructPtr; + ScopeAcpiTablesStructPtr--; + ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr; + ScopeAcpiTablesStructPtrTemp++; + + 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; + + // Set _PSS Table - START + //------------------------ + + // Increment and then typecast the pointer + pPctAcpiTables++; + TempVar_c += PCT_STRUCT_SIZE; + + ScopeAcpiTablesStructPtrTemp = (SCOPE *) pPctAcpiTables; + } // end of OptionPstateLateConfiguration.CfgPstatePct + + pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables; + + if (OptionPstateLateConfiguration.CfgPstatePss) { + // + // Set _PSS Header + // Note: Set the 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++; + }// end of PSS Header if OptionPstateLateConfiguration.CfgPstatePss + + pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables; + + if (OptionPstateLateConfiguration.CfgPstatePss) { + // Restore the pPssHeaderAcpiTables + pPssHeaderAcpiTables--; + + // Set _PSS Body + //--------------- + PStateCount = 0; + + // + //Calculate pci address for socket only + // + GetPciAddress (StdHeader, (UINT32) PStateLevelingBufferStructPtr->SocketNumber, 0, &PciAddress, &IgnoredStatus); + TransAndBusMastLatency = 0; + GetCpuServicesOfSocket ((UINT32) PStateLevelingBufferStructPtr->SocketNumber, &FamilySpecificServices, StdHeader); + ASSERT (FamilySpecificServices != NULL); + FamilySpecificServices->GetPstateLatency (FamilySpecificServices, + PStateLevelingBufferStructPtr, + &PciAddress, + &TransAndBusMastLatency, + StdHeader); + + for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { + if (PStateLevelingBufferStructPtr->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 = + PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq; + + pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; + + pPssBodyAcpiTables->Power = + PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].Power; + + if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) { + PstateCapLevelSupport = (UINT8) k; + 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 = k; + pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE; + pPssBodyAcpiTables->Status = k; + + 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; + if (TempVar_a > 63) { + TempVar_b = TempVar_a; + TempVar_d = ((TempVar_b << 4) & 0x0000FF00); + TempVar_d = TempVar_d | ((TempVar_b & 0x0000000F) | 0x00000040); + TempVar_a = (UINT16) TempVar_d; + } + + pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a; + pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PStateCount; + TempVar_c += (PSS_HEADER_STRUCT_SIZE + (PStateCount * PSS_BODY_STRUCT_SIZE)); + + ScopeAcpiTablesStructPtrTemp = (SCOPE *) pPssBodyAcpiTables; + } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss + + // + // Set XPSS Table - START + //------------------------ + // Typecast the pointer + pXpssHeaderAcpiTables = (XPSS_HEADER *) 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++; + }//end of XPSS header if OptionPstateLateConfiguration.CfgPstateXpss + + pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables; + + if (OptionPstateLateConfiguration.CfgPstateXpss) { + // Restore the pXpssHeaderAcpiTables + pXpssHeaderAcpiTables--; + + // Set XPSS Body + //--------------- + for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) { + if (PStateLevelingBufferStructPtr->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 = + PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq; + + pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; + + pXpssBodyAcpiTables->Power = + PStateLevelingBufferStructPtr->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 = k; + pXpssBodyAcpiTables->ControlHi = 0; + pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER; + pXpssBodyAcpiTables->StatusLo = k; + 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; + if (TempVar_a > 63) { + TempVar_b = TempVar_a; + TempVar_d = ((TempVar_b << 4) & 0x0000FF00); + TempVar_d = TempVar_d | ((TempVar_b & 0x0000000F) | 0x00000040); + TempVar_a = (UINT16) TempVar_d; + } + + pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a; + pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PStateCount; + TempVar_c += (XPSS_HEADER_STRUCT_SIZE + (PStateCount * XPSS_BODY_STRUCT_SIZE)); + + ScopeAcpiTablesStructPtrTemp = (SCOPE *) pXpssBodyAcpiTables; + } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss + + // + // Set _PSD Table - START + //------------------------ + // Typecast the pointer + pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables; + + // + // Get Total Cores Per Node + /// @todo Maybe this should ask for single core Sockets not single core nodes? + if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBufferStructPtr->SocketNumber, &CoreCount1, AmdConfigParamsStructPtr)) { + if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd)) { + // + // Set _PSD Header + //----------------- + pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE; + pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE; + pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH; + pPsdHeaderAcpiTables->Value1 = PSD_VALUE1; + + // Set _PSD Header + 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++; + TempVar_c += PSD_HEADER_STRUCT_SIZE; + } // end of PSD Header if (CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) + } + pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables; + + if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd)) { + 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; + // + //Get ApicId from AMD CPU general service. + //Basically, DependencyDomain should be LocalApicId for each core PSD independent. + // + GetApicId (StdHeader, (UINT32) PStateLevelingBufferStructPtr->SocketNumber, j, &LocalApicId, &AgesaStatus); + + GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader); + if (FamilyServices != NULL) { + IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader); + } + + if (IsPsdDependent) { + pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN; + pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL; + pPsdBodyAcpiTables->NumOfProcessors = CoreCount1; + } else { + pPsdBodyAcpiTables->DependencyDomain = LocalApicId; + pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY; + pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS; + } + + pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE; + pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE; + + pPsdBodyAcpiTables++; + ScopeAcpiTablesStructPtrTemp = (SCOPE *) pPsdBodyAcpiTables; + TempVar_c += PSD_BODY_STRUCT_SIZE; + }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd) + + // + // Set _PPC Table - START + //------------------------ + + // Typecast the pointer + + pPpcHeaderBodyAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables; + + // Set _PPC Header and Body + //-------------------------- + if (OptionPstateLateConfiguration.CfgPstatePpc) { + pPpcHeaderBodyAcpiTables->NameOpcode = NAME_OPCODE; + pPpcHeaderBodyAcpiTables->PpcName_a__ = PPC_NAME__; + pPpcHeaderBodyAcpiTables->PpcName_a_P = PPC_NAME_P; + pPpcHeaderBodyAcpiTables->PpcName_b_P = PPC_NAME_P; + pPpcHeaderBodyAcpiTables->PpcName_a_C = PPC_NAME_C; + pPpcHeaderBodyAcpiTables->Value1 = PPC_VALUE1; + + pPpcHeaderBodyAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport; + TempVar_c += PPC_HEADER_BODY_STRUCT_SIZE; + // Increment and typecast the pointer + pPpcHeaderBodyAcpiTables++; + ScopeAcpiTablesStructPtrTemp = (SCOPE *) pPpcHeaderBodyAcpiTables; + }// end of OptionPstateLateConfiguration.CfgPstatePpc + + // If C6 is enabled, generate the corresponding ACPI object for it + if (IsFeatureEnabled (C6Cstate, PlatformConfig, StdHeader)) { + GetFeatureServicesOfCurrentCore (&C6FamilyServiceTable, (CONST VOID **)&C6FamilyServices, StdHeader); + C6FamilyServices->CreateAcpiCstObj ((VOID *) &ScopeAcpiTablesStructPtrTemp, StdHeader); + TempVar_c += C6FamilyServices->GetAcpiCstObj (); + } + + // + // Now update the SCOPE Length field + // + { + TempVar_c += (SCOPE_STRUCT_SIZE - 1); + ScopeSize += TempVar_c; + + TempVar_d = ((TempVar_c << 4) & 0x0000FF00); + TempVar_d |= ((TempVar_c & 0x0000000F) | 0x00000040); + TempVar_a = TempVar_d; + ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a; + TempVar_c = 0; + } + + // Increment and typecast the pointer + ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp; + + } // for (j = 0; j < MPPSTATE_MAX_CORES_PER_NODE; j++) + + // + //Calculate next node buffer address + // + PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES))); + + } // for (i = 0; i < NodeCount; i++) + + //Update SSDT header Checksum + ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER)); + ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader); + + return AGESA_SUCCESS; +} + + + |