On 10/26/23 13:03, Leif Lindholm wrote:
On Wed, Oct 25, 2023 at 13:25:39 +0200, PierreGondois wrote:
From: Pierre Gondois <pierre.gond...@arm.com>

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.

Couple of questions:
With a generic name like ArmScmiInfoLib, does is belong in ArmPkg or
MdeModulePkg?

Or if it's more tightly integrated with DynamicTablesPkg (not
blatantly obvious from a quick skim below), should that be reflected
by the library name?

The library is tight to the DynamicTablesPkg as it produces DynamicTablesPkg
specific objects. It uses the SCMI interface to fetch information from the SCP.
The ScmiProtocol resides in the ArmPkg, thus the name.
Does the name 'ScmiInfoLib' sound better ?

Regards,
Pierre



/
     Leif

Signed-off-by: Pierre Gondois <pierre.gond...@arm.com>
---
  DynamicTablesPkg/DynamicTables.dsc.inc        |   1 +
  DynamicTablesPkg/DynamicTablesPkg.dec         |   3 +
  DynamicTablesPkg/DynamicTablesPkg.dsc         |   1 +
  .../Include/Library/ArmScmiInfoLib.h          |  33 ++
  .../Library/ArmScmiInfoLib/ArmScmiInfoLib.c   | 294 ++++++++++++++++++
  .../Library/ArmScmiInfoLib/ArmScmiInfoLib.inf |  31 ++
  6 files changed, 363 insertions(+)
  create mode 100644 DynamicTablesPkg/Include/Library/ArmScmiInfoLib.h
  create mode 100644 DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c
  create mode 100644 DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf

diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc 
b/DynamicTablesPkg/DynamicTables.dsc.inc
index 9d4312c4e87d..be40ebc4b472 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
+  ArmScmiInfoLib|DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.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..26498e5fec53 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.
+  ArmScmiInfoLib|Include/Library/ArmScmiInfoLib.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..6ea86c9efdb0 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/ArmScmiInfoLib/ArmScmiInfoLib.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/ArmScmiInfoLib.h 
b/DynamicTablesPkg/Include/Library/ArmScmiInfoLib.h
new file mode 100644
index 000000000000..8d3fb31df13c
--- /dev/null
+++ b/DynamicTablesPkg/Include/Library/ArmScmiInfoLib.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
+ArmScmiInfoGetFastChannel (
+  IN  UINT32        DomainId,
+  OUT AML_CPC_INFO  *CpcInfo
+  );
+
+#endif // ARM_SCMI_INFO_LIB_H_
diff --git a/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c 
b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c
new file mode 100644
index 000000000000..c23bff63bb6f
--- /dev/null
+++ b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c
@@ -0,0 +1,294 @@
+/** @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/ArmScmiInfoLib.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
+ArmScmiInfoLibConstructor (
+  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, "ArmScmiInfoLib 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
+ArmScmiInfoDescribeLevels (
+  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
+ArmScmiInfoGetFastChannel (
+  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 = ArmScmiInfoDescribeLevels (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_4_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_4_SYSTEM_MEMORY;
+  CpcInfo->DesiredPerformanceRegister.RegisterBitWidth  = 32;
+  CpcInfo->DesiredPerformanceRegister.RegisterBitOffset = 0;
+  CpcInfo->DesiredPerformanceRegister.AccessSize        = EFI_ACPI_6_4_DWORD;
+  CpcInfo->DesiredPerformanceRegister.Address           = FcLevelGetAddr;
+
+  CpcInfo->MinimumPerformanceRegister.AddressSpaceId    = 
EFI_ACPI_6_4_SYSTEM_MEMORY;
+  CpcInfo->MinimumPerformanceRegister.RegisterBitWidth  = 32;
+  CpcInfo->MinimumPerformanceRegister.RegisterBitOffset = 0;
+  CpcInfo->MinimumPerformanceRegister.AccessSize        = EFI_ACPI_6_4_DWORD;
+  CpcInfo->MinimumPerformanceRegister.Address           = FcLimitsMinSetAddr;
+
+  CpcInfo->MaximumPerformanceRegister.AddressSpaceId    = 
EFI_ACPI_6_4_SYSTEM_MEMORY;
+  CpcInfo->MaximumPerformanceRegister.RegisterBitWidth  = 32;
+  CpcInfo->MaximumPerformanceRegister.RegisterBitOffset = 0;
+  CpcInfo->MaximumPerformanceRegister.AccessSize        = EFI_ACPI_6_4_DWORD;
+  CpcInfo->MaximumPerformanceRegister.Address           = FcLimitsMaxSetAddr;
+
+  CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId    = 
EFI_ACPI_6_4_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_4_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/ArmScmiInfoLib/ArmScmiInfoLib.inf 
b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf
new file mode 100644
index 000000000000..aad3f0fa7b83
--- /dev/null
+++ b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.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      = ArmScmiInfoLib
+  FILE_GUID      = 1A7CDB04-9FFC-40DA-A87C-A5ACADAF8136
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = ArmScmiInfoLib
+  CONSTRUCTOR    = ArmScmiInfoLibConstructor
+
+[Sources]
+  ArmScmiInfoLib.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 (#110514): https://edk2.groups.io/g/devel/message/110514
Mute This Topic: https://groups.io/mt/102175821/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to