[edk2-devel] [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed Nov 3 09:33:24 UTC 2021


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 at os.amperecomputing.com>
>>
>> Provides essential functions to initialize the PCIe Root Complex on
>> Ampere Altra processor.
>>
>> Cc: Thang Nguyen <thang at os.amperecomputing.com>
>> Cc: Chuong Tran <chuong at os.amperecomputing.com>
>> Cc: Phong Vo <phong at os.amperecomputing.com>
>> Cc: Leif Lindholm <leif at nuviainc.com>
>> Cc: Michael D Kinney <michael.d.kinney at intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
>> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
>>
>> Signed-off-by: Nhi Pham <nhi at 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
>>


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





More information about the edk2-devel-archive mailing list