On Tue, Nov 21, 2023 at 17:50:06 +0100, Pierre Gondois wrote: > The SCP holds some power information that could be advertised > through the _CPC object. The communication with the SCP is done > through SCMI protocols (c.f. ArmScmiDxe). > > Use the SCMI protocols to query information and feed it to > the DynamicTablesPkg. > > Signed-off-by: Pierre Gondois <pierre.gond...@arm.com>
Acked-by: Leif Lindholm <quic_llind...@quicinc.com> / Leif > --- > DynamicTablesPkg/DynamicTables.dsc.inc | 1 + > DynamicTablesPkg/DynamicTablesPkg.dec | 3 + > DynamicTablesPkg/DynamicTablesPkg.dsc | 1 + > .../Library/DynamicTablesScmiInfoLib.h | 33 ++ > .../DynamicTablesScmiInfoLib.c | 297 ++++++++++++++++++ > .../DynamicTablesScmiInfoLib.inf | 31 ++ > 6 files changed, 366 insertions(+) > create mode 100644 > DynamicTablesPkg/Include/Library/DynamicTablesScmiInfoLib.h > create mode 100644 > DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.c > create mode 100644 > DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > > diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc > b/DynamicTablesPkg/DynamicTables.dsc.inc > index 9d4312c4e87d..41947012b92b 100644 > --- a/DynamicTablesPkg/DynamicTables.dsc.inc > +++ b/DynamicTablesPkg/DynamicTables.dsc.inc > @@ -15,6 +15,7 @@ [BuildOptions] > [LibraryClasses.common] > > AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf > AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf > + > DynamicTablesScmiInfoLib|DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > > SsdtPcieSupportLib|DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf > > SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf > > TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf > diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec > b/DynamicTablesPkg/DynamicTablesPkg.dec > index cfbcbb9569f1..aa422ce9f6fd 100644 > --- a/DynamicTablesPkg/DynamicTablesPkg.dec > +++ b/DynamicTablesPkg/DynamicTablesPkg.dec > @@ -42,6 +42,9 @@ [LibraryClasses] > ## @libraryclass Defines a set of SMBIOS string helper methods. > SmbiosStringTableLib|Include/Library/SmbiosStringTableLib.h > > + ## @libraryclass Defines a set of APIs to populate CmObj using SCMI. > + DynamicTablesScmiInfoLib|Include/Library/DynamicTablesScmiInfoLib.h > + > [Protocols] > # Configuration Manager Protocol GUID > gEdkiiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { > 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } } > diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc > b/DynamicTablesPkg/DynamicTablesPkg.dsc > index bd5084a9008f..853ea2a1e4c2 100644 > --- a/DynamicTablesPkg/DynamicTablesPkg.dsc > +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc > @@ -39,6 +39,7 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64] > PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf > > [Components.common] > + > DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf > DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf > DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf > diff --git a/DynamicTablesPkg/Include/Library/DynamicTablesScmiInfoLib.h > b/DynamicTablesPkg/Include/Library/DynamicTablesScmiInfoLib.h > new file mode 100644 > index 000000000000..ff6b47d51fe8 > --- /dev/null > +++ b/DynamicTablesPkg/Include/Library/DynamicTablesScmiInfoLib.h > @@ -0,0 +1,33 @@ > +/** @file > + Arm SCMI Info Library. > + > + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef ARM_SCMI_INFO_LIB_H_ > +#define ARM_SCMI_INFO_LIB_H_ > + > +#include <ConfigurationManagerObject.h> > + > +/** Populate a AML_CPC_INFO object based on SCMI information. > + > + @param[in] DomainId Identifier for the performance domain. > + @param[out] CpcInfo If success, this structure was populated from > + information queried to the SCP. > + > + @retval EFI_SUCCESS Success. > + @retval EFI_DEVICE_ERROR Device error. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_TIMEOUT Time out. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +EFI_STATUS > +EFIAPI > +DynamicTablesScmiInfoGetFastChannel ( > + IN UINT32 DomainId, > + OUT AML_CPC_INFO *CpcInfo > + ); > + > +#endif // ARM_SCMI_INFO_LIB_H_ > diff --git > a/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.c > > b/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.c > new file mode 100644 > index 000000000000..b59da3d6bb51 > --- /dev/null > +++ > b/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.c > @@ -0,0 +1,297 @@ > +/** @file > + Arm SCMI Info Library. > + > + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> > + > + Arm Functional Fixed Hardware Specification: > + - https://developer.arm.com/documentation/den0048/latest/ > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include <Library/AcpiLib.h> > +#include <Library/DynamicTablesScmiInfoLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Protocol/ArmScmi.h> > +#include <Protocol/ArmScmiPerformanceProtocol.h> > + > +/** Arm FFH registers > + > + Cf. Arm Functional Fixed Hardware Specification > + s3.2 Performance management and Collaborative Processor Performance Control > +*/ > +#define ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER 0x0 > +#define ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER 0x1 > + > +/// Arm SCMI performance protocol. > +STATIC SCMI_PERFORMANCE_PROTOCOL *ScmiPerfProtocol; > + > +/** Arm SCMI Info Library constructor. > + > + @param ImageHandle Image of the loaded driver. > + @param SystemTable Pointer to the System Table. > + > + @retval EFI_SUCCESS Success. > + @retval EFI_DEVICE_ERROR Device error. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not Found > + @retval EFI_TIMEOUT Timeout. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +EFI_STATUS > +EFIAPI > +DynamicTablesScmiInfoLibConstructor ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + UINT32 Version; > + > + Status = gBS->LocateProtocol ( > + &gArmScmiPerformanceProtocolGuid, > + NULL, > + (VOID **)&ScmiPerfProtocol > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiPerfProtocol->GetVersion (ScmiPerfProtocol, &Version); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // FastChannels were added in SCMI v2.0 spec. > + if (Version < PERFORMANCE_PROTOCOL_VERSION_V2) { > + DEBUG (( > + DEBUG_ERROR, > + "DynamicTablesScmiInfoLib requires SCMI version > 2.0\n" > + )); > + return EFI_UNSUPPORTED; > + } > + > + return Status; > +} > + > +/** Get the OPPs/performance states of a power domain. > + > + This function is a wrapper around the SCMI PERFORMANCE_DESCRIBE_LEVELS > + command. The list of discrete performance states is returned in a buffer > + that must be freed by the caller. > + > + @param[in] DomainId Identifier for the performance domain. > + @param[out] LevelArray If success, pointer to the list of list of > + performance state. This memory must be freed by > + the caller. > + @param[out] LevelArrayCount If success, contains the number of states in > + LevelArray. > + > + @retval EFI_SUCCESS Success. > + @retval EFI_DEVICE_ERROR Device error. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_TIMEOUT Time out. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +DynamicTablesScmiInfoDescribeLevels ( > + IN UINT32 DomainId, > + OUT SCMI_PERFORMANCE_LEVEL **LevelArray, > + OUT UINT32 *LevelArrayCount > + ) > +{ > + EFI_STATUS Status; > + SCMI_PERFORMANCE_LEVEL *Array; > + UINT32 Count; > + UINT32 Size; > + > + if ((ScmiPerfProtocol == NULL) || > + (LevelArray == NULL) || > + (LevelArrayCount == NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + // First call to get the number of levels. > + Size = 0; > + Status = ScmiPerfProtocol->DescribeLevels ( > + ScmiPerfProtocol, > + DomainId, > + &Count, > + &Size, > + NULL > + ); > + if (Status != EFI_BUFFER_TOO_SMALL) { > + // EFI_SUCCESS is not a valid option. > + if (Status == EFI_SUCCESS) { > + return EFI_INVALID_PARAMETER; > + } else { > + return Status; > + } > + } > + > + Array = AllocateZeroPool (Size); > + if (Array == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // Second call to get the descriptions of the levels. > + Status = ScmiPerfProtocol->DescribeLevels ( > + ScmiPerfProtocol, > + DomainId, > + &Count, > + &Size, > + Array > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *LevelArray = Array; > + *LevelArrayCount = Count; > + > + return Status; > +} > + > +/** Populate a AML_CPC_INFO object based on SCMI information. > + > + @param[in] DomainId Identifier for the performance domain. > + @param[out] CpcInfo If success, this structure was populated from > + information queried to the SCP. > + > + @retval EFI_SUCCESS Success. > + @retval EFI_DEVICE_ERROR Device error. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_TIMEOUT Time out. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +EFI_STATUS > +EFIAPI > +DynamicTablesScmiInfoGetFastChannel ( > + IN UINT32 DomainId, > + OUT AML_CPC_INFO *CpcInfo > + ) > +{ > + EFI_STATUS Status; > + SCMI_PERFORMANCE_FASTCHANNEL FcLevelGet; > + SCMI_PERFORMANCE_FASTCHANNEL FcLimitsSet; > + SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES DomainAttributes; > + > + SCMI_PERFORMANCE_LEVEL *LevelArray; > + UINT32 LevelCount; > + > + UINT64 FcLevelGetAddr; > + UINT64 FcLimitsMaxSetAddr; > + UINT64 FcLimitsMinSetAddr; > + > + if ((ScmiPerfProtocol == NULL) || > + (CpcInfo == NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ScmiPerfProtocol->DescribeFastchannel ( > + ScmiPerfProtocol, > + DomainId, > + ScmiMessageIdPerformanceLevelSet, > + &FcLevelGet > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiPerfProtocol->DescribeFastchannel ( > + ScmiPerfProtocol, > + DomainId, > + ScmiMessageIdPerformanceLimitsSet, > + &FcLimitsSet > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiPerfProtocol->GetDomainAttributes ( > + ScmiPerfProtocol, > + DomainId, > + &DomainAttributes > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = DynamicTablesScmiInfoDescribeLevels (DomainId, &LevelArray, > &LevelCount); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + /* Do some safety checks. > + Only support FastChannels (and not doorbells) as this is > + the only mechanism supported by SCP. > + FcLimits[Get|Set] require 2 UINT32 values (max, then min) and > + FcLimits[Get|Set] require 1 UINT32 value (level). > + */ > + if ((FcLevelGet.ChanSize != sizeof (UINT32)) || > + ((FcLevelGet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) == > + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) || > + (FcLimitsSet.ChanSize != 2 * sizeof (UINT32)) || > + ((FcLimitsSet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) == > + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL)) > + { > + Status = EFI_INVALID_PARAMETER; > + goto exit_handler; > + } > + > + FcLevelGetAddr = ((UINT64)FcLevelGet.ChanAddrHigh << 32) | > + FcLevelGet.ChanAddrLow; > + FcLimitsMaxSetAddr = ((UINT64)FcLimitsSet.ChanAddrHigh << 32) | > + FcLimitsSet.ChanAddrLow; > + FcLimitsMinSetAddr = FcLimitsMaxSetAddr + 0x4; > + > + CpcInfo->Revision = > EFI_ACPI_6_5_AML_CPC_REVISION_V3; > + CpcInfo->HighestPerformanceInteger = LevelArray[LevelCount - > 1].Level; > + CpcInfo->NominalPerformanceInteger = > DomainAttributes.SustainedPerfLevel; > + CpcInfo->LowestNonlinearPerformanceInteger = LevelArray[0].Level; > + CpcInfo->LowestPerformanceInteger = LevelArray[0].Level; > + > + CpcInfo->DesiredPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_5_SYSTEM_MEMORY; > + CpcInfo->DesiredPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->DesiredPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->DesiredPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD; > + CpcInfo->DesiredPerformanceRegister.Address = FcLevelGetAddr; > + > + CpcInfo->MinimumPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_5_SYSTEM_MEMORY; > + CpcInfo->MinimumPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->MinimumPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->MinimumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD; > + CpcInfo->MinimumPerformanceRegister.Address = FcLimitsMinSetAddr; > + > + CpcInfo->MaximumPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_5_SYSTEM_MEMORY; > + CpcInfo->MaximumPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->MaximumPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->MaximumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD; > + CpcInfo->MaximumPerformanceRegister.Address = FcLimitsMaxSetAddr; > + > + CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId = > EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE; > + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitWidth = 0x40; > + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitOffset = 0; > + CpcInfo->ReferencePerformanceCounterRegister.AccessSize = > ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER; > + CpcInfo->ReferencePerformanceCounterRegister.Address = 0x4; > + > + CpcInfo->DeliveredPerformanceCounterRegister.AddressSpaceId = > EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE; > + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitWidth = 0x40; > + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitOffset = 0; > + CpcInfo->DeliveredPerformanceCounterRegister.AccessSize = > ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER; > + CpcInfo->DeliveredPerformanceCounterRegister.Address = 0x4; > + > + // SCMI should advertise performance values on a unified scale. So > frequency > + // values are not available. LowestFrequencyInteger and > + // NominalFrequencyInteger are populated in the ConfigurationManager. > + > +exit_handler: > + FreePool (LevelArray); > + return Status; > +} > diff --git > a/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > > b/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > new file mode 100644 > index 000000000000..d49277f82bc3 > --- /dev/null > +++ > b/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf > @@ -0,0 +1,31 @@ > +## @file > +# Arm SCMI Info Library. > +# > +# Copyright (c) 2022 - 2023, Arm Limited. All rights reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = DynamicTablesScmiInfoLib > + FILE_GUID = 1A7CDB04-9FFC-40DA-A87C-A5ACADAF8136 > + VERSION_STRING = 1.0 > + MODULE_TYPE = DXE_DRIVER > + LIBRARY_CLASS = DynamicTablesScmiInfoLib > + CONSTRUCTOR = DynamicTablesScmiInfoLibConstructor > + > +[Sources] > + DynamicTablesScmiInfoLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + DynamicTablesPkg/DynamicTablesPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + > +[Protocols] > + gArmScmiPerformanceProtocolGuid ## CONSUMES > + > +[Depex] > + gArmScmiPerformanceProtocolGuid > -- > 2.25.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111586): https://edk2.groups.io/g/devel/message/111586 Mute This Topic: https://groups.io/mt/102732033/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-