From: Vu Nguyen <vungu...@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 <minhnguy...@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/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-