[edk2-devel] [edk2-platforms][PATCH 06/34] Platform/Ampere: Add AcpiPccLib to support ACPI PCCT Table

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed Dec 9 09:25:03 UTC 2020


The AcpiPccLib provides functions to allocate and get the physical
address of PCC shared memory.

Signed-off-by: Nhi Pham <nhi at os.amperecomputing.com>
---
 Silicon/Ampere/AmperePkg.dec                      |   4 +
 Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.inf |  45 +++
 Silicon/Ampere/Include/Library/AcpiPccLib.h       |  91 ++++++
 Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.c   | 322 ++++++++++++++++++++
 4 files changed, 462 insertions(+)

diff --git a/Silicon/Ampere/AmperePkg.dec b/Silicon/Ampere/AmperePkg.dec
index 47b29f508185..fa5b7074f749 100755
--- a/Silicon/Ampere/AmperePkg.dec
+++ b/Silicon/Ampere/AmperePkg.dec
@@ -22,8 +22,12 @@ [Defines]
 #
 ################################################################################
 [Includes.common]
+  Include                        # Root include for the package
 
 [LibraryClasses]
+  ##  @libraryclass  Provides functions to create the ACPI PCCT Table which which advertises PCC mailbox channel information.
+  AcpiPccLib|Silicon/Ampere/Include/Library/AcpiPccLib.h
+
 
 [Guids]
   gAmpereTokenSpaceGuid = { 0xdbd4436e, 0x89cb, 0x44dc, { 0xb5, 0xc0, 0x49, 0xc3, 0x91, 0x35, 0xbf, 0xdf } }
