From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: Leif Lindholm <leif@nuviainc.com>
Cc: devel@edk2.groups.io, patches@amperecomputing.com,
vunguyen@os.amperecomputing.com,
Thang Nguyen <thang@os.amperecomputing.com>,
Chuong Tran <chuong@os.amperecomputing.com>,
Phong Vo <phong@os.amperecomputing.com>,
Michael D Kinney <michael.d.kinney@intel.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: Re: [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance
Date: Wed, 3 Nov 2021 16:33:24 +0700 [thread overview]
Message-ID: <b20789e1-5b20-ba36-c5f2-c26409f85f6d@os.amperecomputing.com> (raw)
In-Reply-To: <20211026124524.ogphzlh34uhc5vga@leviathan>
Hi Leif,
Thanks a lot for reviewing. I will address all your comments and review
carefully through this module as well.
Best regards,
Nhi
On 26/10/2021 19:45, Leif Lindholm wrote:
> On Fri, Oct 22, 2021 at 13:17:50 +0700, Nhi Pham wrote:
>> From: Vu Nguyen <vunguyen@os.amperecomputing.com>
>>
>> Provides essential functions to initialize the PCIe Root Complex on
>> Ampere Altra processor.
>>
>> Cc: Thang Nguyen <thang@os.amperecomputing.com>
>> Cc: Chuong Tran <chuong@os.amperecomputing.com>
>> Cc: Phong Vo <phong@os.amperecomputing.com>
>> Cc: Leif Lindholm <leif@nuviainc.com>
>> Cc: Michael D Kinney <michael.d.kinney@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
>>
>> Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
>> ---
>> Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 6 +
>> Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 2 +
>> Platform/Ampere/JadePkg/Jade.dsc | 5 +
>> Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf | 42 +
>> Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf | 25 +
>> Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h | 49 +
>> Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h | 45 +
>> Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h | 451 +++++++
>> Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c | 1391 ++++++++++++++++++++
>> Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c | 47 +
>> 10 files changed, 2063 insertions(+)
>>
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
>> index e19925c68a0e..7bd4d3ac9462 100644
>> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
>> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
>> @@ -43,6 +43,12 @@ [LibraryClasses]
>> ## @libraryclass Defines a set of methods to access flash memory.
>> FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
>>
>> + ## @libraryclass Defines a set of platform dependent functions
>> + BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
>> +
>> + ## @libraryclass Defines a set of methods to initialize Pcie
>> + Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
>> +
>> [Guids]
>> ## NVParam MM GUID
>> gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
>> index c01a8be3c607..a6f7d87769fe 100644
>> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
>> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
>> @@ -81,6 +81,8 @@ [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
>> + PciePhyLib|Silicon/Ampere/AmpereAltraBinPkg/Library/PciePhyLib/PciePhyLib.inf
>> + Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
>> AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
>> TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
>> I2cLib|Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf
>> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
>> index e4b29e36fc8d..23a297d0dbeb 100644
>> --- a/Platform/Ampere/JadePkg/Jade.dsc
>> +++ b/Platform/Ampere/JadePkg/Jade.dsc
>> @@ -82,6 +82,11 @@ [LibraryClasses]
>> #
>> AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf
>>
>> + #
>> + # Pcie Board
>> + #
>> + BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
>> +
>> ################################################################################
>> #
>> # Specific Platform Pcds
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
>> new file mode 100644
>> index 000000000000..8c8661265cd5
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
>> @@ -0,0 +1,42 @@
>> +## @file
>> +#
>> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +#
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +#
>> +##
>> +
>> +[Defines]
>> + INF_VERSION = 0x0001001B
>> + BASE_NAME = Ac01PcieLib
>> + FILE_GUID = 8ABFA0FC-313E-11E8-B467-0ED5F89F718B
>> + MODULE_TYPE = BASE
>> + VERSION_STRING = 1.0
>> + LIBRARY_CLASS = Ac01PcieLib
>> +
>> +[Sources]
>> + PcieCore.c
>> + PcieCore.h
>> +
>> +[Packages]
>> + ArmPkg/ArmPkg.dec
>> + MdePkg/MdePkg.dec
>> + Silicon/Ampere/AmpereAltraBinPkg/AmpereAltraBinPkg.dec
>> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
>> +
>> +[LibraryClasses]
>> + ArmGenericTimerCounterLib
>> + BaseLib
>> + BoardPcieLib
>> + DebugLib
>> + HobLib
>> + IoLib
>> + PciePhyLib
>> + SystemFirmwareInterfaceLib
>> + TimerLib
>> +
>> +[Guids]
>> + gPlatformInfoHobGuid
>> +
>> +[Depex]
>> + TRUE
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
>> new file mode 100644
>> index 000000000000..435092b864ec
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
>> @@ -0,0 +1,25 @@
>> +## @file
>> +#
>> +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +#
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +#
>> +##
>> +
>> +[Defines]
>> + INF_VERSION = 0x0001001B
>> + BASE_NAME = BoardPcieLibNull
>> + FILE_GUID = 7820C925-F525-4101-8E64-87838356B7A6
>> + MODULE_TYPE = BASE
>> + VERSION_STRING = 1.0
>> + LIBRARY_CLASS = BoardPcieLib
>> +
>> +[Sources.common]
>> + BoardPcieLibNull.c
>> +
>> +[Packages]
>> + MdePkg/MdePkg.dec
>> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
>> +
>> +[LibraryClasses]
>> + BaseLib
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
>> new file mode 100644
>> index 000000000000..53d3739af713
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
>> @@ -0,0 +1,49 @@
>> +/** @file
>> +
>> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef AC01_PCIE_LIB_H_
>> +#define AC01_PCIE_LIB_H_
>> +
>> +/**
>> + Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers
>> +
>> + @param RootComplex Pointer to Root Complex structure
>> + @param ReInit Re-init status
>> + @param ReInitPcieIndex PCIe index
>> +
>> + @retval RETURN_SUCCESS The Root Complex has been initialized successfully.
>> + @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready.
>> +**/
>> +RETURN_STATUS
>> +Ac01PcieCoreSetupRC (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN BOOLEAN ReInit,
>> + IN UINT8 ReInitPcieIndex
>> + );
>> +
>> +/**
>> + Verify the link status and retry to initialize the Root Complex if there's any issue.
>> +
>> + @param RootComplexList Pointer to the Root Complex list
>> +**/
>> +VOID
>> +Ac01PcieCorePostSetupRC (
>> + IN AC01_ROOT_COMPLEX *RootComplexList
>> + );
>> +
>> +/**
>> + Callback function when the Host Bridge enumeration end.
>> +
>> + @param RootComplex Pointer to the Root Complex structure
>> +**/
>> +VOID
>> +Ac01PcieCoreEndEnumeration (
>> + IN AC01_ROOT_COMPLEX *RootComplex
>> + );
>> +
>> +#endif /* AC01_PCIE_LIB_H_ */
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
>> new file mode 100644
>> index 000000000000..34e7dee702ec
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
>> @@ -0,0 +1,45 @@
>> +/** @file
>> +
>> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef BOARD_PCIE_LIB_H_
>> +#define BOARD_PCIE_LIB_H_
>> +
>> +#include <Guid/RootComplexInfoHob.h>
>> +
>> +/**
>> + Assert PERST of the PCIe controller
>> +
>> + @param[in] RootComplex Root Complex instance.
>> + @param[in] PcieIndex PCIe controller index of input Root Complex.
>> + @param[in] IsPullToHigh Target status for the PERST.
>> +
>> + @retval RETURN_SUCCESS The operation is successful.
>> + @retval Others An error occurred.
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +BoardPcieAssertPerst (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN BOOLEAN IsPullToHigh
>> + );
>> +
>> +/**
>> + Override the segment number for a root complex with a board specific number.
>> +
>> + @param[in] RootComplex Root Complex instance with properties.
>> +
>> + @retval Segment number corresponding to the input root complex.
>> + Default segment number is 0x0F.
>> +**/
>> +UINT16
>> +BoardPcieGetSegmentNumber (
>> + IN AC01_ROOT_COMPLEX *RootComplex
>> + );
>> +
>> +#endif /* BOARD_PCIE_LIB_H_ */
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
>> new file mode 100644
>> index 000000000000..f3f15c4c74df
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
>> @@ -0,0 +1,451 @@
>> +/** @file
>> +
>> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef AC01_PCIE_CORE_H_
>> +#define AC01_PCIE_CORE_H_
>> +
>> +//
>> +// PCIe config space capabilities offset
>> +//
>> +#define PM_CAP 0x40
>> +#define MSI_CAP 0x50
>> +#define PCIE_CAP 0x70
>> +#define MSIX_CAP 0xB0
>> +#define SLOT_CAP 0xC0
>> +#define VPD_CAP 0xD0
>> +#define SATA_CAP 0xE0
>> +#define CFG_NEXT_CAP 0x40
>> +#define PM_NEXT_CAP 0x70
>> +#define MSI_NEXT_CAP 0x00
>> +#define PCIE_NEXT_CAP 0x00
>> +#define MSIX_NEXT_CAP 0x00
>> +#define SLOT_NEXT_CAP 0x00
>> +#define VPD_NEXT_CAP 0x00
>> +#define SATA_NEXT_CAP 0x00
>> +#define BASE_CAP 0x100
>> +#define AER_CAP 0x100
>> +#define VC_CAP 0x148
>> +#define SN_CAP 0x178
>> +#define PB_CAP 0x178
>> +#define ARI_CAP 0x178
>> +#define SPCIE_CAP_x8 0x148
>> +#define SPCIE_CAP 0x178
>> +#define PL16G_CAP 0x1A8
>> +#define MARGIN_CAP 0x1D8
>> +#define PL32G_CAP 0x220
>> +#define SRIOV_CAP 0x220
>> +#define TPH_CAP 0x220
>> +#define ATS_CAP 0x220
>> +#define ACS_CAP 0x230
>> +#define PRS_CAP 0x238
>> +#define LTR_CAP 0x248
>> +#define L1SUB_CAP 0x248
>> +#define PASID_CAP 0x248
>> +#define DPA_CAP 0x248
>> +#define DPC_CAP 0x248
>> +#define MPCIE_CAP 0x248
>> +#define FRSQ_CAP 0x248
>> +#define RTR_CAP 0x248
>> +#define LN_CAP 0x248
>> +#define RAS_DES_CAP 0x248
>> +#define VSECRAS_CAP 0x348
>> +#define DLINK_CAP 0x380
>> +#define PTM_CAP 0x38C
>> +#define PTM_VSEC_CAP 0x38C
>> +#define CCIX_TP_CAP 0x38C
>> +#define CXS_CAP 0x3D0
>> +#define RBAR_CAP 0x3E8
>> +#define VF_RBAR_CAP 0x3E8
>> +
>> +#define MAX_REINIT 3
>> +
>> +#define SLOT_POWER_LIMIT 75 // Watt
>> +
>> +#define LINK_CHECK_SUCCESS 0
>> +#define LINK_CHECK_FAILED -1
>> +#define LINK_CHECK_WRONG_PARAMETER 1
>> +
>> +#define PFA_REG_ENABLE 0
>> +#define PFA_REG_READ 1
>> +#define PFA_REG_CLEAR 2
>> +
>> +#define AMPERE_PCIE_VENDORID 0x1DEF
>> +#define AC01_HOST_BRIDGE_DEVICEID_RCA 0xE100
>> +#define AC01_HOST_BRIDGE_DEVICEID_RCB 0xE110
>> +#define AC01_PCIE_BRIDGE_DEVICEID_RCA 0xE101
>> +#define AC01_PCIE_BRIDGE_DEVICEID_RCB 0xE111
>> +
>> +#define MEMRDY_TIMEOUT 10 // 10 us
>> +#define PIPE_CLOCK_TIMEOUT 20000 // 20,000 us
>> +#define LTSSM_TRANSITION_TIMEOUT 100000 // 100 ms in total
>> +#define EP_LINKUP_TIMEOUT (10 * 1000) // 10ms
>> +#define LINK_WAIT_INTERVAL_US 50
>> +
>> +//
>> +// DATA LINK registers
>> +//
>> +#define DLINK_VENDOR_CAP_ID 0x25
>> +#define DLINK_VSEC 0x80000001
>> +#define DATA_LINK_FEATURE_CAP_OFF 0x04
>> +
>> +//
>> +// PL16 CAP registers
>> +//
>> +#define PL16_CAP_ID 0x26
>> +#define PL16G_CAP_OFF_20H_REG_OFF 0x20
>> +#define PL16G_STATUS_REG_OFF 0x0C
>> +#define PL16G_STATUS_EQ_CPL_GET(val) (val & 0x1)
>> +#define PL16G_STATUS_EQ_CPL_P1_GET(val) ((val & 0x2) >> 1)
>> +#define PL16G_STATUS_EQ_CPL_P2_GET(val) ((val & 0x4) >> 2)
>> +#define PL16G_STATUS_EQ_CPL_P3_GET(val) ((val & 0x8) >> 3)
>> +#define DSP_16G_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +#define DSP_16G_TX_PRESET1_SET(dst,src) (((dst) & ~0xF00) | (((UINT32) (src) << 8) & 0xF00))
>> +#define DSP_16G_TX_PRESET2_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
>> +#define DSP_16G_TX_PRESET3_SET(dst,src) (((dst) & ~0xF000000) | (((UINT32) (src) << 24) & 0xF000000))
>> +#define DSP_16G_RXTX_PRESET0_SET(dst,src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +#define DSP_16G_RXTX_PRESET1_SET(dst,src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +#define DSP_16G_RXTX_PRESET2_SET(dst,src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
>> +#define DSP_16G_RXTX_PRESET3_SET(dst,src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000))
>> +
>> +//
>> +// PCIe PF0_PORT_LOGIC registers
>> +//
>> +#define PORT_LOCIG_VC0_P_RX_Q_CTRL_OFF 0x748
>> +#define PORT_LOCIG_VC0_NP_RX_Q_CTRL_OFF 0x74C
>> +
>> +//
>> +// SNPSRAM Synopsys Memory Read/Write Margin registers
>> +//
>> +#define SPRF_RMR 0x0
>> +#define SPSRAM_RMR 0x4
>> +#define TPRF_RMR 0x8
>> +#define TPSRAM_RMR 0xC
>> +
>> +//
>> +// Host bridge registers
>> +//
>> +#define HBRCAPDMR 0x0
>> +#define HBRCBPDMR 0x4
>> +#define HBPDVIDR 0x10
>> +#define HBPRBNR 0x14
>> +#define HBPREVIDR 0x18
>> +#define HBPSIDR 0x1C
>> +#define HBPCLSSR 0x20
>> +
>> +// HBRCAPDMR
>> +#define RCAPCIDEVMAP_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
>> +#define RCAPCIDEVMAP_GET(val) ((val) & 0x7)
>> +
>> +// HBRCBPDMR
>> +#define RCBPCIDEVMAPLO_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
>> +#define RCBPCIDEVMAPLO_GET(val) ((val) & 0x7)
>> +
>> +#define RCBPCIDEVMAPHI_SET(dst, src) (((dst) & ~0x70) | (((UINT32) (src) << 4) & 0x70))
>> +#define RCBPCIDEVMAPHI_GET(val) (((val) & 0x7) >> 4)
>> +
>> +// HBPDVIDR
>> +#define PCIVENDID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
>> +#define PCIVENDID_GET(val) ((val) & 0xFFFF)
>> +
>> +#define PCIDEVID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
>> +#define PCIDEVID_GET(val) (((val) & 0xFFFF0000) >> 16)
>> +
>> +// HBPRBNR
>> +#define PCIRBNUM_SET(dst, src) (((dst) & ~0x1F) | (((UINT32) (src)) & 0x1F))
>> +
>> +// HBPREVIDR
>> +#define PCIREVID_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +
>> +// HBPSIDR
>> +#define PCISUBSYSVENDID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
>> +
>> +#define PCISUBSYSID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
>> +
>> +// HBPCLSSR
>> +#define CACHELINESIZE_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +
>> +//
>> +// PCIE core register
>> +//
>> +#define LINKCTRL 0x0
>> +#define LINKSTAT 0x4
>> +#define IRQSEL 0xC
>> +#define HOTPLUGSTAT 0x28
>> +#define IRQENABLE 0x30
>> +#define IRQEVENTSTAT 0x38
>> +#define BLOCKEVENTSTAT 0x3c
>> +#define RESET 0xC000
>> +#define CLOCK 0xC004
>> +#define MEMRDYR 0xC104
>> +#define RAMSDR 0xC10C
>> +
>> +// LINKCTRL
>> +#define LTSSMENB_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define DEVICETYPE_SET(dst, src) (((dst) & ~0xF0) | (((UINT32) (src) << 4) & 0xF0))
>> +#define DEVICETYPE_GET(val) (((val) & 0xF0) >> 4)
>> +
>> +// LINKSTAT
>> +#define PHY_STATUS_MASK (1 << 2)
>> +#define SMLH_LTSSM_STATE_MASK 0x3f00
>> +#define SMLH_LTSSM_STATE_GET(val) ((val & 0x3F00) >> 8)
>> +#define RDLH_SMLH_LINKUP_STATUS_GET(val) (val & 0x3)
>> +#define PHY_STATUS_MASK_BIT 0x04
>> +#define SMLH_LINK_UP_MASK_BIT 0x02
>> +#define RDLH_LINK_UP_MASK_BIT 0x01
>> +
>> +#define LTSSM_STATE_L0 0x11
>> +
>> +// IRQSEL
>> +#define AER_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define PME_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
>> +#define LINKAUTOBW_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
>> +#define BWMGMT_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8))
>> +#define EQRQST_SET(dst, src) (((dst) & ~0x10) | (((UINT32) (src) << 4) & 0x10))
>> +#define INTPIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +
>> +// SLOTCAP
>> +#define SLOT_HPC_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
>> +
>> +// SLOT_CAPABILITIES_REG, PCIE_CAP_SLOT_POWER_LIMIT_VALUE bits[14:7]
>> +#define SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET(dst, src) \
>> + (((dst) & ~0x7F80) | (((UINT32)(src) << 7) & 0x7F80))
>> +
>> +// HOTPLUGSTAT
>> +#define PWR_IND_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define ATTEN_IND_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
>> +#define PWR_CTRL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
>> +#define EML_CTRL_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8))
>> +
>> +// IRQENABLE
>> +#define LINKUP_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
>> +
>> +// IRQEVENTSTAT
>> +#define BLOCK_INT_MASK BIT4
>> +#define INT_MASK BIT3
>> +
>> +// BLOCKEVENTSTAT
>> +#define LINKUP_MASK BIT0
>> +
>> +// RESET
>> +#define DWCPCIE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define RESET_MASK 0x1
>> +
>> +// CLOCK
>> +#define AXIPIPE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +// RAMSDR
>> +#define SD_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +//
>> +// PHY registers
>> +//
>> +#define RSTCTRL 0x0
>> +#define PHYCTRL 0x4
>> +#define RAMCTRL 0x8
>> +#define RAMSTAT 0xC
>> +#define PLLCTRL 0x10
>> +#define PHYLPKCTRL 0x14
>> +#define PHYTERMOFFSET0 0x18
>> +#define PHYTERMOFFSET1 0x1C
>> +#define PHYTERMOFFSET2 0x20
>> +#define PHYTERMOFFSET3 0x24
>> +#define RXTERM 0x28
>> +#define PHYDIAGCTRL 0x2C
>> +
>> +// RSTCTRL
>> +#define PHY_RESET_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +// PHYCTRL
>> +#define PWR_STABLE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +//
>> +// PCIe config space registers
>> +//
>> +#define TYPE1_DEV_ID_VEND_ID_REG 0
>> +#define TYPE1_CLASS_CODE_REV_ID_REG 0x8
>> +#define TYPE1_CAP_PTR_REG 0x34
>> +#define SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG 0x18
>> +#define BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3c
>> +#define CON_STATUS_REG (PM_CAP + 0x4)
>> +#define LINK_CAPABILITIES_REG (PCIE_CAP + 0xc)
>> +#define LINK_CONTROL_LINK_STATUS_REG (PCIE_CAP + 0x10)
>> +#define SLOT_CAPABILITIES_REG (PCIE_CAP + 0x14)
>> +#define DEVICE_CONTROL2_DEVICE_STATUS2_REG (PCIE_CAP + 0x28)
>> +#define LINK_CAPABILITIES2_REG (PCIE_CAP + 0x2c)
>> +#define LINK_CONTROL2_LINK_STATUS2_REG (PCIE_CAP + 0x30)
>> +#define UNCORR_ERR_STATUS_OFF (AER_CAP + 0x4)
>> +#define UNCORR_ERR_MASK_OFF (AER_CAP + 0x8)
>> +#define RESOURCE_CON_REG_VC0 (VC_CAP + 0x14)
>> +#define RESOURCE_CON_REG_VC1 (VC_CAP + 0x20)
>> +#define RESOURCE_STATUS_REG_VC1 (VC_CAP + 0x24)
>> +#define SD_CONTROL1_REG (RAS_DES_CAP+0xA0)
>> +#define CCIX_TP_CAP_TP_HDR2_OFF (CCIX_TP_CAP + 0x8)
>> +#define ESM_MNDTRY_RATE_CAP_OFF (CCIX_TP_CAP + 0xc)
>> +#define ESM_STAT_OFF (CCIX_TP_CAP + 0x14)
>> +#define ESM_CNTL_OFF (CCIX_TP_CAP + 0x18)
>> +#define ESM_LN_EQ_CNTL_25G_0_OFF (CCIX_TP_CAP + 0x2c)
>> +#define PORT_LINK_CTRL_OFF 0x710
>> +#define FILTER_MASK_2_OFF 0x720
>> +#define GEN2_CTRL_OFF 0x80c
>> +#define GEN3_RELATED_OFF 0x890
>> +#define GEN3_EQ_CONTROL_OFF 0x8A8
>> +#define MISC_CONTROL_1_OFF 0x8bc
>> +#define AMBA_ERROR_RESPONSE_DEFAULT_OFF 0x8d0
>> +#define AMBA_LINK_TIMEOUT_OFF 0x8d4
>> +#define AMBA_ORDERING_CTRL_OFF 0x8d8
>> +#define DTIM_CTRL0_OFF 0xab0
>> +#define AUX_CLK_FREQ_OFF 0xb40
>> +#define CCIX_CTRL_OFF 0xc20
>> +
>> +// TYPE1_DEV_ID_VEND_ID_REG
>> +#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
>> +#define DEVICE_ID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
>> +
>> +// TYPE1_CLASS_CODE_REV_ID_REG
>> +#define BASE_CLASS_CODE_SET(dst, src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000))
>> +#define SUBCLASS_CODE_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
>> +#define PROGRAM_INTERFACE_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +#define REVISION_ID_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +
>> +// SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG
>> +#define DEFAULT_SUB_BUS 0xFF
>> +#define SUB_BUS_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
>> +#define SEC_BUS_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +#define PRIM_BUS_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +
>> +// BRIDGE_CTRL_INT_PIN_INT_LINE_REG
>> +#define INT_PIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +
>> +// CON_STATUS_REG
>> +#define POWER_STATE_SET(dst, src) (((dst) & ~0x3) | (((UINT32) (src)) & 0x3))
>> +
>> +// DEVICE_CONTROL2_DEVICE_STATUS2_REG
>> +#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +
>> +// LINK_CAPABILITIES_REG
>> +#define CAP_ID 0x10
>> +#define LINK_CAPABILITIES_REG_OFF 0xC
>> +#define LINK_CONTROL_LINK_STATUS_OFF 0x10
>> +#define CAP_MAX_LINK_WIDTH_X1 0x1
>> +#define CAP_MAX_LINK_WIDTH_X2 0x2
>> +#define CAP_MAX_LINK_WIDTH_X4 0x4
>> +#define CAP_MAX_LINK_WIDTH_X8 0x8
>> +#define CAP_MAX_LINK_WIDTH_X16 0x10
>> +#define CAP_MAX_LINK_WIDTH_GET(val) ((val & 0x3F0) >> 4)
>> +#define CAP_MAX_LINK_WIDTH_SET(dst, src) (((dst) & ~0x3F0) | (((UINT32) (src) << 4) & 0x3F0))
>> +#define MAX_LINK_SPEED_25 0x1
>> +#define MAX_LINK_SPEED_50 0x2
>> +#define MAX_LINK_SPEED_80 0x3
>> +#define MAX_LINK_SPEED_160 0x4
>> +#define MAX_LINK_SPEED_320 0x5
>> +#define CAP_MAX_LINK_SPEED_GET(val) ((val & 0xF))
>> +#define CAP_MAX_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +#define CAP_SLOT_CLK_CONFIG_SET(dst, src) (((dst) & ~0x10000000) | (((UINT32) (src) << 28) & 0x10000000))
>> +#define NO_ASPM_SUPPORTED 0x0
>> +#define L0S_SUPPORTED 0x1
>> +#define L1_SUPPORTED 0x2
>> +#define L0S_L1_SUPPORTED 0x3
>> +#define CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET(dst, src) (((dst) & ~0xC00) | (((UINT32)(src) << 10) & 0xC00))
>> +
>> +// LINK_CONTROL_LINK_STATUS_REG
>> +#define CAP_DLL_ACTIVE_GET(val) ((val & 0x20000000) >> 29)
>> +#define CAP_NEGO_LINK_WIDTH_GET(val) ((val & 0x3F00000) >> 20)
>> +#define CAP_LINK_SPEED_GET(val) ((val & 0xF0000) >> 16)
>> +#define CAP_LINK_SPEED_SET(dst, src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
>> +#define CAP_LINK_SPEED_TO_VECTOR(val) (1 << ((val)-1))
>> +#define CAP_EN_CLK_POWER_MAN_GET(val) ((val & 0x100) >> 8)
>> +#define CAP_EN_CLK_POWER_MAN_SET(dst, src) (((dst) & ~0x100) | (((UINT32) (src) << 8) & 0x100))
>> +#define CAP_RETRAIN_LINK_SET(dst, src) (((dst) & ~0x20) | (((UINT32) (src) << 5) & 0x20))
>> +#define CAP_COMMON_CLK_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
>> +#define CAP_LINK_TRAINING_GET(val) ((val & 0x8000000) >> 27)
>> +#define CAP_LINK_DISABLE_SET(dst, src) (((dst) & ~0x10) | (((UINT32)(src) << 4) & 0x10))
>> +
>> +// LINK_CONTROL2_LINK_STATUS2_REG
>> +#define CAP_TARGET_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +
>> +// Secondary Capability
>> +#define SPCIE_CAP_ID 0x19
>> +#define CAP_OFF_0C 0x0C
>> +#define LINK_CONTROL3_REG_OFF 0x4
>> +#define DSP_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +#define DSP_TX_PRESET1_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
>> +
>> +// UNCORR_ERR_MASK_OFF
>> +#define CMPLT_TIMEOUT_ERR_MASK_SET(dst, src) (((dst) & ~0x4000) | (((UINT32) (src) << 14) & 0x4000))
>> +#define SDES_ERR_MASK_SET(dst, src) (((dst) & ~0x20) | (((UINT32)(src) << 5) & 0x20))
>> +
>> +// PORT_LINK_CTRL_OFF
>> +#define LINK_CAPABLE_X1 0x1
>> +#define LINK_CAPABLE_X2 0x3
>> +#define LINK_CAPABLE_X4 0x7
>> +#define LINK_CAPABLE_X8 0xF
>> +#define LINK_CAPABLE_X16 0x1F
>> +#define LINK_CAPABLE_X32 0x3F
>> +#define LINK_CAPABLE_SET(dst, src) (((dst) & ~0x3F0000) | (((UINT32) (src) << 16) & 0x3F0000))
>> +#define FAST_LINK_MODE_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80))
>> +
>> +// FILTER_MASK_2_OFF
>> +#define CX_FLT_MASK_VENMSG0_DROP_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define CX_FLT_MASK_VENMSG1_DROP_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
>> +#define CX_FLT_MASK_DABORT_4UCPL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
>> +
>> +// GEN2_CTRL_OFF
>> +#define NUM_OF_LANES_X2 0x2
>> +#define NUM_OF_LANES_X4 0x4
>> +#define NUM_OF_LANES_X8 0x8
>> +#define NUM_OF_LANES_X16 0x10
>> +#define NUM_OF_LANES_SET(dst, src) (((dst) & ~0x1F00) | (((UINT32) (src) << 8) & 0x1F00))
>> +
>> +// GEN3_RELATED_OFF
>> +#define RATE_SHADOW_SEL_SET(dst, src) (((dst) & ~0x3000000) | (((UINT32) (src) << 24) & 0x3000000))
>> +#define EQ_PHASE_2_3_SET(dst, src) (((dst) & ~0x200) | (((UINT32) (src) << 9) & 0x200))
>> +#define RXEQ_REGRDLESS_SET(dst, src) (((dst) & ~0x2000) | (((UINT32) (src) << 13) & 0x2000))
>> +
>> +// GEN3_EQ_CONTROL_OFF
>> +#define GEN3_EQ_FB_MODE(dst, src) (((dst) & ~0xF) | ((UINT32) (src) & 0xF))
>> +#define GEN3_EQ_PRESET_VEC(dst, src) (((dst) & 0xFF0000FF) | (((UINT32) (src) << 8) & 0xFFFF00))
>> +#define GEN3_EQ_INIT_EVAL(dst,src) (((dst) & ~0x1000000) | (((UINT32) (src) << 24) & 0x1000000))
>> +
>> +// MISC_CONTROL_1_OFF
>> +#define DBI_RO_WR_EN_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +// AMBA_ERROR_RESPONSE_DEFAULT_OFF
>> +#define AMBA_ERROR_RESPONSE_CRS_SET(dst, src) (((dst) & ~0x18) | (((UINT32) (src) << 3) & 0x18))
>> +#define AMBA_ERROR_RESPONSE_GLOBAL_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +// AMBA_LINK_TIMEOUT_OFF
>> +#define LINK_TIMEOUT_PERIOD_DEFAULT_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +
>> +// AMBA_ORDERING_CTRL_OFF
>> +#define AX_MSTR_ZEROLREAD_FW_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80))
>> +
>> +// DTIM_CTRL0_OFF
>> +#define DTIM_CTRL0_ROOT_PORT_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
>> +
>> +// AUX_CLK_FREQ_OFF
>> +#define AUX_CLK_500MHZ 500
>> +#define AUX_CLK_FREQ_SET(dst, src) (((dst) & ~0x1FF) | (((UINT32) (src)) & 0x1FF))
>> +
>> +#define EXT_CAP_OFFSET_START 0x100
>> +
>> +// EVENT_COUNTER_CONTROL_REG
>> +#define ECCR_GROUP_EVENT_SEL_SET(dst, src) (((dst) & ~0xFFF0000) | (((UINT32)(src) << 16) & 0xFFF0000))
>> +#define ECCR_GROUP_SEL_SET(dst, src) (((dst) & ~0xF000000) | (((UINT32)(src) << 24) & 0xF000000))
>> +#define ECCR_EVENT_SEL_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32)(src) << 16) & 0xFF0000))
>> +#define ECCR_LANE_SEL_SET(dst, src) (((dst) & ~0xF00) | (((UINT32)(src) << 8) & 0xF00))
>> +#define ECCR_EVENT_COUNTER_ENABLE_SET(dst, src) (((dst) & ~0x1C) | (((UINT32)(src) << 2) & 0x1C))
>> +#define ECCR_EVENT_COUNTER_CLEAR_SET(dst, src) (((dst) & ~0x3) | (((UINT32)(src)) & 0x3))
>> +
>> +// PFA Registers offests
>> +#define RAS_DES_CAP_ID 0xB
>> +#define EVENT_COUNTER_CONTROL_REG_OFF 0x8
>> +#define EVENT_COUNTER_DATA_REG_OFF 0xC
>> +
>> +#define MAX_NUM_ERROR_CODE 47
>> +
>> +#endif /* AC01_PCIE_CORE_H_ */
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
>> new file mode 100644
>> index 000000000000..c546ee8330b9
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
>> @@ -0,0 +1,1391 @@
>> +/** @file
>> +
>> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#include <PiDxe.h>
>> +
>> +#include <Guid/PlatformInfoHob.h>
>> +#include <Guid/RootComplexInfoHob.h>
>> +#include <Library/ArmGenericTimerCounterLib.h>
>> +#include <Library/BaseLib.h>
>> +#include <Library/BoardPcieLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/HobLib.h>
>> +#include <Library/IoLib.h>
>> +#include <Library/PciePhyLib.h>
>> +#include <Library/SystemFirmwareInterfaceLib.h>
>> +#include <Library/TimerLib.h>
>> +
>> +#include "PcieCore.h"
>> +
>> +/**
>> + Return the next extended capability address
>> +
>> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex PCIe index
>> + @param IsRC TRUE: Checking RootComplex configuration space
>> + FALSE: Checking EP configuration space
>> + @param ExtendedCapId
>> +**/
>> +UINT64
>> +PcieCheckCap (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN BOOLEAN IsRC,
> IsRootComplex.
>
>> + IN UINT16 ExtendedCapId
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + UINT32 Val = 0, NextCap = 0, CapId = 0, ExCap = 0;
> NextCap is clear...ish, CapId likewise. ExCap is not. Please give it a
> proper name.
>
>> +
>> + if (IsRC) {
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> + } else {
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 20);
> Please, some macros for those live integers.
>
>> + }
>> +
>> + Val = MmioRead32 (CfgAddr + TYPE1_CAP_PTR_REG);
>> + NextCap = Val & 0xFF;
> Macro.
>
>> +
>> + // Loop untill desired capability is found else return 0
>> + while (1) {
>> + if ((NextCap & 0x3) != 0) {
> Macro.
>
>> + // Not alignment, just return
>> + return 0;
>> + }
>> + Val = MmioRead32 (CfgAddr + NextCap);
>> + if (NextCap < EXT_CAP_OFFSET_START) {
>> + CapId = Val & 0xFF;
> Macro.
>
>> + } else {
>> + CapId = Val & 0xFFFF;
> Macro.
> (OK, I'll stop here - but please excise every single instance of a
> live-coded integer, with the potential exception of 0, from .c files.)
>
>> + }
>> +
>> + if (CapId == ExtendedCapId) {
>> + return (UINT64)(CfgAddr + NextCap);
>> + }
>> +
>> + if (NextCap < EXT_CAP_OFFSET_START) {
>> + NextCap = (Val & 0xFFFF) >> 8;
>> + } else {
>> + NextCap = (Val & 0xFFFF0000) >> 20;
>> + }
>> +
>> + if ((NextCap == 0) && (ExCap == 0)) {
>> + ExCap = 1;
>> + NextCap = EXT_CAP_OFFSET_START;
>> + }
>> +
>> + if ((NextCap == 0) && (ExCap == 1)) {
>> + return (UINT64)0;
>> + }
>> + }
>> +}
>> +
>> +/**
>> + Configure equalization settings
>> +
>> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex PCIe index
>> +**/
>> +STATIC
>> +VOID
>> +ConfigureEqualization (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + UINT32 Val;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Select the FoM method, need double-write to convey settings
>> + Val = MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF);
>> + Val = GEN3_EQ_FB_MODE (Val, 0x1);
>> + Val = GEN3_EQ_PRESET_VEC (Val, 0x3FF);
>> + Val = GEN3_EQ_INIT_EVAL (Val, 0x1);
> The double-write part of the above comment should be moved here, and
> improved. Explain why the double-write is needed.
>
>> + MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val);
>> + MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val);
>> + Val = MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF);
> This function retrieves CfgAddr once and gives it a variable.
> It then performs four accesses to same offset from that address,
> and writes out the arithmetic on each instance.
> This is not the balance I would have chosen.
>
>> +}
>> +
>> +/**
>> + Configure presets for GEN3 equalization
>> +
>> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex PCIe index
>> +**/
>> +STATIC
>> +VOID
>> +ConfigurePresetGen3 (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr, SpcieBaseAddr;
>> + UINT32 Val, Idx;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Bring to legacy mode
>> + Val = MmioRead32 (CfgAddr + GEN3_RELATED_OFF);
>> + Val = RATE_SHADOW_SEL_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
>> + Val = EQ_PHASE_2_3_SET (Val, 0);
>> + Val = RXEQ_REGRDLESS_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
> Same pattern again - a series of accesses to the same offset register,
> writing out the offset every time instead of assigning it to a variable.
>
>> +
>> + // Generate SPCIE capability address
> What's an SPCIE?
>
>> + SpcieBaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_ID);
>> + if (SpcieBaseAddr == 0) {
>> + DEBUG ((
>> + DEBUG_ERROR,
>> + "PCIE%d.%d: Cannot get SPCIE capability address\n",
>> + RootComplex->ID,
>> + PcieIndex
>> + ));
>> + return;
>> + }
>> +
>> + for (Idx=0; Idx < RootComplex->Pcie[PcieIndex].MaxWidth/2; Idx++) {
> What's with the 2?
>
>> + // Program Preset to Gen3 EQ Lane Control
>> + Val = MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4);
> (Idx * 4) or (Idx * sizeof (UINT32))?
>
>> + Val = DSP_TX_PRESET0_SET (Val, 0x7);
>> + Val = DSP_TX_PRESET1_SET (Val, 0x7);
>> + MmioWrite32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4, Val);
> Only two addresses to the same offset, but would still be clearer
> assigned to a variable.
>
>> + }
>> +}
>> +
>> +/**
>> + Configure presets for GEN4 equalization
>> +
>> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex PCIe controller index
>> +**/
>> +STATIC
>> +VOID
>> +ConfigurePresetGen4 (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr, SpcieBaseAddr, Pl16BaseAddr;
>> + UINT32 LinkWidth, Idx;
>> + UINT32 Val;
>> + UINT8 Preset;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Bring to legacy mode
>> + Val = MmioRead32 (CfgAddr + GEN3_RELATED_OFF);
>> + Val = RATE_SHADOW_SEL_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
>> + Val = EQ_PHASE_2_3_SET (Val, 0);
>> + Val = RXEQ_REGRDLESS_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
> OK, last time I'm commenting on this as well - please go through and
> replace Address + OFFSET with a temporary variable wherever more than
> one access to the same offset register is made in sequence.
>
> It doesn't even need to be an additional variable unless you need to
> access multiple offset registers from the same base in the same
> function - you could do something like
>
> RegAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15)
> + GEN3_RELATED_OFF;
>
> (although obviously not with a live-coded 15)
>
>> +
>> + // Generate the PL16 capability address
>> + Pl16BaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, PL16_CAP_ID);
>> + if (Pl16BaseAddr == 0) {
>> + DEBUG ((
>> + DEBUG_ERROR,
>> + "PCIE%d.%d: Cannot get PL16 capability address\n",
>> + RootComplex->ID,
>> + PcieIndex
>> + ));
>> + return;
>> + }
>> +
>> + // Generate the SPCIE capability address
>> + SpcieBaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_ID);
>> + if (SpcieBaseAddr == 0) {
>> + DEBUG ((
>> + DEBUG_ERROR,
>> + "PCIE%d.%d: Cannot get SPICE capability address\n",
>> + RootComplex->ID,
>> + PcieIndex
>> + ));
>> + return;
>> + }
>> +
>> + // Configure downstream Gen4 Tx preset
>> + if (RootComplex->PresetGen4[PcieIndex] == PRESET_INVALID) {
>> + Preset = 0x57; // Default Gen4 preset
>> + } else {
>> + Preset = RootComplex->PresetGen4[PcieIndex];
>> + }
>> +
>> + LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
>> + if (LinkWidth == 0x2) {
>> + Val = MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF);
>> + Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
>> + Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
>> + MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF, Val);
>> + } else {
>> + for (Idx = 0; Idx < LinkWidth/4; Idx++) {
>> + Val = MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4);
>> + Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
>> + Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
>> + Val = DSP_16G_RXTX_PRESET2_SET (Val, Preset);
>> + Val = DSP_16G_RXTX_PRESET3_SET (Val, Preset);
>> + MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4, Val);
>> + }
>> + }
>> +
>> + // Configure Gen3 preset
>> + for (Idx = 0; Idx < LinkWidth/2; Idx++) {
>> + Val = MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4);
>> + Val = DSP_TX_PRESET0_SET (Val, 0x7);
>> + Val = DSP_TX_PRESET1_SET (Val, 0x7);
>> + MmioWrite32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4, Val);
>> + }
>> +}
>> +
>> +INT8
>> +RasdpMitigation (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr, DlinkBaseAddr, SnpsRamBase;
>> + PLATFORM_INFO_HOB *PlatformHob;
>> + UINT16 NextExtendedCapabilityOff;
>> + UINT32 Val;
>> + UINT32 VsecVal;
>> + VOID *Hob;
>> +
>> + SnpsRamBase = RootComplex->Pcie[PcieIndex].SnpsRamBase;
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + Hob = GetFirstGuidHob (&gPlatformInfoHobGuid);
>> + PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
>> + if ((PlatformHob->ScuProductId[0] & 0xff) == 0x01
>> + && AsciiStrCmp ((CONST CHAR8 *)PlatformHob->CpuVer, "A0") == 0
>> + && (RootComplex->Type == RootComplexTypeB || PcieIndex > 0)) {
>> + // Change the Read Margin dual ported RAMs
>> + Val = 0x10; // Margin to 0x0 (most conservative setting)
>> + MmioWrite32 (SnpsRamBase + TPSRAM_RMR, Val);
>> +
>> + // Generate the DLINK capability address
>> + DlinkBaseAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> + NextExtendedCapabilityOff = 0x100; // This is the 1st extended capability offset
>> + do {
>> + Val = MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff);
>> + if (Val == 0xFFFFFFFF) {
>> + DlinkBaseAddr = 0x0;
>> + break;
>> + }
>> + if ((Val & 0xFFFF) == DLINK_VENDOR_CAP_ID) {
>> + VsecVal = MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff + 0x4);
>> + if (VsecVal == DLINK_VSEC) {
>> + DlinkBaseAddr = DlinkBaseAddr + NextExtendedCapabilityOff;
>> + break;
>> + }
>> + }
>> + NextExtendedCapabilityOff = (Val >> 20);
>> + } while (NextExtendedCapabilityOff != 0);
>> +
>> + // Disable the scaled credit mode
>> + if (DlinkBaseAddr != 0x0) {
>> + Val = 1;
>> + MmioWrite32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF, Val);
>> + Val = MmioRead32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF);
>> + if (Val != 1) {
>> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Unable to disable scaled credit\n", PcieIndex));
>> + return -1;
>> + }
>> + } else {
>> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Unable to locate data link feature cap offset\n", PcieIndex));
>> + return -1;
>> + }
>> +
>> + // Reduce Posted Credits to 1 packet header and data credit for all
>> + // impacted controllers. Also zero credit scale values for both
>> + // data and packet headers.
>> + Val=0x40201020;
>> + MmioWrite32 (CfgAddr + PORT_LOCIG_VC0_P_RX_Q_CTRL_OFF, Val);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +VOID
>> +ProgramHostBridge (
>> + AC01_ROOT_COMPLEX *RootComplex
>> + )
>> +{
>> + UINT32 Val;
>> +
>> + // Program Root Complex Bifurcation
>> + if (RootComplex->Active) {
>> + if (RootComplex->Type == RootComplexTypeA) {
>> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCAPDMR, &Val))) {
>> + Val = RCAPCIDEVMAP_SET (Val, RootComplex->DevMapLow);
>> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCAPDMR, Val);
>> + }
>> + } else {
>> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCBPDMR, &Val))) {
>> + Val = RCBPCIDEVMAPLO_SET (Val, RootComplex->DevMapLow);
>> + Val = RCBPCIDEVMAPHI_SET (Val, RootComplex->DevMapHigh);
>> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCBPDMR, Val);
>> + }
>> + }
>> + }
>> +
>> + // Program VendorID and DeviceId
>> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBPDVIDR, &Val))) {
>> + Val = PCIVENDID_SET (Val, AMPERE_PCIE_VENDORID);
>> + if (RootComplexTypeA == RootComplex->Type) {
>> + Val = PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCA);
>> + } else {
>> + Val = PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCB);
>> + }
>> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBPDVIDR, Val);
>> + }
>> +}
>> +
>> +VOID
>> +ProgramLinkCapabilities (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + UINT32 Val;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + Val = MmioRead32 (CfgAddr + PORT_LINK_CTRL_OFF);
>> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
>> + case LINK_WIDTH_X2:
>> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X2);
>> + break;
>> +
>> + case LINK_WIDTH_X4:
>> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X4);
>> + break;
>> +
>> + case LINK_WIDTH_X8:
>> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X8);
>> + break;
>> +
>> + case LINK_WIDTH_X16:
>> + default:
>> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X16);
>> + break;
>> + }
>> + MmioWrite32 (CfgAddr + PORT_LINK_CTRL_OFF, Val);
>> + Val = MmioRead32 (CfgAddr + GEN2_CTRL_OFF);
>> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
>> + case LINK_WIDTH_X2:
>> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X2);
>> + break;
>> +
>> + case LINK_WIDTH_X4:
>> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X4);
>> + break;
>> +
>> + case LINK_WIDTH_X8:
>> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X8);
>> + break;
>> +
>> + case LINK_WIDTH_X16:
>> + default:
>> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X16);
>> + break;
>> + }
>> + MmioWrite32 (CfgAddr + GEN2_CTRL_OFF, Val);
>> + Val = MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG);
>> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
>> + case LINK_WIDTH_X2:
>> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X2);
>> + break;
>> +
>> + case LINK_WIDTH_X4:
>> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X4);
>> + break;
>> +
>> + case LINK_WIDTH_X8:
>> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X8);
>> + break;
>> +
>> + case LINK_WIDTH_X16:
>> + default:
>> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X16);
>> + break;
>> + }
>> +
>> + switch (RootComplex->Pcie[PcieIndex].MaxGen) {
>> + case LINK_SPEED_GEN1:
>> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
>> + break;
>> +
>> + case LINK_SPEED_GEN2:
>> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
>> + break;
>> +
>> + case LINK_SPEED_GEN3:
>> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
>> + break;
>> +
>> + default:
>> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
>> + break;
>> + }
>> + /* Enable ASPM Capability */
>> + Val = CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET (Val, L0S_L1_SUPPORTED);
>> + MmioWrite32 (CfgAddr + LINK_CAPABILITIES_REG, Val);
>> +
>> + Val = MmioRead32 (CfgAddr + LINK_CONTROL2_LINK_STATUS2_REG);
>> + switch (RootComplex->Pcie[PcieIndex].MaxGen) {
>> + case LINK_SPEED_GEN1:
>> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
>> + break;
>> +
>> + case LINK_SPEED_GEN2:
>> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
>> + break;
>> +
>> + case LINK_SPEED_GEN3:
>> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
>> + break;
>> +
>> + default:
>> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
>> + break;
>> + }
>> + MmioWrite32 (CfgAddr + LINK_CONTROL2_LINK_STATUS2_REG, Val);
>> +}
>> +
>> +VOID
>> +MaskCompletionTimeOut (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN UINT32 TimeOut,
>> + IN BOOLEAN IsMask
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + UINT32 Val;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + Val = MmioRead32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF);
>> + Val = LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, TimeOut);
>> + MmioWrite32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF, Val);
>> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
>> + Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0);
>> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val);
>> +}
>> +
>> +BOOLEAN
>> +PollMemReady (
>> + PHYSICAL_ADDRESS CsrBase
>> + )
>> +{
>> + UINT32 TimeOut;
>> + UINT32 Val;
>> +
>> + // Poll till mem is ready
> What mem?
>
> /
> Leif
>
>> + TimeOut = MEMRDY_TIMEOUT;
>> + do {
>> + Val = MmioRead32 (CsrBase + MEMRDYR);
>> + if (Val & 1) {
>> + break;
>> + }
>> +
>> + TimeOut--;
>> + MicroSecondDelay (1);
>> + } while (TimeOut > 0);
>> +
>> + if (TimeOut <= 0) {
>> + return FALSE;
>> + }
>> +
>> + return TRUE;
>> +}
>> +
>> +BOOLEAN
>> +PollPipeReady (
>> + PHYSICAL_ADDRESS CsrBase
>> + )
>> +{
>> + UINT32 TimeOut;
>> + UINT32 Val;
>> +
>> + // Poll till PIPE clock is stable
>> + TimeOut = PIPE_CLOCK_TIMEOUT;
>> + do {
>> + Val = MmioRead32 (CsrBase + LINKSTAT);
>> + if (!(Val & PHY_STATUS_MASK)) {
>> + break;
>> + }
>> +
>> + TimeOut--;
>> + MicroSecondDelay (1);
>> + } while (TimeOut > 0);
>> +
>> + if (TimeOut <= 0) {
>> + return FALSE;
>> + }
>> +
>> + return TRUE;
>> +}
>> +
>> +/**
>> + Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers
>> +
>> + @param RootComplex Pointer to Root Complex structure
>> + @param ReInit Re-init status
>> + @param ReInitPcieIndex PCIe index
>> +
>> + @retval RETURN_SUCCESS The Root Complex has been initialized successfully.
>> + @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready.
>> +**/
>> +RETURN_STATUS
>> +Ac01PcieCoreSetupRC (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN BOOLEAN ReInit,
>> + IN UINT8 ReInitPcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CsrBase, CfgAddr;
>> + RETURN_STATUS Status;
>> + UINT32 Val;
>> + UINT8 PcieIndex;
>> +
>> + DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex->Socket, RootComplex->ID));
>> +
>> + ProgramHostBridge (RootComplex);
>> +
>> + if (!ReInit) {
>> + // Initialize PHY
>> + Status = PciePhyInit (RootComplex->SerdesBase);
>> + if (RETURN_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a: Failed to initialize the PCIe PHY\n", __FUNCTION__));
>> + return RETURN_DEVICE_ERROR;
>> + }
>> + }
>> +
>> + // Setup each controller
>> + for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
>> +
>> + if (ReInit) {
>> + PcieIndex = ReInitPcieIndex;
>> + }
>> +
>> + if (!RootComplex->Pcie[PcieIndex].Active) {
>> + continue;
>> + }
>> +
>> + DEBUG ((DEBUG_INFO, "Initializing Controller %d\n", PcieIndex));
>> +
>> + CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Put Controller into reset if not in reset already
>> + Val = MmioRead32 (CsrBase + RESET);
>> + if (!(Val & RESET_MASK)) {
>> + Val = DWCPCIE_SET (Val, 1);
>> + MmioWrite32 (CsrBase + RESET, Val);
>> +
>> + // Delay 50ms to ensure controller finish its reset
>> + MicroSecondDelay (50000);
>> + }
>> +
>> + // Clear memory shutdown
>> + Val = MmioRead32 (CsrBase + RAMSDR);
>> + Val = SD_SET (Val, 0);
>> + MmioWrite32 (CsrBase + RAMSDR, Val);
>> +
>> + if (!PollMemReady (CsrBase)) {
>> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Mem not ready\n", PcieIndex));
>> + return RETURN_DEVICE_ERROR;
>> + }
>> +
>> + // Hold link training
>> + Val = MmioRead32 (CsrBase + LINKCTRL);
>> + Val = LTSSMENB_SET (Val, 0);
>> + MmioWrite32 (CsrBase + LINKCTRL, Val);
>> +
>> + // Enable subsystem clock and release reset
>> + Val = MmioRead32 (CsrBase + CLOCK);
>> + Val = AXIPIPE_SET (Val, 1);
>> + MmioWrite32 (CsrBase + CLOCK, Val);
>> + Val = MmioRead32 (CsrBase + RESET);
>> + Val = DWCPCIE_SET (Val, 0);
>> + MmioWrite32 (CsrBase + RESET, Val);
>> +
>> + //
>> + // Controller does not provide any indicator for reset released.
>> + // Must wait at least 1us as per EAS.
>> + //
>> + MicroSecondDelay (1);
>> +
>> + if (!PollPipeReady (CsrBase)) {
>> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - PIPE clock is not stable\n", PcieIndex));
>> + return RETURN_DEVICE_ERROR;
>> + }
>> +
>> + // Start PERST pulse
>> + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
>> +
>> + // Allow programming to config space
>> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val);
>> +
>> + // In order to detect the NVMe disk for booting without disk,
>> + // need to set Hot-Plug Slot Capable during port initialization.
>> + // It will help PCI Linux driver to initialize its slot iomem resource,
>> + // the one is used for detecting the disk when it is inserted.
>> + Val = MmioRead32 (CfgAddr + SLOT_CAPABILITIES_REG);
>> + Val = SLOT_HPC_SET (Val, 1);
>> + // Program the power limit
>> + Val = SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT);
>> + MmioWrite32 (CfgAddr + SLOT_CAPABILITIES_REG, Val);
>> +
>> + // Apply RASDP error mitigation for all x8, x4, and x2 controllers
>> + // This includes all RootComplexTypeB root ports, and every RootComplexTypeA root port controller
>> + // except for index 0 (i.e. x16 controllers are exempted from this WA)
>> + RasdpMitigation (RootComplex, PcieIndex);
>> +
>> + // Program DTI for ATS support
>> + Val = MmioRead32 (CfgAddr + DTIM_CTRL0_OFF);
>> + Val = DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + DTIM_CTRL0_OFF, Val);
>> +
>> + //
>> + // Program number of lanes used
>> + // - Reprogram LINK_CAPABLE of PORT_LINK_CTRL_OFF
>> + // - Reprogram NUM_OF_LANES of GEN2_CTRL_OFF
>> + // - Reprogram CAP_MAX_LINK_WIDTH of LINK_CAPABILITIES_REG
>> + //
>> + ProgramLinkCapabilities (RootComplex, PcieIndex);
>> +
>> + // Set Zero byte request handling
>> + Val = MmioRead32 (CfgAddr + FILTER_MASK_2_OFF);
>> + Val = CX_FLT_MASK_VENMSG0_DROP_SET (Val, 0);
>> + Val = CX_FLT_MASK_VENMSG1_DROP_SET (Val, 0);
>> + Val = CX_FLT_MASK_DABORT_4UCPL_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + FILTER_MASK_2_OFF, Val);
>> + Val = MmioRead32 (CfgAddr + AMBA_ORDERING_CTRL_OFF);
>> + Val = AX_MSTR_ZEROLREAD_FW_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + AMBA_ORDERING_CTRL_OFF, Val);
>> +
>> + //
>> + // Set Completion with CRS handling for CFG Request
>> + // Set Completion with CA/UR handling non-CFG Request
>> + //
>> + Val = MmioRead32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF);
>> + Val = AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2);
>> + MmioWrite32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF, Val);
>> +
>> + // Set Legacy PCIE interrupt map to INTA
>> + Val = MmioRead32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG);
>> + Val = INT_PIN_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG, Val);
>> + Val = MmioRead32 (CsrBase + IRQSEL);
>> + Val = INTPIN_SET (Val, 1);
>> + MmioWrite32 (CsrBase + IRQSEL, Val);
>> +
>> + if (RootComplex->Pcie[PcieIndex].MaxGen != LINK_SPEED_GEN1) {
>> + ConfigureEqualization (RootComplex, PcieIndex);
>> + if (RootComplex->Pcie[PcieIndex].MaxGen == LINK_SPEED_GEN3) {
>> + ConfigurePresetGen3 (RootComplex, PcieIndex);
>> + } else if (RootComplex->Pcie[PcieIndex].MaxGen == LINK_SPEED_GEN4) {
>> + ConfigurePresetGen4 (RootComplex, PcieIndex);
>> + }
>> + }
>> +
>> + // Mask Completion Timeout
>> + MaskCompletionTimeOut (RootComplex, PcieIndex, 1, TRUE);
>> +
>> + // AER surprise link down error should be masked due to hotplug is enabled
>> + // This event must be handled by Hotplug handler, instead of error handler
>> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
>> + Val = SDES_ERR_MASK_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val);
>> +
>> + // Program Class Code
>> + Val = MmioRead32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG);
>> + Val = REVISION_ID_SET (Val, 4);
>> + Val = SUBCLASS_CODE_SET (Val, 4);
>> + Val = BASE_CLASS_CODE_SET (Val, 6);
>> + MmioWrite32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG, Val);
>> +
>> + // Program VendorID and DeviceID
>> + Val = MmioRead32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG);
>> + Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDORID);
>> + if (RootComplexTypeA == RootComplex->Type) {
>> + Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCA + PcieIndex);
>> + } else {
>> + Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCB + PcieIndex);
>> + }
>> + MmioWrite32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG, Val);
>> +
>> + // Enable common clock for downstream
>> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG);
>> + Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
>> + Val = CAP_COMMON_CLK_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG, Val);
>> +
>> + // Match aux_clk to system
>> + Val = MmioRead32 (CfgAddr + AUX_CLK_FREQ_OFF);
>> + Val = AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ);
>> + MmioWrite32 (CfgAddr + AUX_CLK_FREQ_OFF, Val);
>> +
>> + // Assert PERST low to reset endpoint
>> + BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE);
>> +
>> + // Start link training
>> + Val = MmioRead32 (CsrBase + LINKCTRL);
>> + Val = LTSSMENB_SET (Val, 1);
>> + MmioWrite32 (CsrBase + LINKCTRL, Val);
>> +
>> + // Complete the PERST pulse
>> + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
>> +
>> + // Lock programming of config space
>> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val);
>> +
>> + if (ReInit) {
>> + return RETURN_SUCCESS;
>> + }
>> + }
>> +
>> + return RETURN_SUCCESS;
>> +}
>> +
>> +BOOLEAN
>> +PcieLinkUpCheck (
>> + IN AC01_PCIE_CONTROLLER *Pcie
>> + )
>> +{
>> + PHYSICAL_ADDRESS CsrBase;
>> + UINT32 BlockEvent;
>> + UINT32 LinkStat;
>> +
>> + CsrBase = Pcie->CsrBase;
>> +
>> + // Check if card present
>> + // smlh_ltssm_state[13:8] = 0
>> + // phy_status[2] = 0
>> + // smlh_link_up[1] = 0
>> + // rdlh_link_up[0] = 0
>> + LinkStat = MmioRead32 (CsrBase + LINKSTAT);
>> + LinkStat = LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT |
>> + SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT);
>> + if (LinkStat == 0x0000) {
>> + return FALSE;
>> + }
>> +
>> + BlockEvent = MmioRead32 (CsrBase + BLOCKEVENTSTAT);
>> + LinkStat = MmioRead32 (CsrBase + LINKSTAT);
>> +
>> + if (((BlockEvent & LINKUP_MASK) != 0)
>> + && (SMLH_LTSSM_STATE_GET(LinkStat) == LTSSM_STATE_L0))
>> + {
>> + DEBUG ((DEBUG_INFO, "%a Linkup\n", __FUNCTION__));
>> + return TRUE;
>> + }
>> +
>> + return FALSE;
>> +}
>> +
>> +/**
>> + Callback function when the Host Bridge enumeration end.
>> +
>> + @param RootComplex Pointer to the Root Complex structure
>> +**/
>> +VOID
>> +Ac01PcieCoreEndEnumeration (
>> + IN AC01_ROOT_COMPLEX *RootComplex
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + PHYSICAL_ADDRESS Reg;
>> + UINT32 Val;
>> + UINTN Index;
>> +
>> + if (RootComplex == NULL || !RootComplex->Active) {
>> + return;
>> + }
>> +
>> + // Clear uncorrectable error during enumuration phase. Mainly completion timeout.
>> + for (Index = 0; Index < RootComplex->MaxPcieController; Index++) {
>> + if (!RootComplex->Pcie[Index].Active) {
>> + continue;
>> + }
>> + if (!PcieLinkUpCheck(&RootComplex->Pcie[Index])) {
>> + // If link down/disabled after enumeration, disable completed time out
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[Index].DevNum << 15);
>> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
>> + Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val);
>> + }
>> + // Clear all errors
>> + Reg = RootComplex->MmcfgBase + ((Index + 1) << 15) + UNCORR_ERR_STATUS_OFF;
>> + Val = MmioRead32 (Reg);
>> + if (Val != 0) {
>> + // Clear error by writting
>> + MmioWrite32 (Reg, Val);
>> + }
>> + }
>> +}
>> +
>> +/**
>> + Comparing current link status with the max capabilities of the link
>> +
>> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex PCIe index
>> + @param EpMaxWidth EP max link width
>> + @param EpMaxGen EP max link speed
>> +
>> + @retval -1: Link status do not match with link max capabilities
>> + 1: Link capabilites are invalid
>> + 0: Link status are correct
>> +**/
>> +INT32
>> +Ac01PcieCoreLinkCheck (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN UINT8 EpMaxWidth,
>> + IN UINT8 EpMaxGen
>> + )
>> +{
>> + PHYSICAL_ADDRESS CsrBase, CfgAddr;
>> + UINT32 Val, LinkStat;
>> + UINT32 MaxWidth, MaxGen;
>> +
>> + CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + Val = MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG);
>> + if ((CAP_MAX_LINK_WIDTH_GET (Val) == 0) ||
>> + (CAP_MAX_LINK_SPEED_GET (Val) == 0)) {
>> + DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong RootComplex capabilities\n", RootComplex->ID, PcieIndex));
>> + return LINK_CHECK_WRONG_PARAMETER;
>> + }
>> +
>> + if ((EpMaxWidth == 0) || (EpMaxGen == 0)) {
>> + DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong EP capabilities\n", RootComplex->ID, PcieIndex));
>> + return LINK_CHECK_FAILED;
>> + }
>> +
>> + // Compare RootComplex and EP capabilities
>> + if (CAP_MAX_LINK_WIDTH_GET (Val) > EpMaxWidth) {
>> + MaxWidth = EpMaxWidth;
>> + } else {
>> + MaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
>> + }
>> +
>> + // Compare RootComplex and EP capabilities
>> + if (CAP_MAX_LINK_SPEED_GET (Val) > EpMaxGen) {
>> + MaxGen = EpMaxGen;
>> + } else {
>> + MaxGen = CAP_MAX_LINK_SPEED_GET (Val);
>> + }
>> +
>> + LinkStat = MmioRead32 (CsrBase + LINKSTAT);
>> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG);
>> + DEBUG ((
>> + DEBUG_INFO,
>> + "PCIE%d.%d: Link MaxWidth %d MaxGen %d, LINKSTAT 0x%x",
>> + RootComplex->ID,
>> + PcieIndex,
>> + MaxWidth,
>> + MaxGen,
>> + LinkStat
>> + ));
>> +
>> + // Checking all conditions of the link
>> + // If one of them is not sastified, return link up fail
>> + if ((CAP_NEGO_LINK_WIDTH_GET (Val) != MaxWidth) ||
>> + (CAP_LINK_SPEED_GET (Val) != MaxGen) ||
>> + (RDLH_SMLH_LINKUP_STATUS_GET (LinkStat) != (SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT)))
>> + {
>> + DEBUG ((DEBUG_INFO, "\tLinkCheck FAILED\n"));
>> + return LINK_CHECK_FAILED;
>> + }
>> +
>> + DEBUG ((DEBUG_INFO, "\tLinkCheck SUCCESS\n"));
>> + return LINK_CHECK_SUCCESS;
>> +}
>> +
>> +INT32
>> +PFACounterRead (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN UINT64 RasDesVSecBase
>> + )
>> +{
>> + INT32 Ret = LINK_CHECK_SUCCESS;
>> + UINT32 Val;
>> + UINT8 ErrCode, ErrGrpNum;
>> +
>> + UINT32 ErrCtrlCfg[MAX_NUM_ERROR_CODE] = {
>> + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, // Per Lane
>> + 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A,
>> + 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
>> + 0x300, 0x301, 0x302, 0x303, 0x304, 0x305,
>> + 0x400, 0x401, // Per Lane
>> + 0x500, 0x501, 0x502, 0x503, 0x504, 0x505, 0x506, 0x507, 0x508, 0x509, 0x50A, 0x50B, 0x50C, 0x50D
>> + };
>> +
>> + for (ErrCode = 0; ErrCode < MAX_NUM_ERROR_CODE; ErrCode++) {
>> + ErrGrpNum = (ErrCtrlCfg[ErrCode] & 0xF00) >> 8;
>> + // Skipping per lane group
>> + // Checking common lane group because AER error are included in common group only
>> + if ((ErrGrpNum != 0) && (ErrGrpNum != 4)) {
>> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
>> + if (RootComplex->Type == RootComplexTypeA) {
>> + // RootComplexTypeA - 4 PCIe controller per port, 1 controller in charge of 4 lanes
>> + Val = ECCR_LANE_SEL_SET (Val, PcieIndex*4);
>> + } else {
>> + // RootComplexTypeB - 8 PCIe controller per port, 1 controller in charge of 2 lanes
>> + Val = ECCR_LANE_SEL_SET (Val, PcieIndex*2);
>> + }
>> + Val = ECCR_GROUP_EVENT_SEL_SET (Val, ErrCtrlCfg[ErrCode]);
>> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val);
>> +
>> + // After setting Counter Control reg
>> + // This delay just to make sure Counter Data reg is update with new value
>> + MicroSecondDelay (1);
>> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_DATA_REG_OFF);
>> + if (Val != 0) {
>> + Ret = LINK_CHECK_FAILED;
>> + DEBUG ((
>> + DEBUG_ERROR,
>> + "\tSocket%d RootComplex%d RP%d \t%s: %d \tGROUP:%d-EVENT:%d\n",
>> + RootComplex->Socket,
>> + RootComplex->ID,
>> + PcieIndex,
>> + Val,
>> + ((ErrCtrlCfg[ErrCode] & 0xF00) >> 8), // Group
>> + (ErrCtrlCfg[ErrCode] & 0x0FF) // Event
>> + ));
>> + }
>> + }
>> + }
>> +
>> + return Ret;
>> +}
>> +
>> +INT32
>> +Ac01PFAEnableAll (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN INTN PFAMode
>> + )
>> +{
>> + PHYSICAL_ADDRESS CfgAddr;
>> + PHYSICAL_ADDRESS RasDesVSecBase;
>> + INT32 Ret = LINK_CHECK_SUCCESS;
>> + UINT32 Val;
>> +
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Allow programming to config space
>> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 1);
>> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val);
>> +
>> + // Generate the RAS DES capability address
>> + // RAS_DES_CAP_ID = 0xB
>> + RasDesVSecBase = PcieCheckCap (RootComplex, PcieIndex, TRUE, RAS_DES_CAP_ID);
>> + if (RasDesVSecBase == 0) {
>> + DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\n", RootComplex->ID, PcieIndex));
>> + return LINK_CHECK_WRONG_PARAMETER;
>> + }
>> +
>> + if (PFAMode == PFA_REG_ENABLE) {
>> + // PFA Counters Enable
>> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
>> + Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0x7);
>> + Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0);
>> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val);
>> + } else if (PFAMode == PFA_REG_CLEAR) {
>> + // PFA Counters Clear
>> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
>> + Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0);
>> + Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0x3);
>> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val);
>> + } else {
>> + // PFA Counters Read
>> + Ret = PFACounterRead (RootComplex, PcieIndex, RasDesVSecBase);
>> + }
>> +
>> + // Disable programming to config space
>> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 0);
>> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val);
>> +
>> + return Ret;
>> +}
>> +
>> +UINT32
>> +CheckEndpointCfg (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + PHYSICAL_ADDRESS EpCfgAddr;
>> + UINT32 TimeOut;
>> + UINT32 Val;
>> +
>> + EpCfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 20); /* Bus 1, dev 0, func 0 */
>> +
>> + // Loop read EpCfgAddr value until got valid value or
>> + // reach to timeout EP_LINKUP_TIMEOUT (or more depend on card)
>> + TimeOut = EP_LINKUP_TIMEOUT;
>> + do {
>> + Val = MmioRead32 (EpCfgAddr);
>> + if (Val != 0xFFFF0001 && Val != 0xFFFFFFFF) {
>> + break;
>> + }
>> + MicroSecondDelay (LINK_WAIT_INTERVAL_US);
>> + TimeOut -= LINK_WAIT_INTERVAL_US;
>> + } while (TimeOut > 0);
>> +
>> + return MmioRead32 (EpCfgAddr);
>> +}
>> +
>> +VOID
>> +GetEndpointInfo (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + OUT UINT8 *EpMaxWidth,
>> + OUT UINT8 *EpMaxGen
>> + )
>> +{
>> + PHYSICAL_ADDRESS PcieCapBaseAddr;
>> + UINT32 Val;
>> +
>> + Val = CheckEndpointCfg (RootComplex, PcieIndex);
>> + if (Val == 0xFFFFFFFF) {
>> + *EpMaxWidth = 0; // Invalid Width
>> + *EpMaxGen = 0; // Invalid Speed
>> + DEBUG ((DEBUG_ERROR, "PCIE%d.%d Cannot access EP config space!\n", RootComplex->ID, PcieIndex));
>> + } else {
>> + PcieCapBaseAddr = PcieCheckCap (RootComplex, PcieIndex, FALSE, CAP_ID);
>> + if (PcieCapBaseAddr == 0) {
>> + *EpMaxWidth = 0; // Invalid Width
>> + *EpMaxGen = 0; // Invalid Speed
>> + DEBUG ((
>> + DEBUG_ERROR,
>> + "PCIE%d.%d Cannot get PCIe capability extended address!\n",
>> + RootComplex->ID,
>> + PcieIndex
>> + ));
>> + } else {
>> + Val = MmioRead32 (PcieCapBaseAddr + LINK_CAPABILITIES_REG_OFF);
>> + *EpMaxWidth = (Val >> 4) & 0x3F;
>> + *EpMaxGen = Val & 0xF;
>> + DEBUG ((
>> + DEBUG_INFO,
>> + "PCIE%d.%d EP MaxWidth %d EP MaxGen %d \n", RootComplex->ID,
>> + PcieIndex,
>> + *EpMaxWidth,
>> + *EpMaxGen
>> + ));
>> +
>> + // From EP, enabling common clock for upstream
>> + Val = MmioRead32 (PcieCapBaseAddr + LINK_CONTROL_LINK_STATUS_OFF);
>> + Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
>> + Val = CAP_COMMON_CLK_SET (Val, 1);
>> + MmioWrite32 (PcieCapBaseAddr + LINK_CONTROL_LINK_STATUS_OFF, Val);
>> + }
>> + }
>> +}
>> +
>> +/**
>> + Get link capabilities link width and speed of endpoint
>> +
>> + @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex[in] PCIe controller index
>> + @param EpMaxWidth[out] EP max link width
>> + @param EpMaxGen[out] EP max link speed
>> +**/
>> +VOID
>> +Ac01PcieCoreGetEndpointInfo (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + OUT UINT8 *EpMaxWidth,
>> + OUT UINT8 *EpMaxGen
>> + )
>> +{
>> + PHYSICAL_ADDRESS RcCfgAddr;
>> + UINT32 Val, RestoreVal;
>> +
>> + RcCfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + // Allow programming to config space
>> + Val = MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 1);
>> + MmioWrite32 (RcCfgAddr + MISC_CONTROL_1_OFF, Val);
>> +
>> + Val = MmioRead32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG);
>> + RestoreVal = Val;
>> + Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS); /* Set DEFAULT_SUB_BUS to Subordinate bus */
>> + Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum); /* Set RootComplex->Pcie[PcieIndex].DevNum to Secondary bus */
>> + Val = PRIM_BUS_SET (Val, 0x0); /* Set 0x0 to Primary bus */
>> + MmioWrite32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, Val);
>> +
>> + GetEndpointInfo (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen);
>> +
>> + // Restore value in order to not affect enumeration process
>> + MmioWrite32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, RestoreVal);
>> +
>> + // Disable programming to config space
>> + Val = MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF);
>> + Val = DBI_RO_WR_EN_SET (Val, 0);
>> + MmioWrite32 (RcCfgAddr + MISC_CONTROL_1_OFF, Val);
>> +}
>> +
>> +VOID
>> +PollLinkUp (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + UINT32 TimeOut;
>> +
>> + // Poll until link up
>> + // This checking for linkup status and
>> + // give LTSSM state the time to transit from DECTECT state to L0 state
>> + // Total delay are 100ms, smaller number of delay cannot always make sure
>> + // the state transition is completed
>> + TimeOut = LTSSM_TRANSITION_TIMEOUT;
>> + do {
>> + if (PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex])) {
>> + DEBUG ((
>> + DEBUG_INFO,
>> + "\tPCIE%d.%d LinkStat is correct after soft reset, transition time: %d\n",
>> + RootComplex->ID,
>> + PcieIndex,
>> + TimeOut
>> + ));
>> + RootComplex->Pcie[PcieIndex].LinkUp = TRUE;
>> + break;
>> + }
>> +
>> + MicroSecondDelay (100);
>> + TimeOut -= 100;
>> + } while (TimeOut > 0);
>> +
>> + if (TimeOut <= 0) {
>> + DEBUG ((DEBUG_ERROR, "\tPCIE%d.%d LinkStat TIMEOUT after re-init\n", RootComplex->ID, PcieIndex));
>> + } else {
>> + DEBUG ((DEBUG_INFO, "PCIE%d.%d Link re-initialization passed!\n", RootComplex->ID, PcieIndex));
>> + }
>> +}
>> +
>> +/**
>> + Check active PCIe controllers of RootComplex, retrain or soft reset if needed
>> +
>> + @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
>> + @param PcieIndex[in] PCIe controller index
>> +
>> + @retval -1: Link recovery had failed
>> + 1: Link width and speed are not correct
>> + 0: Link recovery succeed
>> +**/
>> +INT32
>> +Ac01PcieCoreQoSLinkCheckRecovery (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex
>> + )
>> +{
>> + INT32 NumberOfReset = MAX_REINIT; // Number of soft reset retry
>> + UINT8 EpMaxWidth, EpMaxGen;
>> + INT32 LinkStatusCheck, RasdesChecking;
>> +
>> + // PCIe controller is not active or Link is not up
>> + // Nothing to be done
>> + if ((!RootComplex->Pcie[PcieIndex].Active) || (!RootComplex->Pcie[PcieIndex].LinkUp)) {
>> + return LINK_CHECK_WRONG_PARAMETER;
>> + }
>> +
>> + do {
>> +
>> + if (RootComplex->Pcie[PcieIndex].LinkUp) {
>> + // Enable all of RASDES register to detect any training error
>> + Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_ENABLE);
>> +
>> + // Accessing Endpoint and checking current link capabilities
>> + Ac01PcieCoreGetEndpointInfo (RootComplex, PcieIndex, &EpMaxWidth, &EpMaxGen);
>> + LinkStatusCheck = Ac01PcieCoreLinkCheck (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen);
>> +
>> + // Delay to allow the link to perform internal operation and generate
>> + // any error status update. This allows detection of any error observed
>> + // during initial link training. Possible evaluation time can be
>> + // between 100ms to 200ms.
>> + MicroSecondDelay (100000);
>> +
>> + // Check for error
>> + RasdesChecking = Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_READ);
>> +
>> + // Clear error counter
>> + Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_CLEAR);
>> +
>> + // If link check functions return passed, then breaking out
>> + // else go to soft reset
>> + if (LinkStatusCheck != LINK_CHECK_FAILED &&
>> + RasdesChecking != LINK_CHECK_FAILED &&
>> + PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex]))
>> + {
>> + return LINK_CHECK_SUCCESS;
>> + }
>> +
>> + RootComplex->Pcie[PcieIndex].LinkUp = FALSE;
>> + }
>> +
>> + // Trigger controller soft reset
>> + DEBUG ((DEBUG_INFO, "PCIE%d.%d Start link re-initialization..\n", RootComplex->ID, PcieIndex));
>> + Ac01PcieCoreSetupRC (RootComplex, TRUE, PcieIndex);
>> +
>> + PollLinkUp (RootComplex, PcieIndex);
>> +
>> + NumberOfReset--;
>> + } while (NumberOfReset > 0);
>> +
>> + return LINK_CHECK_SUCCESS;
>> +}
>> +
>> +VOID
>> +Ac01PcieCoreUpdateLink (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + OUT BOOLEAN *IsNextRoundNeeded,
>> + OUT INT8 *FailedPciePtr,
>> + OUT INT8 *FailedPcieCount
>> + )
>> +{
>> + AC01_PCIE_CONTROLLER *Pcie;
>> + PHYSICAL_ADDRESS CfgAddr;
>> + UINT8 PcieIndex;
>> + UINT32 Index;
>> + UINT32 Val;
>> +
>> + *IsNextRoundNeeded = FALSE;
>> + *FailedPcieCount = 0;
>> + for (Index = 0; Index < MaxPcieControllerB; Index++) {
>> + FailedPciePtr[Index] = -1;
>> + }
>> +
>> + if (!RootComplex->Active) {
>> + return;
>> + }
>> +
>> + // Loop for all controllers
>> + for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
>> + Pcie = &RootComplex->Pcie[PcieIndex];
>> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15);
>> +
>> + if (Pcie->Active && !Pcie->LinkUp) {
>> + if (PcieLinkUpCheck (Pcie)) {
>> + Pcie->LinkUp = TRUE;
>> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG);
>> + DEBUG ((
>> + DEBUG_INFO,
>> + "%a Socket%d RootComplex%d RP%d NEGO_LINK_WIDTH: 0x%x LINK_SPEED: 0x%x\n",
>> + __FUNCTION__,
>> + RootComplex->Socket,
>> + RootComplex->ID,
>> + PcieIndex,
>> + CAP_NEGO_LINK_WIDTH_GET (Val),
>> + CAP_LINK_SPEED_GET (Val)
>> + ));
>> +
>> + // Doing link checking and recovery if needed
>> + Ac01PcieCoreQoSLinkCheckRecovery (RootComplex, PcieIndex);
>> +
>> + // Un-mask Completion Timeout
>> + MaskCompletionTimeOut (RootComplex, PcieIndex, 32, FALSE);
>> +
>> + } else {
>> + *IsNextRoundNeeded = FALSE;
>> + FailedPciePtr[*FailedPcieCount] = PcieIndex;
>> + *FailedPcieCount += 1;
>> + }
>> + }
>> + }
>> +}
>> +
>> +/**
>> + Verify the link status and retry to initialize the Root Complex if there's any issue.
>> +
>> + @param RootComplexList Pointer to the Root Complex list
>> +**/
>> +VOID
>> +Ac01PcieCorePostSetupRC (
>> + IN AC01_ROOT_COMPLEX *RootComplexList
>> + )
>> +{
>> + UINT8 RCIndex, Idx;
>> + BOOLEAN IsNextRoundNeeded = FALSE, NextRoundNeeded;
>> + UINT64 PrevTick, CurrTick, ElapsedCycle;
>> + UINT64 TimerTicks64;
>> + UINT8 ReInit;
>> + INT8 FailedPciePtr[MaxPcieControllerB];
>> + INT8 FailedPcieCount;
>> +
>> + ReInit = 0;
>> +
>> +_link_polling:
>> + NextRoundNeeded = 0;
>> + //
>> + // It is not guaranteed the timer service is ready prior to PCI Dxe.
>> + // Calculate system ticks for link training.
>> + //
>> + TimerTicks64 = ArmGenericTimerGetTimerFreq (); /* 1 Second */
>> + PrevTick = ArmGenericTimerGetSystemCount ();
>> + ElapsedCycle = 0;
>> +
>> + do {
>> + CurrTick = ArmGenericTimerGetSystemCount ();
>> + if (CurrTick < PrevTick) {
>> + ElapsedCycle += (UINT64)(~0x0ULL) - PrevTick;
>> + PrevTick = 0;
>> + }
>> + ElapsedCycle += (CurrTick - PrevTick);
>> + PrevTick = CurrTick;
>> + } while (ElapsedCycle < TimerTicks64);
>> +
>> + for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
>> + Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
>> + if (IsNextRoundNeeded) {
>> + NextRoundNeeded = 1;
>> + }
>> + }
>> +
>> + if (NextRoundNeeded && ReInit < MAX_REINIT) {
>> + //
>> + // Timer is up. Give another chance to re-program controller
>> + //
>> + ReInit++;
>> + for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
>> + Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
>> + if (IsNextRoundNeeded) {
>> + for (Idx = 0; Idx < FailedPcieCount; Idx++) {
>> + if (FailedPciePtr[Idx] == -1) {
>> + continue;
>> + }
>> +
>> + //
>> + // Some controller still observes link-down. Re-init controller
>> + //
>> + Ac01PcieCoreSetupRC (&RootComplexList[RCIndex], TRUE, FailedPciePtr[Idx]);
>> + }
>> + }
>> + }
>> +
>> + goto _link_polling;
>> + }
>> +}
>> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
>> new file mode 100644
>> index 000000000000..0916adb77539
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
>> @@ -0,0 +1,47 @@
>> +/** @file
>> +
>> + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
>> +
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#include <Library/BoardPcieLib.h>
>> +
>> +/**
>> + Assert PERST of input PCIe controller
>> +
>> + @param[in] RootComplex RootComplex instance.
>> + @param[in] PcieIndex PCIe controller index of input Root Complex.
>> + @param[in] Bifurcation Bifurcation mode of input Root Complex.
>> + @param[in] IsPullToHigh Target status for the PERST.
>> +
>> + @retval RETURN_SUCCESS The operation is successful.
>> + @retval Others An error occurred.
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +BoardPcieAssertPerst (
>> + IN AC01_ROOT_COMPLEX *RootComplex,
>> + IN UINT8 PcieIndex,
>> + IN BOOLEAN IsPullToHigh
>> + )
>> +{
>> + return RETURN_SUCCESS;
>> +}
>> +
>> +/**
>> + Override the segment number for a root complex with a board specific number.
>> +
>> + @param[in] RootComplex Root Complex instance with properties.
>> +
>> + @retval Segment number corresponding to the input root complex.
>> + Default segment number is 0x0F.
>> +**/
>> +UINT16
>> +BoardPcieGetSegmentNumber (
>> + IN AC01_ROOT_COMPLEX *RootComplex
>> + )
>> +{
>> + return 0x0F;
>> +}
>> --
>> 2.17.1
>>
next prev parent reply other threads:[~2021-11-03 9:39 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-22 6:17 [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 01/31] Ampere: Initial support for Ampere Altra processor and " Nhi Pham
2021-10-26 11:14 ` Leif Lindholm
2021-11-03 9:31 ` Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 02/31] AmpereAltraPkg: Add FlashLib library instance Nhi Pham
2021-10-26 11:25 ` Leif Lindholm
2021-11-03 9:32 ` Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 03/31] AmpereAltraPkg: Add FailSafe and WDT support Nhi Pham
2021-10-26 12:15 ` Leif Lindholm
2021-11-03 9:35 ` Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 04/31] AmpereAltraPkg: Add DwI2cLib library instance Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 05/31] AmpereAltraPkg: Add DwGpioLib " Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 06/31] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 07/31] AmpereAltraPkg: Add BootProgress support Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 08/31] AmpereAltraPkg: Support UEFI non-volatile variable Nhi Pham
2021-10-26 12:21 ` Leif Lindholm
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 09/31] AmpereSiliconPkg: Add PlatformManagerUiLib library instance Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 10/31] AmpereAltraPkg, JadePkg: Add ACPI support Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 11/31] AmpereAltraPkg: Add Root Complex HOB data structures Nhi Pham
2021-10-26 12:23 ` Leif Lindholm
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance Nhi Pham
2021-10-26 12:45 ` Leif Lindholm
2021-11-03 9:33 ` Nhi Pham [this message]
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 13/31] JadePkg: Add BoardPcieLib " Nhi Pham
2021-10-26 12:46 ` Leif Lindholm
2021-11-03 9:33 ` Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 14/31] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Nhi Pham
2021-10-26 12:49 ` Leif Lindholm
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 15/31] AmpereAltraPkg: Add PciHostBridgeLib library instance Nhi Pham
2021-10-26 12:49 ` Leif Lindholm
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 16/31] AmpereAltraPkg: Add PciSegmentLib " Nhi Pham
2021-10-26 12:53 ` Leif Lindholm
2021-11-03 9:35 ` Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 17/31] JadePkg: Enable PciHostBridgeDxe driver Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 18/31] JadePkg: Add PciPlatformDxe driver Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe Nhi Pham
2021-10-26 12:54 ` Leif Lindholm
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 20/31] JadePkg: Add ASpeed GOP driver Nhi Pham
2021-10-22 6:17 ` [edk2-platforms][PATCH v4 21/31] AmpereAltraPkg: Add Random Number Generator Support Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 22/31] JadePkg: Add SMBIOS tables support Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 23/31] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 24/31] AmpereAltraPkg: Add configuration screen for PCIe Nhi Pham
2021-10-26 12:56 ` Leif Lindholm
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 25/31] Ampere: Utilize the PCIe User setting Nhi Pham
2021-10-26 12:57 ` Leif Lindholm
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 26/31] AmpereAltraPkg: Add platform info screen Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 27/31] AmpereAltraPkg: Add configuration screen for Memory Nhi Pham
2021-10-26 12:58 ` Leif Lindholm
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 28/31] AmpereAltraPkg: Add configuration screen for CPU Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 29/31] AmpereAltraPkg: Add configuration screen for ACPI Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 30/31] AmpereAltraPkg: Add configuration screen for RAS Nhi Pham
2021-10-22 6:18 ` [edk2-platforms][PATCH v4 31/31] AmpereAltraPkg: Add configuration screen for Watchdog timer Nhi Pham
2021-10-26 13:03 ` Leif Lindholm
2021-11-03 9:36 ` Nhi Pham
2021-10-26 13:08 ` [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Leif Lindholm
2021-11-03 9:37 ` Nhi Pham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b20789e1-5b20-ba36-c5f2-c26409f85f6d@os.amperecomputing.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox