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.gondois@arm.com>
---
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 (#111577): https://edk2.groups.io/g/devel/message/111577
Mute This Topic: https://groups.io/mt/102732033/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
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.gondois@arm.com>
Acked-by: Leif Lindholm <quic_llindhol@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/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.