diff --git a/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.inf b/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.inf
new file mode 100755
index 000000000000..d4b48e0fa248
--- /dev/null
+++ b/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.inf
@@ -0,0 +1,45 @@
+## @file
+#
+# Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x0001001B
+  BASE_NAME                     = AcpiPccLib
+  FILE_GUID                     = 790519F0-F344-11E3-AC10-0800200C9A66
+  MODULE_TYPE                   = BASE
+  VERSION_STRING                = 1.0
+  LIBRARY_CLASS                 = AcpiPccLib
+
+[Sources.common]
+  AcpiPccLib.c
+
+[FeaturePcd]
+
+[Pcd]
+
+[FixedPcd]
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  Silicon/Ampere/AmperePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/Ac01Pkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseLib
+  DebugLib
+  IoLib
+  PrintLib
+  TimerLib
+  BaseMemoryLib
+  UefiBootServicesTableLib
+
+[Pcd]
+  gAmpereTokenSpaceGuid.PcdPmproDbBaseReg
+  gAmpereTokenSpaceGuid.PcdSmproDbBaseReg
diff --git a/Silicon/Ampere/Include/Library/AcpiPccLib.h b/Silicon/Ampere/Include/Library/AcpiPccLib.h
new file mode 100755
index 000000000000..7ec761adaec1
--- /dev/null
+++ b/Silicon/Ampere/Include/Library/AcpiPccLib.h
@@ -0,0 +1,91 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_PCC_LIB_H_
+#define _ACPI_PCC_LIB_H_
+
+struct ACPI_PCCT_SHARED_MEMORY {
+  UINT32 Signature;
+  union {
+    UINT16 Command;
+    struct PCC_COMMAND {
+      UINT16 CommandCode:8;
+      UINT16 Reserved:7;
+      UINT16 Interrupt:1;
+    } __attribute__ ((packed)) CmdT;
+  } CmdData;
+  union {
+    UINT16 Status;
+    struct PCC_STATUS {
+      UINT16 CommandComplete:1;
+      UINT16 SciDb:1;
+      UINT16 Error:1;
+      UINT16 PlatformNotification:1;
+      UINT16 Reserved:12;
+    } __attribute__ ((packed)) StatusT;
+  } StatusData;
+} __attribute__((packed));
+
+EFI_STATUS
+EFIAPI
+AcpiPccSendMsg (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace,
+  IN VOID                        *MsgBuf,
+  IN UINT32                      Length
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiPccUnmaskInt (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiPccSyncSharedMemAddr (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiPccSharedMemInit (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiPccSharedMemInitV2 (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiIppPccIsSupported (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiPccAllocSharedMemory (
+  OUT UINT64                     *PccSharedMemPointer,
+  IN UINT32                      SubspaceNum
+  );
+
+VOID
+EFIAPI
+AcpiPccFreeSharedMemory (
+  OUT UINT64                     *PccSharedMemPointer,
+  IN UINT32                      SubspaceNum
+  );
+
+#endif /* _ACPI_PCC_LIB_H_*/
diff --git a/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.c b/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.c
new file mode 100755
index 000000000000..94e55ce34505
--- /dev/null
+++ b/Platform/Ampere/Library/AcpiPccLib/AcpiPccLib.c
@@ -0,0 +1,322 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TimerLib.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Platform/Ac01.h>
+#include <Library/AcpiPccLib.h>
+#include <Uefi/UefiBaseType.h>
+
+#define PCC_NULL_MSG             0x0F000000
+
+STATIC UINT64 PccSharedMemAddr = 0;
+
+STATIC EFI_STATUS
+AcpiPccGetSharedMemAddr (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace,
+  OUT VOID                       **AcpiPcct
+  )
+{
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PccSharedMemAddr == 0) {
+    return EFI_NOT_READY;
+  }
+
+  *AcpiPcct = (VOID *) (PccSharedMemAddr + PCC_SUBSPACE_SHARED_MEM_SIZE *
+                       (Subspace + PCC_MAX_SUBSPACES_PER_SOCKET * Socket));
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccSendMsg (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace,
+  IN VOID                        *MsgBuf,
+  IN UINT32                      Length
+  )
+{
+  INTN TimeoutCnt                = PCC_NOMINAL_LATENCY / PCC_CMD_POLL_UDELAY;
+  VOID                           *CommunicationSpacePtr;
+  struct ACPI_PCCT_SHARED_MEMORY *AcpiPcct;
+  EFI_STATUS                     Status;
+  UINT32                         PccMsg;
+
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AcpiPccGetSharedMemAddr (Socket, Subspace, (VOID **) &AcpiPcct);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CommunicationSpacePtr = AcpiPcct + 1;
+
+  /* Write Data into Communication Space Region */
+  CopyMem (CommunicationSpacePtr, MsgBuf, Length);
+  /* Flip CMD_COMPLETE bit */
+  AcpiPcct->StatusData.StatusT.CommandComplete = 0;
+  /* PCC signature */
+  AcpiPcct->Signature = PCC_SIGNATURE_MASK | Subspace;
+  /* Ring the Doorbell */
+  PccMsg = PCC_MSG;
+  /* Store the upper address (Bit 40-43) of PCC shared memory */
+  PccMsg |= ((UINT64) AcpiPcct >> 40) & PCP_MSG_UPPER_ADDR_MASK;
+  if (Subspace < PMPRO_MAX_DB) {
+    MmioWrite32 (PMPRO_DBx_REG (Socket, Subspace, DB_OUT), PccMsg);
+  } else {
+    MmioWrite32 (SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_OUT),
+                PccMsg);
+  }
+
+  /* Polling CMD_COMPLETE bit */
+  while (AcpiPcct->StatusData.StatusT.CommandComplete != 1) {
+    if (--TimeoutCnt <= 0) {
+      return EFI_TIMEOUT;
+    }
+    MicroSecondDelay (PCC_CMD_POLL_UDELAY);
+  };
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccUnmaskInt (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  )
+{
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  /* Unmask Interrupt */
+  if (Subspace < PMPRO_MAX_DB) {
+    MmioWrite32 (
+      PMPRO_DBx_REG (Socket, Subspace, DB_STATUSMASK),
+      ~DB_AVAIL_MASK
+      );
+  } else {
+    MmioWrite32 (
+      SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_STATUSMASK),
+      ~DB_AVAIL_MASK
+      );
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccSyncSharedMemAddr (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  )
+{
+  UINT32 PccData;
+
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  /*
+   * Advertise shared memory address to Platform (SMPro/PMPro)
+   * by ring the doorbell with dummy PCC message
+   */
+  PccData = PCC_NULL_MSG;
+
+  return AcpiPccSendMsg (Socket, Subspace, &PccData, 4);
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccSharedMemInit (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  )
+{
+  struct ACPI_PCCT_SHARED_MEMORY *AcpiPcct;
+  EFI_STATUS                     Status;
+
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AcpiPccGetSharedMemAddr (Socket, Subspace, (VOID **) &AcpiPcct);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /* Set Shared Memory address into DB OUT register */
+  if (Subspace < PMPRO_MAX_DB) {
+    MmioWrite32 (
+      PMPRO_DBx_REG (Socket, Subspace, DB_OUT0),
+      (UINT32) ((UINT64) AcpiPcct >> 8)
+      );
+  } else {
+    MmioWrite32 (
+      SMPRO_DBx_REG(Socket, Subspace - PMPRO_MAX_DB, DB_OUT0),
+      (UINT32) ((UINT64) AcpiPcct >> 8)
+      );
+  }
+
+  /* Init shared memory for each PCC subspaces */
+  SetMem (
+    (VOID *) AcpiPcct,
+    sizeof (struct ACPI_PCCT_SHARED_MEMORY) + PCC_MSG_SIZE,
+    0x0
+    );
+  AcpiPcct->StatusData.StatusT.CommandComplete = 1;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccSharedMemInitV2 (
+  IN UINT32                      Socket,
+  IN UINT32                      Subspace
+  )
+{
+  struct ACPI_PCCT_SHARED_MEMORY *AcpiPcct;
+  EFI_STATUS                     Status;
+  UINT32                         AlignBit;
+
+  if ((Subspace >= PCC_MAX_SUBSPACES_PER_SOCKET)
+    || (Socket >= PLATFORM_CPU_MAX_SOCKET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AcpiPccGetSharedMemAddr (Socket, Subspace, (VOID **) &AcpiPcct);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((PCC_MSG & PCC_256_ALIGN_ADDR) != 0) {
+    AlignBit = 8;
+  }
+
+  /* Set Shared Memory address into DB OUT register */
+  if (Subspace < PMPRO_MAX_DB) {
+    MmioWrite32 (
+      PMPRO_DBx_REG (Socket, Subspace, DB_OUT0),
+      (UINT32) ((UINT64) AcpiPcct >> AlignBit)
+      );
+
+    MmioWrite32 (
+      (PMPRO_DBx_REG (Socket, Subspace, DB_OUT1)),
+      (UINT32) ((UINT64) AcpiPcct >> (32 + AlignBit))
+      );
+  } else {
+    MmioWrite32 (
+      SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_OUT0),
+      (UINT32) ((UINT64) AcpiPcct >> AlignBit)
+      );
+
+    MmioWrite32 (
+      SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_OUT1),
+      (UINT32) ((UINT64) AcpiPcct >> (32 + AlignBit))
+      );
+  }
+
+  /* Init shared memory for each PCC subspaces */
+  SetMem (
+    (VOID *) AcpiPcct,
+    sizeof (struct ACPI_PCCT_SHARED_MEMORY) + PCC_MSG_SIZE,
+    0x0
+    );
+  AcpiPcct->StatusData.StatusT.CommandComplete = 1;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiIppPccIsSupported (
+  VOID
+  )
+{
+  EFI_STATUS                     Status;
+
+  /* Send a PCC NULL command to check if IPP supports PCC request */
+  AcpiPccSharedMemInit (0, 0);
+
+  Status = AcpiPccSyncSharedMemAddr (0, 0);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiPccAllocSharedMemory (
+  OUT UINT64                     *PccSharedMemPointer,
+  IN UINT32                      SubspaceNum
+  )
+{
+  EFI_STATUS                     Status;
+
+  if (SubspaceNum > PCC_MAX_SUBSPACES) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiRuntimeServicesData,
+                  EFI_SIZE_TO_PAGES (PCC_SUBSPACE_SHARED_MEM_SIZE * SubspaceNum),
+                  &PccSharedMemAddr
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate PCC shared memory\n"));
+    return Status;
+  }
+
+  *PccSharedMemPointer = PccSharedMemAddr;
+
+  return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+AcpiPccFreeSharedMemory (
+  OUT UINT64                     *PccSharedMemPointer,
+  IN UINT32                      SubspaceNum
+  )
+{
+  if (SubspaceNum > PCC_MAX_SUBSPACES) {
+    return;
+  }
+
+  gBS->FreePages (
+         *PccSharedMemPointer,
+         EFI_SIZE_TO_PAGES (PCC_SUBSPACE_SHARED_MEM_SIZE * SubspaceNum)
+         );
+
+  PccSharedMemAddr = 0;
+}
-- 
2.17.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#68506): https://edk2.groups.io/g/devel/message/68506
Mute This Topic: https://groups.io/mt/78825489/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list