[edk2-devel] [edk2-platforms][PATCH 1/6] AmpereAltraPkg: Add PCIe Hot Plug library
Minh Nguyen via groups.io
minhnguyen1=os.amperecomputing.com at groups.io
Thu May 11 08:10:06 UTC 2023
From: Vu Nguyen <vunguyen at os.amperecomputing.com>
This adds PCIe Hot Plug library to support Hot Plug
feature and specific procedures for setting different
Portmap tables (GPIO pins used for PCIe reset).
Signed-off-by: Minh Nguyen <minhnguyen1 at os.amperecomputing.com>
---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 8 +-
Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec | 13 +
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 +
Platform/Ampere/JadePkg/Jade.dsc | 66 ++++
Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.inf | 37 ++
Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieHotPlugLib.h | 162 ++++++++
Silicon/Ampere/AmpereSiliconPkg/Include/Library/PcieHotPlugPortMapLib.h | 81 ++++
Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.c | 397 ++++++++++++++++++++
8 files changed, 764 insertions(+), 1 deletion(-)
diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index d795c9229691..d4881eaed692 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -1,6 +1,6 @@
## @file
#
-# Copyright (c) 2020-2021, Ampere Computing LLC. All rights reserved.<BR>
+# Copyright (c) 2020-2023, Ampere Computing LLC. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -49,6 +49,9 @@ [LibraryClasses]
## @libraryclass Defines a set of methods to initialize Pcie
Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
+ ## @libraryclass Defines a set of methods to start Hot plug feature
+ PcieHotPlugLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieHotPlugLib.h
+
[Guids]
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
@@ -70,3 +73,6 @@ [Guids]
## Include/Guid/AcpiConfigHii.h
gAcpiConfigFormSetGuid = { 0x0ceb6764, 0xd415, 0x4b01, { 0xa8, 0x43, 0xd1, 0x01, 0xbc, 0xb0, 0xd8, 0x29 } }
+
+ ## PCIe Hot Plug GUID
+ gPcieHotPlugGuid = { 0x5598273c, 0x11ea, 0xa496, { 0x42, 0x02, 0x37, 0xbb, 0x02, 0x00, 0x13, 0xac } }
diff --git a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
index 625a9b2b1e89..9259956c7caa 100644
--- a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+++ b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
@@ -80,3 +80,16 @@ [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx]
#
# SMBIOS Type 0 - BIOS Information
gAmpereTokenSpaceGuid.PcdSmbiosTables0BiosReleaseDate|"MM/DD/YYYY"|VOID*|0xB0000002 # Must follow this MM/DD/YYYY SMBIOS date format
+
+ # Pcie HotPlug reset map
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugGpioResetMap|0x0|UINT8|0xB000000A
+
+ #
+ # Pcie HotPlug Port Map table
+ #
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable|{0x00}|PCIE_HOT_PLUG_PORT_MAP_TABLE|0xB000000B {
+ <HeaderFiles>
+ Library/PcieHotPlugPortMapLib.h
+ <Packages>
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+ }
diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index 9275e0053af6..8cb2a3fe6422 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -81,6 +81,7 @@ [LibraryClasses.common]
NVParamLib|Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.inf
MailboxInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.inf
SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf
+ PcieHotPlugLib|Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.inf
PciePhyLib|Silicon/Ampere/AmpereAltraBinPkg/Library/PciePhyLib/PciePhyLib.inf
Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index f14d286cdfb8..a6b5fa3ca2d3 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -100,7 +100,73 @@ [PcdsFeatureFlag.common]
#
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+ #
+ # Flag to indicate option of using default or specific platform Port Map table
+ #
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.UseDefaultConfig|TRUE
+
[PcdsFixedAtBuild]
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugGpioResetMap|0x3F
+
+ #
+ # Setting Portmap table
+ #
+ # * Elements of array:
+ # - 0: Index of Portmap entry in Portmap table structure (Vport).
+ # - 1: Socket number (Socket).
+ # - 2: Root complex port for each Portmap entry (RcaPort).
+ # - 3: Root complex sub-port for each Portmap entry (RcaSubPort).
+ # - 4: Select output port of IO expander (PinPort).
+ # - 5: I2C address of IO expander that CPLD backplane simulates (I2cAddress).
+ # - 6: Address of I2C switch between CPU and CPLD backplane (MuxAddress).
+ # - 7: Channel of I2C switch (MuxChannel).
+ # - 8: It is set from PcieHotPlugSetGPIOMapCmd () function to select GPIO[16:21] (PcdPcieHotPlugGpioResetMap) or I2C for PCIe reset purpose.
+ # - 9: Segment of root complex (Segment).
+ # - 10: SSD slot index on the front panel of backplane (DriveIndex).
+ #
+ # * Caution:
+ # - The last array ({ 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF }) require if no fully structured used.
+ # - Size of Portmap table: PortMap[MAX_PORT_MAP_ENTRY][sizeof(PCIE_HOT_PLUG_PORTMAP_ENTRY)] <=> PortMap[96][11].
+ # * Example: Bellow configuration is the configuration for Portmap table of Mt. Jade 2U platform.
+ #
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[0]|{ 0, 0, 2, 0, 0, 0x00, 0x00, 0x0, 0, 1, 0xFF } # S0 RCA2.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[1]|{ 1, 0, 3, 0, 1, 0x00, 0x00, 0x0, 0, 0, 0xFF } # S0 RCA3.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[2]|{ 2, 0, 4, 0, 2, 0x27, 0x70, 0x1, 0, 2, 6 } # S0 RCB0.0 - SSD6
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[3]|{ 3, 0, 4, 2, 3, 0x27, 0x70, 0x1, 0, 2, 7 } # S0 RCB0.2 - SSD7
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[4]|{ 4, 0, 4, 4, 0, 0x25, 0x70, 0x1, 0, 2, 2 } # S0 RCB0.4 - SSD2
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[5]|{ 5, 0, 4, 6, 1, 0x25, 0x70, 0x1, 0, 2, 3 } # S0 RCB0.6 - SSD3
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[6]|{ 6, 0, 5, 0, 0, 0x24, 0x70, 0x1, 0, 3, 0 } # S0 RCB1.0 - SSD0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[7]|{ 7, 0, 5, 2, 1, 0x24, 0x70, 0x1, 0, 3, 1 } # S0 RCB1.2 - SSD1
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[8]|{ 8, 0, 5, 4, 2, 0x26, 0x70, 0x1, 0, 3, 4 } # S0 RCB1.4 - SSD4
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[9]|{ 9, 0, 5, 6, 3, 0x26, 0x70, 0x1, 0, 3, 5 } # S0 RCB1.6 - SSD5
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[10]|{ 10, 0, 6, 0, 2, 0x00, 0x00, 0x0, 0, 4, 0xFF } # S0 RCB2.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[11]|{ 11, 0, 6, 2, 3, 0x00, 0x00, 0x0, 0, 4, 0xFF } # S0 RCB2.2
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[12]|{ 12, 0, 6, 4, 0, 0x00, 0x00, 0x0, 0, 4, 0xFF } # S0 RCB2.4
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[13]|{ 13, 0, 7, 0, 1, 0x00, 0x00, 0x0, 0, 5, 0xFF } # S0 RCB3.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[14]|{ 14, 0, 7, 4, 2, 0x00, 0x00, 0x0, 0, 5, 0xFF } # S0 RCB3.4
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[15]|{ 15, 0, 7, 6, 3, 0x00, 0x00, 0x0, 0, 5, 0xFF } # S0 RCB3.6
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[16]|{ 16, 1, 2, 0, 0, 0x26, 0x70, 0x2, 0, 6, 20 } # S1 RCA2.0 - SSD20
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[17]|{ 17, 1, 2, 1, 1, 0x26, 0x70, 0x2, 0, 6, 21 } # S1 RCA2.1 - SSD21
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[18]|{ 18, 1, 2, 2, 2, 0x27, 0x70, 0x2, 0, 6, 22 } # S1 RCA2.2 - SSD22
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[19]|{ 19, 1, 2, 3, 3, 0x27, 0x70, 0x2, 0, 6, 23 } # S1 RCA2.3 - SSD23
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[20]|{ 20, 1, 3, 0, 0, 0x00, 0x00, 0x0, 0, 7, 0xFF } # S1 RCA3.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[21]|{ 21, 1, 3, 2, 1, 0x00, 0x00, 0x0, 0, 7, 0xFF } # S1 RCA3.2
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[22]|{ 22, 1, 4, 0, 0, 0x00, 0x00, 0x0, 0, 8, 0xFF } # S1 RCB0.0
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[23]|{ 23, 1, 4, 4, 2, 0x25, 0x70, 0x2, 0, 8, 18 } # S1 RCB0.4 - SSD18
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[24]|{ 24, 1, 4, 6, 3, 0x25, 0x70, 0x2, 0, 8, 19 } # S1 RCB0.6 - SSD19
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[25]|{ 25, 1, 5, 0, 0, 0x24, 0x70, 0x2, 0, 9, 16 } # S1 RCB1.0 - SSD16
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[26]|{ 26, 1, 5, 2, 1, 0x24, 0x70, 0x2, 0, 9, 17 } # S1 RCB1.2 - SSD17
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[27]|{ 27, 1, 5, 4, 2, 0x00, 0x00, 0x0, 0, 9, 0xFF } # S1 RCB1.4
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[28]|{ 28, 1, 6, 0, 3, 0x25, 0x70, 0x4, 0, 10, 11 } # S1 RCB2.0 - SSD11
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[29]|{ 29, 1, 6, 2, 2, 0x25, 0x70, 0x4, 0, 10, 10 } # S1 RCB2.2 - SSD10
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[30]|{ 30, 1, 6, 4, 1, 0x27, 0x70, 0x4, 0, 10, 15 } # S1 RCB2.4 - SSD15
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[31]|{ 31, 1, 6, 6, 0, 0x27, 0x70, 0x4, 0, 10, 14 } # S1 RCB2.6 - SSD14
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[32]|{ 32, 1, 7, 0, 3, 0x26, 0x70, 0x4, 0, 11, 13 } # S1 RCB3.0 - SSD13
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[33]|{ 33, 1, 7, 2, 2, 0x26, 0x70, 0x4, 0, 11, 12 } # S1 RCB3.2 - SSD12
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[34]|{ 34, 1, 7, 4, 1, 0x24, 0x70, 0x4, 0, 11, 9 } # S1 RCB3.4 - SSD9
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[35]|{ 35, 1, 7, 6, 0, 0x24, 0x70, 0x4, 0, 11, 8 } # S1 RCB3.6 - SSD8
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable.PortMap[36]|{ 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF } # Require if no fully structure used
+
!ifdef $(FIRMWARE_VER)
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"$(FIRMWARE_VER)"
!endif
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.inf
new file mode 100644
index 000000000000..faeb74ecc0bf
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.inf
@@ -0,0 +1,37 @@
+## @file
+#
+# Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PcieHotPlugLib
+ FILE_GUID = 6C0C1D32-CB51-4236-AC33-A7A6D4B638E2
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PcieHotPlugLib
+
+[Sources]
+ PcieHotPlugLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Pcd]
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugGpioResetMap
+ gAmpereTokenSpaceGuid.PcdPcieHotPlugPortMapTable
+
+[Guids]
+ gPcieHotPlugGuid
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieHotPlugLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieHotPlugLib.h
new file mode 100644
index 000000000000..e2f17d366a58
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieHotPlugLib.h
@@ -0,0 +1,162 @@
+/** @file
+
+ Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef PCIE_HOT_PLUG_H_
+#define PCIE_HOT_PLUG_H_
+
+#define PCIE_HOT_PLUG_SPCI_CMD_ALERT_IRQ 1 // Alert IRQ
+#define PCIE_HOT_PLUG_SPCI_CMD_START 2 // Stat monitor event
+#define PCIE_HOT_PLUG_SPCI_CMD_CHG 3 // Indicate PCIE port change state explicitly
+#define PCIE_HOT_PLUG_SPCI_CMD_LED 4 // Control LED state
+#define PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_CLR 5 // Clear all port map
+#define PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_SET 6 // Set port map
+#define PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_LOCK 7 // Lock port map
+#define PCIE_HOT_PLUG_SPCI_CMD_GPIO_MAP 8 // Set GPIO reset map
+
+#define LED_FAULT 1 // LED_CMD: LED type - Fault
+#define LED_ATT 2 // LED_CMD: LED type - Attention
+
+#define LED_SET_ON 1
+#define LED_SET_OFF 2
+#define LED_SET_BLINK 3
+
+// DEN0077A Arm Secure Partition Client Interface Specification 1.0 Beta_0_0
+
+// Client ID used for SPCI calls
+#define SPCI_CLIENT_ID 0x0000ACAC
+
+// SPCI error codes.
+#define SPCI_SUCCESS 0
+#define SPCI_NOT_SUPPORTED -1
+#define SPCI_INVALID_PARAMETER -2
+#define SPCI_NO_MEMORY -3
+#define SPCI_BUSY -4
+#define SPCI_QUEUED -5
+#define SPCI_DENIED -6
+#define SPCI_NOT_PRESENT -7
+
+// Bit definitions inside the function id as per the SMC calling convention
+#define FUNCID_CC_SHIFT 30
+#define FUNCID_OEN_SHIFT 24
+
+#define SMC_64 1
+#define SMC_32 0
+
+// Definitions to build the complete SMC ID
+#define SPCI_FID_MISC_FLAG (0 << 27)
+#define SPCI_FID_MISC_SHIFT 20
+#define SPCI_FID_TUN_FLAG (1 << 27)
+#define SPCI_FID_TUN_SHIFT 24
+
+#define OEN_SPCI_START 0x30
+#define OEN_SPCI_END 0x3F
+
+#define SPCI_SMC(spci_fid) ((OEN_SPCI_START << FUNCID_OEN_SHIFT) | \
+ (1U << 31) | (spci_fid))
+#define SPCI_MISC_32(misc_fid) ((SMC_32 << FUNCID_CC_SHIFT) | \
+ SPCI_FID_MISC_FLAG | \
+ SPCI_SMC ((misc_fid) << SPCI_FID_MISC_SHIFT))
+#define SPCI_MISC_64(misc_fid) ((SMC_64 << FUNCID_CC_SHIFT) | \
+ SPCI_FID_MISC_FLAG | \
+ SPCI_SMC ((misc_fid) << SPCI_FID_MISC_SHIFT))
+#define SPCI_TUN_64(tun_fid) ((SMC_64 << FUNCID_CC_SHIFT) | \
+ SPCI_FID_TUN_FLAG | \
+ SPCI_SMC ((tun_fid) << SPCI_FID_TUN_SHIFT))
+
+// SPCI miscellaneous functions
+#define SPCI_FID_SERVICE_HANDLE_OPEN 0x2
+#define SPCI_FID_SERVICE_HANDLE_CLOSE 0x3
+#define SPCI_FID_SERVICE_REQUEST_BLOCKING 0x7
+#define SPCI_FID_SERVICE_REQUEST_START 0x8
+
+// SPCI tunneling functions
+#define SPCI_FID_SERVICE_TUN_REQUEST_BLOCKING 0x2
+
+// Complete SMC IDs and associated values
+#define SPCI_SERVICE_HANDLE_OPEN \
+ SPCI_MISC_32 (SPCI_FID_SERVICE_HANDLE_OPEN)
+#define SPCI_SERVICE_HANDLE_CLOSE \
+ SPCI_MISC_32 (SPCI_FID_SERVICE_HANDLE_CLOSE)
+#define SPCI_SERVICE_REQUEST_BLOCKING_AARCH64 \
+ SPCI_MISC_64 (SPCI_FID_SERVICE_REQUEST_BLOCKING)
+#define SPCI_SERVICE_REQUEST_START_AARCH64 \
+ SPCI_MISC_64 (SPCI_FID_SERVICE_REQUEST_START)
+#define SPCI_SERVICE_TUN_REQUEST_BLOCKING_AARCH64 \
+ SPCI_TUN_64 (SPCI_FID_SERVICE_TUN_REQUEST_BLOCKING)
+
+#pragma pack(1)
+
+typedef struct {
+ UINT64 Token;
+ UINT32 HandleId;
+ UINT64 SpciCommand;
+ UINT64 SpciParam1;
+ UINT64 SpciParam2;
+ UINT64 SpciParam3;
+ UINT64 SpciParam4;
+ UINT64 SpciParam5;
+} AMPERE_SPCI_ARGS;
+
+#pragma pack()
+
+/**
+ Set GPIO pins used for PCIe reset. This command
+ limits the number of GPIO[16:21] for reset purpose.
+**/
+VOID
+PcieHotPlugSetGpioMap (
+ VOID
+ );
+
+/**
+ Lock current Portmap table.
+**/
+VOID
+PcieHotPlugSetLockPortMap (
+ VOID
+ );
+
+/**
+ Start Hot plug service.
+**/
+VOID
+PcieHotPlugSetStart (
+ VOID
+ );
+
+/**
+ Clear current configuration of Portmap table.
+**/
+VOID
+PcieHotPlugSetClear (
+ VOID
+ );
+
+/**
+ Set configuration for Portmap table.
+**/
+VOID
+PcieHotPlugSetPortMap (
+ VOID
+ );
+
+/**
+ This function will start Hotplug service after following steps:
+ - Open handle to make a SPCI call.
+ - Set GPIO pins for PCIe reset.
+ - Set configuration for Portmap table.
+ - Lock current Portmap table.
+ - Start Hot plug service.
+ - Close handle.
+**/
+VOID
+PcieHotPlugStart (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Ampere/AmpereSiliconPkg/Include/Library/PcieHotPlugPortMapLib.h b/Silicon/Ampere/AmpereSiliconPkg/Include/Library/PcieHotPlugPortMapLib.h
new file mode 100644
index 000000000000..4889f0891c47
--- /dev/null
+++ b/Silicon/Ampere/AmpereSiliconPkg/Include/Library/PcieHotPlugPortMapLib.h
@@ -0,0 +1,81 @@
+/** @file
+
+ Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PCIE_HOT_PLUG_PORT_MAP_H_
+#define PCIE_HOT_PLUG_PORT_MAP_H_
+
+// "PCIe Bifurcation Mapping" spec just reserve 24x48 bytes (48 ports)
+#define MAX_NUMBER_PROCESSORS 2
+#define NUMBER_OF_PCIE_PORTS 48
+#define MAX_PORT_MAP_ENTRY (NUMBER_OF_PCIE_PORTS * MAX_NUMBER_PROCESSORS)
+
+//
+// - Macro to create value for PCIe Hot Plug configuration from PcieHotPlugPortMapEntry structure.
+// - Value structure:
+// Bit [0:7]: Vport
+// Bit [8:11]: Socket
+// Bit [12:15]: RcaPort
+// Bit [16:19]: RcaSubPort
+// Bit [20:23]: PinPort
+// Bit [24:31]: I2cAddress
+// Bit [32:39]: MuxAddress
+// Bit [40:43]: MuxChannel
+// Bit [44:51]: GpioResetNumber
+// Bit [52:55]: Segment
+// Bit [56: 63]: DriveIndexGpioResetNumber
+//
+#define PCIE_HOT_PLUG_DECODE_VPORT(Value) ((((UINTN)(Value).Vport) & 0xFF) << 0)
+#define PCIE_HOT_PLUG_DECODE_SOCKET(Value) ((((UINTN)(Value).Socket) & 0x0F) << 8)
+#define PCIE_HOT_PLUG_DECODE_RCA_PORT(Value) ((((UINTN)(Value).RcaPort) & 0x0F) << 12)
+#define PCIE_HOT_PLUG_DECODE_RCA_SUB_PORT(Value) ((((UINTN)(Value).RcaSubPort) & 0x0F) << 16)
+#define PCIE_HOT_PLUG_DECODE_PIN_PORT(Value) ((((UINTN)(Value).PinPort) & 0x0F) << 20)
+#define PCIE_HOT_PLUG_DECODE_I2C_ADDRESS(Value) ((((UINTN)(Value).I2cAddress) & 0xFF) << 24)
+#define PCIE_HOT_PLUG_DECODE_MUX_ADDRESS(Value) ((((UINTN)(Value).MuxAddress) & 0xFF) << 32)
+#define PCIE_HOT_PLUG_DECODE_MUX_CHANNEL(Value) ((((UINTN)(Value).MuxChannel) & 0x0F) << 40)
+#define PCIE_HOT_PLUG_DECODE_GPIO_RESET_NUMBER(Value) ((((UINTN)(Value).GpioResetNumber) & 0xFF) << 44)
+#define PCIE_HOT_PLUG_DECODE_SEGMENT(Value) ((((UINTN)(Value).Segment) & 0x0F) << 52)
+#define PCIE_HOT_PLUG_DECODE_DRIVE_INDEX(Value) ((((UINTN)(Value).DriveIndex) & 0xFF) << 56)
+
+#define PCIE_HOT_PLUG_GET_CONFIG_VALUE(Value) ( \
+ PCIE_HOT_PLUG_DECODE_VPORT(Value) | \
+ PCIE_HOT_PLUG_DECODE_SOCKET(Value) | \
+ PCIE_HOT_PLUG_DECODE_RCA_PORT(Value) | \
+ PCIE_HOT_PLUG_DECODE_RCA_SUB_PORT(Value) | \
+ PCIE_HOT_PLUG_DECODE_PIN_PORT(Value) | \
+ PCIE_HOT_PLUG_DECODE_I2C_ADDRESS(Value) | \
+ PCIE_HOT_PLUG_DECODE_MUX_ADDRESS(Value) | \
+ PCIE_HOT_PLUG_DECODE_MUX_CHANNEL(Value) | \
+ PCIE_HOT_PLUG_DECODE_GPIO_RESET_NUMBER(Value) | \
+ PCIE_HOT_PLUG_DECODE_SEGMENT(Value) | \
+ PCIE_HOT_PLUG_DECODE_DRIVE_INDEX(Value) \
+)
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Vport;
+ UINT8 Socket;
+ UINT8 RcaPort;
+ UINT8 RcaSubPort;
+ UINT8 PinPort;
+ UINT8 I2cAddress;
+ UINT8 MuxAddress;
+ UINT8 MuxChannel;
+ UINT8 GpioResetNumber;
+ UINT8 Segment;
+ UINT8 DriveIndex;
+} PCIE_HOT_PLUG_PORT_MAP_ENTRY;
+
+typedef struct {
+ BOOLEAN UseDefaultConfig;
+ UINT8 PortMap[MAX_PORT_MAP_ENTRY][sizeof (PCIE_HOT_PLUG_PORT_MAP_ENTRY)];
+} PCIE_HOT_PLUG_PORT_MAP_TABLE;
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.c
new file mode 100644
index 000000000000..10de5d17d2b9
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PcieHotPlugLib/PcieHotPlugLib.c
@@ -0,0 +1,397 @@
+/** @file
+
+ Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#include <Uefi.h>
+
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PcieHotPlugLib.h>
+#include <Library/PcieHotPlugPortMapLib.h>
+
+#define END_PORT_MAP_ENTRY 0xFF
+
+// SPM takes up to 4 arguments as value for SPCI call (Args.SpciParam1->Args.SpciParam4).
+#define MAX_MSG_CMD_ARGS 4
+
+UINT32 HandleId;
+
+STATIC
+EFI_STATUS
+SpciStatusMap (
+ UINTN SpciStatus
+ )
+{
+ switch (SpciStatus) {
+ case SPCI_SUCCESS:
+ return EFI_SUCCESS;
+
+ case SPCI_NOT_SUPPORTED:
+ return EFI_UNSUPPORTED;
+
+ case SPCI_INVALID_PARAMETER:
+ return EFI_INVALID_PARAMETER;
+
+ case SPCI_NO_MEMORY:
+ return EFI_OUT_OF_RESOURCES;
+
+ case SPCI_BUSY:
+ case SPCI_QUEUED:
+ return EFI_NOT_READY;
+
+ case SPCI_DENIED:
+ return EFI_ACCESS_DENIED;
+
+ case SPCI_NOT_PRESENT:
+ return EFI_NOT_FOUND;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+SpciServiceHandleOpen (
+ UINT16 ClientId,
+ UINT32 *HandleId,
+ EFI_GUID Guid
+ )
+{
+ ARM_SMC_ARGS SmcArgs;
+ EFI_STATUS Status;
+ UINT32 X1;
+ UINT64 Uuid1, Uuid2, Uuid3, Uuid4;
+
+ if (HandleId == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a HandleId is NULL \n", __func__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Uuid1 = Guid.Data1;
+ Uuid2 = Guid.Data3 << 16 | Guid.Data2;
+ Uuid3 = Guid.Data4[3] << 24 | Guid.Data4[2] << 16 | Guid.Data4[1] << 8 | Guid.Data4[0];
+ Uuid4 = Guid.Data4[7] << 24 | Guid.Data4[6] << 16 | Guid.Data4[5] << 8 | Guid.Data4[4];
+
+ SmcArgs.Arg0 = SPCI_SERVICE_HANDLE_OPEN;
+ SmcArgs.Arg1 = Uuid1;
+ SmcArgs.Arg2 = Uuid2;
+ SmcArgs.Arg3 = Uuid3;
+ SmcArgs.Arg4 = Uuid4;
+ SmcArgs.Arg5 = 0;
+ SmcArgs.Arg6 = 0;
+ SmcArgs.Arg7 = ClientId;
+ ArmCallSmc (&SmcArgs);
+
+ Status = SpciStatusMap (SmcArgs.Arg0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ X1 = SmcArgs.Arg1;
+
+ if ((X1 & 0x0000FFFF) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: SpciServiceHandleOpen returned X1 = 0x%08x\n",
+ __func__,
+ X1
+ ));
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Combine of returned handle and clientid
+ *HandleId = (UINT32)X1 | ClientId;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpciServiceHandleClose (
+ UINT32 HandleId
+ )
+{
+ ARM_SMC_ARGS SmcArgs;
+ EFI_STATUS Status;
+
+ SmcArgs.Arg0 = SPCI_SERVICE_HANDLE_CLOSE;
+ SmcArgs.Arg1 = HandleId;
+ ArmCallSmc (&SmcArgs);
+
+ Status = SpciStatusMap (SmcArgs.Arg0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpciServiceRequestStart (
+ AMPERE_SPCI_ARGS *Args
+ )
+{
+ ARM_SMC_ARGS SmcArgs;
+ EFI_STATUS Status;
+
+ if (Args == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid parameter\n", __func__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmcArgs.Arg0 = SPCI_SERVICE_REQUEST_START_AARCH64;
+ SmcArgs.Arg1 = Args->SpciCommand;
+ SmcArgs.Arg2 = Args->SpciParam1;
+ SmcArgs.Arg3 = Args->SpciParam2;
+ SmcArgs.Arg4 = Args->SpciParam3;
+ SmcArgs.Arg5 = Args->SpciParam4;
+ SmcArgs.Arg6 = Args->SpciParam5;
+ SmcArgs.Arg7 = (UINT64)Args->HandleId;
+ ArmCallSmc (&SmcArgs);
+
+ Status = SpciStatusMap (SmcArgs.Arg0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Return Token
+ Args->Token = SmcArgs.Arg1;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpciServiceRequestBlocking (
+ AMPERE_SPCI_ARGS *Args
+ )
+{
+ ARM_SMC_ARGS SmcArgs;
+ EFI_STATUS Status;
+
+ if (Args == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid parameter\n", __func__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmcArgs.Arg0 = SPCI_SERVICE_REQUEST_BLOCKING_AARCH64;
+ SmcArgs.Arg1 = Args->SpciCommand;
+ SmcArgs.Arg2 = Args->SpciParam1;
+ SmcArgs.Arg3 = Args->SpciParam2;
+ SmcArgs.Arg4 = Args->SpciParam3;
+ SmcArgs.Arg5 = Args->SpciParam4;
+ SmcArgs.Arg6 = Args->SpciParam5;
+ SmcArgs.Arg7 = (UINT64)Args->HandleId;
+ ArmCallSmc (&SmcArgs);
+
+ Status = SpciStatusMap (SmcArgs.Arg0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Args->SpciCommand = SmcArgs.Arg1;
+ Args->SpciParam1 = SmcArgs.Arg2;
+ Args->SpciParam2 = SmcArgs.Arg3;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set GPIO pins used for PCIe reset. This command
+ limits the number of GPIO[16:21] for reset purpose.
+**/
+VOID
+PcieHotPlugSetGpioMap (
+ VOID
+ )
+{
+ AMPERE_SPCI_ARGS Args;
+ EFI_STATUS Status;
+
+ Args.HandleId = HandleId;
+ Args.SpciCommand = PCIE_HOT_PLUG_SPCI_CMD_GPIO_MAP;
+ Args.SpciParam1 = (UINTN)PcdGet8 (PcdPcieHotPlugGpioResetMap);
+
+ Status = SpciServiceRequestBlocking (&Args);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug GPIO reset map failed. Returned: %r\n", Status));
+ }
+}
+
+/**
+ Lock current Portmap table.
+**/
+VOID
+PcieHotPlugSetLockPortMap (
+ VOID
+ )
+{
+ AMPERE_SPCI_ARGS Args;
+ EFI_STATUS Status;
+
+ Args.HandleId = HandleId;
+ Args.SpciCommand = PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_LOCK;
+
+ Status = SpciServiceRequestBlocking (&Args);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug port map lock failed. Returned: %r\n", Status));
+ }
+}
+
+/**
+ Start Hot plug service.
+**/
+VOID
+PcieHotPlugSetStart (
+ VOID
+ )
+{
+ AMPERE_SPCI_ARGS Args;
+ EFI_STATUS Status;
+
+ Args.HandleId = HandleId;
+ Args.SpciCommand = PCIE_HOT_PLUG_SPCI_CMD_START;
+
+ Status = SpciServiceRequestBlocking (&Args);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug start failed. Returned: %r\n", Status));
+ }
+}
+
+/**
+ Clear current configuration of Portmap table.
+**/
+VOID
+PcieHotPlugSetClear (
+ VOID
+ )
+{
+ AMPERE_SPCI_ARGS Args;
+ EFI_STATUS Status;
+
+ Args.HandleId = HandleId;
+ Args.SpciCommand = PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_CLR;
+
+ Status = SpciServiceRequestBlocking (&Args);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug clear port map failed. Returned: %r\n", Status));
+ }
+}
+
+/**
+ Set configuration for Portmap table.
+**/
+VOID
+PcieHotPlugSetPortMap (
+ VOID
+ )
+{
+ AMPERE_SPCI_ARGS Args;
+ EFI_STATUS Status;
+
+ PCIE_HOT_PLUG_PORT_MAP_TABLE *PortMapTable;
+ PCIE_HOT_PLUG_PORT_MAP_ENTRY PortMapEntry;
+ UINT8 Index;
+ UINT8 PortMapEntryIndex;
+ BOOLEAN IsEndPortMapEntry;
+ UINTN ConfigValue;
+ UINTN *ConfigLegacy;
+
+ // Retrieves PCD of Portmap table.
+ PortMapTable = (PCIE_HOT_PLUG_PORT_MAP_TABLE *)PcdGetPtr (PcdPcieHotPlugPortMapTable);
+
+ //
+ // Check whether specific platform configuration is used?
+ // Otherwise, keep default configuration (Mt. Jade 2U).
+ //
+ if (!PortMapTable->UseDefaultConfig) {
+ IsEndPortMapEntry = FALSE;
+ PortMapEntryIndex = 0;
+
+ // Clear old Port Map table first.
+ PcieHotPlugSetClear ();
+
+ while (!IsEndPortMapEntry) {
+ ZeroMem (&Args, sizeof (Args));
+ Args.HandleId = HandleId;
+ Args.SpciCommand = PCIE_HOT_PLUG_SPCI_CMD_PORT_MAP_SET;
+
+ // Pointer will get configuration value for Args.SpciParam1->Args.SpciParam5
+ ConfigLegacy = &Args.SpciParam1;
+
+ for (Index = 0; Index < MAX_MSG_CMD_ARGS; Index++) {
+ PortMapEntry = *((PCIE_HOT_PLUG_PORT_MAP_ENTRY *)PortMapTable->PortMap[PortMapEntryIndex]);
+ ConfigValue = PCIE_HOT_PLUG_GET_CONFIG_VALUE (PortMapEntry);
+ *ConfigLegacy = ConfigValue;
+
+ if (PortMapTable->PortMap[PortMapEntryIndex][0] == END_PORT_MAP_ENTRY) {
+ IsEndPortMapEntry = TRUE;
+ break;
+ }
+
+ PortMapEntryIndex++;
+ ConfigLegacy++;
+ }
+
+ Status = SpciServiceRequestBlocking (&Args);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug set port map failed. Returned: %r\n", Status));
+ }
+ }
+ }
+}
+
+/**
+ This function will start Hotplug service after following steps:
+ - Open handle to make a SPCI call.
+ - Set GPIO pins for PCIe reset.
+ - Set configuration for Portmap table.
+ - Lock current Portmap table.
+ - Start Hot plug service.
+ - Close handle.
+**/
+VOID
+PcieHotPlugStart (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ // Open handle
+ Status = SpciServiceHandleOpen (SPCI_CLIENT_ID, &HandleId, gPcieHotPlugGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "SPM failed to return invalid handle. Returned: %r\n",
+ Status
+ ));
+
+ return;
+ }
+
+ // Set GPIO pins for PCIe reset
+ PcieHotPlugSetGpioMap ();
+
+ // Set Portmap table
+ PcieHotPlugSetPortMap ();
+
+ // Lock current Portmap table
+ PcieHotPlugSetLockPortMap ();
+
+ // Start Hot plug service
+ PcieHotPlugSetStart ();
+
+ // Close handle
+ Status = SpciServiceHandleClose (HandleId);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SPM HotPlug close handle failed. Returned: %r\n", Status));
+ }
+}
--
2.39.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#104715): https://edk2.groups.io/g/devel/message/104715
Mute This Topic: https://groups.io/mt/98831767/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