public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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 v5 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance
Date: Thu, 18 Nov 2021 20:33:57 +0700	[thread overview]
Message-ID: <f74dc867-5b1f-ad4c-1124-54b2b765711b@os.amperecomputing.com> (raw)
In-Reply-To: <YZZIEAOi9qi0XVut@leviathan>

On 18/11/2021 19:33, Leif Lindholm wrote:
> Hi Nhi,
>
> On Wed, Nov 17, 2021 at 23:47:08 +0700, Nhi Pham wrote:
>> From: Vu Nguyen <vunguyen@os.amperecomputing.com>
>>
>> Provides essential functions to initialize the PCIe Root Complex on
>> Ampere Altra processor.
> The NOOPT build fails for me with
> /work/git/edk2-platforms/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c:
> In function ‘Ac01PFACommand’: /work/git/edk2-platforms/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c:1024:26:
> error: variable ‘CfgBase’ set but not used [-Werror=unused-but-set-variable]
>   1024 |   PHYSICAL_ADDRESS       CfgBase;
>        |                          ^~~~~~~
>
> I will have a look at 1-10/30 - in the mean time, could you fix this
> along with anything else in later patches preventing a successful
> NOOPT build? And then send out only updated versions of affected
> patches (as v6), not the whole set.
Thanks, Leif. I will fix and send shortly.
>
> In case your toolchain does not expose this bug, I'm using:
> gcc version 10.2.1 20210110 (Debian 10.2.1-6)

I see the compilation error now with gcc. Thank you. I used CLANG for 
checking NOOPT.

Best regards,

Nhi

>
> Best Regards,
>
> Leif
>
>> 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                |  372 +++++
>>   Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c                | 1419 ++++++++++++++++++++
>>   Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c   |   47 +
>>   10 files changed, 2012 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 fa9b120b2c2b..5b767ecb024f 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..692bc2669915
>> --- /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 controller 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..1db8a68b3df4
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
>> @@ -0,0 +1,372 @@
>> +/** @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_
>> +
>> +#define BUS_SHIFT                        20
>> +#define DEV_SHIFT                        15
>> +
>> +#define GET_LOW_8_BITS(x)                ((x) & 0xFF)
>> +#define GET_HIGH_8_BITS(x)               (((x) >> 8) & 0xFF)
>> +#define GET_LOW_16_BITS(x)               ((x) & 0xFFFF)
>> +#define GET_HIGH_16_BITS(x)              (((x) >> 16) & 0xFFFF)
>> +#define GET_CAPABILITY_PTR(x)            (GET_LOW_16_BITS (x) >> 8)
>> +#define GET_EXT_CAPABILITY_PTR(x)        (GET_HIGH_16_BITS (x) >> 4)
>> +
>> +#define WORD_ALIGN_MASK                  0x3
>> +
>> +#define MAX_REINIT                       3      // Number of soft reset retry
>> +
>> +#define SLOT_POWER_LIMIT_75W             75     // Watt
>> +
>> +#define LINK_CHECK_SUCCESS               0
>> +#define LINK_CHECK_FAILED                -1
>> +#define LINK_CHECK_WRONG_PARAMETER       1
>> +
>> +#define AMPERE_PCIE_VENDOR_ID            0x1DEF
>> +#define AC01_HOST_BRIDGE_DEVICE_ID_RCA   0xE100
>> +#define AC01_HOST_BRIDGE_DEVICE_ID_RCB   0xE110
>> +#define AC01_PCIE_BRIDGE_DEVICE_ID_RCA   0xE101
>> +#define AC01_PCIE_BRIDGE_DEVICE_ID_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
>> +
>> +#define PFA_MODE_ENABLE                  0
>> +#define PFA_MODE_CLEAR                   1
>> +#define PFA_MODE_READ                    2
>> +
>> +//
>> +// Host Bridge registers
>> +//
>> +#define AC01_HOST_BRIDGE_RCA_DEV_MAP_REG        0x0
>> +#define AC01_HOST_BRIDGE_RCB_DEV_MAP_REG        0x4
>> +#define AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG   0x10
>> +
>> +// AC01_HOST_BRIDGE_RCA_DEV_MAP_REG
>> +#define RCA_DEV_MAP_SET(dst, src)               (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
>> +#define RCA_DEV_MAP_GET(val)                    ((val) & 0x7)
>> +
>> +// AC01_HOST_BRIDGE_RCB_DEV_MAP_REG
>> +#define RCB_DEV_MAP_LOW_SET(dst, src)           (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
>> +#define RCB_DEV_MAP_LOW_GET(val)                ((val) & 0x7)
>> +
>> +#define RCB_DEV_MAP_HIGH_SET(dst, src)          (((dst) & ~0x70) | (((UINT32) (src) << 4) & 0x70))
>> +#define RCB_DEV_MAP_HIGH_GET(val)               (((val) & 0x7) >> 4)
>> +
>> +// AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG
>> +#define VENDOR_ID_SET(dst, src)                 (((dst) & ~0xFFFF) | (((UINT32) (src))  & 0xFFFF))
>> +#define VENDOR_ID_GET(val)                      ((val) & 0xFFFF)
>> +
>> +#define DEVICE_ID_SET(dst, src)                 (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
>> +#define DEVICE_ID_GET(val)                      (((val) & 0xFFFF0000) >> 16)
>> +
>> +//
>> +// PCIe core registers
>> +//
>> +#define AC01_PCIE_CORE_LINK_CTRL_REG            0x0
>> +#define AC01_PCIE_CORE_LINK_STAT_REG            0x4
>> +#define AC01_PCIE_CORE_IRQ_SEL_REG              0xC
>> +#define AC01_PCIE_CORE_HOT_PLUG_STAT_REG        0x28
>> +#define AC01_PCIE_CORE_IRQ_ENABLE_REG           0x30
>> +#define AC01_PCIE_CORE_IRQ_EVENT_STAT_REG       0x38
>> +#define AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG     0x3C
>> +#define AC01_PCIE_CORE_RESET_REG                0xC000
>> +#define AC01_PCIE_CORE_CLOCK_REG                0xC004
>> +#define AC01_PCIE_CORE_MEM_READY_REG            0xC104
>> +#define AC01_PCIE_CORE_RAM_SHUTDOWN_REG         0xC10C
>> +
>> +// AC01_PCIE_CORE_LINK_CTRL_REG
>> +#define LTSSMENB_SET(dst, src)              (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define   HOLD_LINK_TRAINING                0
>> +#define   START_LINK_TRAINING               1
>> +#define DEVICETYPE_SET(dst, src)            (((dst) & ~0xF0) | (((UINT32) (src) << 4) & 0xF0))
>> +#define DEVICETYPE_GET(val)                 (((val) & 0xF0) >> 4)
>> +
>> +// AC01_PCIE_CORE_LINK_STAT_REG
>> +#define PHY_STATUS_MASK                     (1 << 2)
>> +#define SMLH_LTSSM_STATE_MASK               0x3F00
>> +#define SMLH_LTSSM_STATE_GET(val)           ((val & SMLH_LTSSM_STATE_MASK) >> 8)
>> +#define   LTSSM_STATE_L0                    0x11
>> +#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
>> +
>> +// AC01_PCIE_CORE_IRQ_SEL_REG
>> +#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))
>> +#define IRQ_INT_A                0x01
>> +
>> +// AC01_PCIE_CORE_HOT_PLUG_STAT_REG
>> +#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))
>> +
>> +// AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG
>> +#define LINKUP_MASK              0x1
>> +
>> +// AC01_PCIE_CORE_RESET_REG
>> +#define DWC_PCIE_SET(dst, src)   (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define   RESET_MASK             0x1
>> +#define   ASSERT_RESET           0x1
>> +
>> +// AC01_PCIE_CORE_CLOCK_REG
>> +#define AXIPIPE_SET(dst, src)    (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +// AC01_PCIE_CORE_MEM_READY_REG
>> +#define MEMORY_READY             0x1
>> +
>> +// AC01_PCIE_CORE_RAM_SHUTDOWN_REG
>> +#define SD_SET(dst, src)         (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +
>> +//
>> +// AC01 PCIe Type 1 configuration 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 PCIE_CAPABILITY_BASE                        0x70
>> +#define EXT_CAPABILITY_START_BASE                   0x100
>> +#define AER_CAPABILITY_BASE                         0x100
>> +
>> +// 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   DEFAULT_BASE_CLASS_CODE               6
>> +#define SUB_CLASS_CODE_SET(dst, src)             (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
>> +#define   DEFAULT_SUB_CLASS_CODE                4
>> +#define PROGRAM_INTERFACE_SET(dst, src)         (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +#define REVISION_ID_SET(dst, src)               (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +#define   DEFAULT_REVISION_ID                   4
>> +
>> +// SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG
>> +#define SUB_BUS_SET(dst, src)                   (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
>> +#define   DEFAULT_SUB_BUS                       0xFF
>> +#define SEC_BUS_SET(dst, src)                   (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +#define PRIM_BUS_SET(dst, src)                  (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
>> +#define   DEFAULT_PRIM_BUS                      0x00
>> +
>> +// BRIDGE_CTRL_INT_PIN_INT_LINE_REG
>> +#define INT_PIN_SET(dst, src)                   (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
>> +
>> +//
>> +// PCI Express Capability
>> +//
>> +#define PCIE_CAPABILITY_ID                      0x10
>> +#define LINK_CAPABILITIES_REG                   0xC
>> +#define LINK_CONTROL_LINK_STATUS_REG            0x10
>> +#define SLOT_CAPABILITIES_REG                   0x14
>> +#define DEVICE_CONTROL2_DEVICE_STATUS2_REG      0x28
>> +#define LINK_CAPABILITIES2_REG                  0x2C
>> +#define LINK_CONTROL2_LINK_STATUS2_REG          0x30
>> +
>> +// LINK_CAPABILITIES_REG
>> +#define CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET(dst, src) (((dst) & ~0xC00) | (((UINT32)(src) << 10) & 0xC00))
>> +#define   NO_ASPM_SUPPORTED                     0x0
>> +#define   L0S_SUPPORTED                         0x1
>> +#define   L1_SUPPORTED                          0x2
>> +#define   L0S_L1_SUPPORTED                      0x3
>> +#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   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_SPEED_GET(val)             ((val & 0xF))
>> +#define CAP_MAX_LINK_SPEED_SET(dst, src)        (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +#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
>> +
>> +// LINK_CONTROL_LINK_STATUS_REG
>> +#define CAP_DLL_ACTIVE_GET(val)                 ((val & 0x20000000) >> 29)
>> +#define CAP_SLOT_CLK_CONFIG_SET(dst, src)       (((dst) & ~0x10000000) | (((UINT32) (src) << 28) & 0x10000000))
>> +#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_COMMON_CLK_SET(dst, src)            (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
>> +#define CAP_RETRAIN_LINK_SET(dst, src)          (((dst) & ~0x20) | (((UINT32) (src) << 5) & 0x20))
>> +#define CAP_LINK_TRAINING_GET(val)              ((val & 0x8000000) >> 27)
>> +#define CAP_LINK_DISABLE_SET(dst, src)          (((dst) & ~0x10) | (((UINT32)(src) << 4) & 0x10))
>> +
>> +// SLOT_CAPABILITIES_REG
>> +#define SLOT_HPC_SET(dst, src)                  (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
>> +#define SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET(dst, src) \
>> +                                                (((dst) & ~0x7F80) | (((UINT32)(src) << 7) & 0x7F80))
>> +
>> +// DEVICE_CONTROL2_DEVICE_STATUS2_REG
>> +#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src)     (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +
>> +// LINK_CONTROL2_LINK_STATUS2_REG
>> +#define CAP_TARGET_LINK_SPEED_SET(dst, src)     (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
>> +
>> +//
>> +// Advanced Error Reporting Capability
>> +//
>> +#define AER_CAPABILITY_ID                       0x0001
>> +#define UNCORR_ERR_STATUS_OFF                   0x04
>> +#define UNCORR_ERR_MASK_OFF                     0x08
>> +
>> +// 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))
>> +
>> +//
>> +// Vendor specific RAS D.E.S Capability
>> +//
>> +#define RAS_DES_CAPABILITY_ID                   0x000B
>> +#define EVENT_COUNTER_CONTROL_REG               0x08
>> +#define EVENT_COUNTER_DATA_REG                  0x0C
>> +
>> +// 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   EVENT_COUNTER_ENABLE_NO_CHANGE        0x00
>> +#define   EVENT_COUNTER_ENABLE_ALL_ON           0x07
>> +#define ECCR_EVENT_COUNTER_CLEAR_SET(dst, src)  (((dst) & ~0x3) | (((UINT32)(src)) & 0x3))
>> +#define   EVENT_COUNTER_CLEAR_NO_CHANGE         0x00
>> +#define   EVENT_COUNTER_CLEAR_ALL_CLEAR         0x03
>> +
>> +//
>> +// Secondary PCI Express Capability
>> +//
>> +#define SPCIE_CAPABILITY_ID                     0x0019
>> +#define SPCIE_CAP_OFF_0C_REG                    0x0C
>> +
>> +// SPCIE_CAP_OFF_0C_REG
>> +#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))
>> +#define DEFAULT_GEN3_PRESET                       0x05
>> +
>> +//
>> +//  Physical Layer 16.0 GT/s Extended Capability
>> +//
>> +#define PL16G_CAPABILITY_ID                     0x0026
>> +#define PL16G_STATUS_REG                        0x0C
>> +#define PL16G_CAP_OFF_20H_REG                   0x20
>> +
>> +// PL16G_STATUS_REG
>> +#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)
>> +
>> +// PL16G_CAP_OFF_20H_REG
>> +#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))
>> +#define   DEFAULT_GEN4_PRESET                   0x57
>> +
>> +//
>> +// Port Logic
>> +//
>> +#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
>> +
>> +// PORT_LINK_CTRL_OFF
>> +#define LINK_CAPABLE_SET(dst, src)              (((dst) & ~0x3F0000) | (((UINT32) (src) << 16) & 0x3F0000))
>> +#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 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_SET(dst, src)              (((dst) & ~0x1F00) | (((UINT32) (src) << 8) & 0x1F00))
>> +#define   NUM_OF_LANES_X2                       0x2
>> +#define   NUM_OF_LANES_X4                       0x4
>> +#define   NUM_OF_LANES_X8                       0x8
>> +#define   NUM_OF_LANES_X16                      0x10
>> +
>> +// GEN3_RELATED_OFF
>> +#define RATE_SHADOW_SEL_SET(dst, src)           (((dst) & ~0x3000000) | (((UINT32) (src) << 24) & 0x3000000))
>> +#define   GEN3_DATA_RATE                        0x00
>> +#define   GEN4_DATA_RATE                        0x01
>> +#define EQ_PHASE_2_3_SET(dst, src)              (((dst) & ~0x200) | (((UINT32) (src) << 9) & 0x200))
>> +#define   ENABLE_EQ_PHASE_2_3                   0x00
>> +#define   DISABLE_EQ_PHASE_2_3                  0x01
>> +#define RXEQ_REGRDLESS_SET(dst, src)            (((dst) & ~0x2000) | (((UINT32) (src) << 13) & 0x2000))
>> +#define   ASSERT_RXEQ                           0x01
>> +
>> +// GEN3_EQ_CONTROL_OFF
>> +#define GEN3_EQ_FB_MODE(dst, src)               (((dst) & ~0xF) | ((UINT32) (src) & 0xF))
>> +#define   FOM_METHOD                            0x01
>> +#define GEN3_EQ_PRESET_VEC(dst, src)            (((dst) & 0xFF0000FF) | (((UINT32) (src) << 8) & 0xFFFF00))
>> +#define   EQ_DEFAULT_PRESET_VECTOR              0x370
>> +#define GEN3_EQ_INIT_EVAL(dst,src)              (((dst) & ~0x1000000) | (((UINT32) (src) << 24) & 0x1000000))
>> +#define   INCLUDE_INIT_FOM                      0x01
>> +
>> +// MISC_CONTROL_1_OFF
>> +#define DBI_RO_WR_EN_SET(dst, src)              (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
>> +#define   ENABLE_WR                             0x01
>> +#define   DISABLE_WR                            0x00
>> +
>> +// 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_FREQ_SET(dst, src)                  (((dst) & ~0x1FF) | (((UINT32) (src)) & 0x1FF))
>> +#define   AUX_CLK_500MHZ                            500
>> +
>> +#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..846e8593f57d
>> --- /dev/null
>> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
>> @@ -0,0 +1,1419 @@
>> +/** @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 base address
>> +
>> +  @param RootComplex      Pointer to AC01_ROOT_COMPLEX structure
>> +  @param PcieIndex        PCIe controller index
>> +  @param IsRootComplex    TRUE: Checking RootComplex configuration space
>> +                          FALSE: Checking EP configuration space
>> +  @param ExtCapabilityId
>> +**/
>> +PHYSICAL_ADDRESS
>> +GetCapabilityBase (
>> +  IN AC01_ROOT_COMPLEX *RootComplex,
>> +  IN UINT8             PcieIndex,
>> +  IN BOOLEAN           IsRootComplex,
>> +  IN UINT16            ExtCapabilityId
>> +  )
>> +{
>> +  BOOLEAN                IsExtCapability = FALSE;
>> +  PHYSICAL_ADDRESS       CfgBase;
>> +  UINT32                 CapabilityId;
>> +  UINT32                 NextCapabilityPtr;
>> +  UINT32                 Val;
>> +
>> +  if (IsRootComplex) {
>> +    CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +  } else {
>> +    CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
>> +  }
>> +
>> +  Val = MmioRead32 (CfgBase + TYPE1_CAP_PTR_REG);
>> +  NextCapabilityPtr = GET_LOW_8_BITS (Val);
>> +
>> +  // Loop untill desired capability is found else return 0
>> +  while (1) {
>> +    if ((NextCapabilityPtr & WORD_ALIGN_MASK) != 0) {
>> +      // Not alignment, just return
>> +      return 0;
>> +    }
>> +
>> +    Val = MmioRead32 (CfgBase + NextCapabilityPtr);
>> +    if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
>> +      CapabilityId = GET_LOW_8_BITS (Val);
>> +    } else {
>> +      CapabilityId = GET_LOW_16_BITS (Val);
>> +    }
>> +
>> +    if (CapabilityId == ExtCapabilityId) {
>> +      return (CfgBase + NextCapabilityPtr);
>> +    }
>> +
>> +    if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
>> +      NextCapabilityPtr = GET_CAPABILITY_PTR (Val);
>> +    } else {
>> +      NextCapabilityPtr = GET_EXT_CAPABILITY_PTR (Val);
>> +    }
>> +
>> +    if ((NextCapabilityPtr == 0) && !IsExtCapability) {
>> +      IsExtCapability = TRUE;
>> +      NextCapabilityPtr = EXT_CAPABILITY_START_BASE;
>> +    }
>> +
>> +    if ((NextCapabilityPtr == 0) && IsExtCapability) {
>> +      return 0;
>> +    }
>> +  }
>> +}
>> +
>> +/**
>> +  Configure equalization settings for Gen3 and Gen4
>> +
>> +  @param RootComplex     Pointer to AC01_ROOT_COMPLEX structure
>> +  @param PcieIndex       PCIe controller index
>> +**/
>> +STATIC
>> +VOID
>> +ConfigureEqualization (
>> +  IN AC01_ROOT_COMPLEX *RootComplex,
>> +  IN UINT8             PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS     CfgBase;
>> +  PHYSICAL_ADDRESS     Gen3RelatedAddr;
>> +  PHYSICAL_ADDRESS     Gen3EqControlAddr;
>> +  UINT32               Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  //
>> +  // Gen3 and Gen4 EQ process use the same setting registers which are
>> +  // GEN3_RELATED_OFF and GEN3_EQ_CONTROL_OFF. Both are shadow registers
>> +  // and controlled by GEN3_RELATED_OFF[25:24].
>> +  //
>> +  Gen3RelatedAddr = CfgBase + GEN3_RELATED_OFF;
>> +  Gen3EqControlAddr = CfgBase + GEN3_EQ_CONTROL_OFF;
>> +
>> +  //
>> +  // Equalization setting for Gen3
>> +  //
>> +  Val = MmioRead32 (Gen3RelatedAddr);
>> +  Val = RATE_SHADOW_SEL_SET (Val, GEN3_DATA_RATE);
>> +  MmioWrite32 (Gen3RelatedAddr, Val);
>> +
>> +  Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
>> +  Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
>> +  MmioWrite32 (Gen3RelatedAddr, Val);
>> +
>> +  Val = MmioRead32 (Gen3EqControlAddr);
>> +  Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
>> +  Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
>> +  Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
>> +  MmioWrite32 (Gen3EqControlAddr, Val);
>> +
>> +  //
>> +  // Equalization setting for Gen4
>> +  //
>> +  Val = MmioRead32 (Gen3RelatedAddr);
>> +  Val = RATE_SHADOW_SEL_SET (Val, GEN4_DATA_RATE);
>> +  MmioWrite32 (Gen3RelatedAddr, Val);
>> +
>> +  Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
>> +  Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
>> +  MmioWrite32 (Gen3RelatedAddr, Val);
>> +
>> +  Val = MmioRead32 (Gen3EqControlAddr);
>> +  Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
>> +  Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
>> +  Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
>> +  MmioWrite32 (Gen3EqControlAddr, Val);
>> +}
>> +
>> +/**
>> +  Configure presets for Gen3 equalization
>> +
>> +  @param RootComplex     Pointer to AC01_ROOT_COMPLEX structure
>> +  @param PcieIndex       PCIe controller index
>> +**/
>> +STATIC
>> +VOID
>> +ConfigurePresetGen3 (
>> +  IN AC01_ROOT_COMPLEX *RootComplex,
>> +  IN UINT8             PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       LaneEqControlAddr;
>> +  PHYSICAL_ADDRESS       SpcieCapabilityBase;
>> +  UINT32                 Idx;
>> +  UINT32                 LinkWidth;
>> +  UINT32                 Val;
>> +
>> +  // Get the Secondary PCI Express Extended capability base address
>> +  SpcieCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, SPCIE_CAPABILITY_ID);
>> +  if (SpcieCapabilityBase == 0) {
>> +    DEBUG ((
>> +      DEBUG_ERROR,
>> +      "PCIE%d.%d: Cannot get SPCIE capability address\n",
>> +      RootComplex->ID,
>> +      PcieIndex
>> +      ));
>> +    return;
>> +  }
>> +
>> +  LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
>> +
>> +  // Each register holds the Preset for 2 lanes
>> +  for (Idx = 0; Idx < (LinkWidth / 2); Idx++) {
>> +    LaneEqControlAddr = SpcieCapabilityBase + SPCIE_CAP_OFF_0C_REG + Idx * sizeof (UINT32);
>> +    Val = MmioRead32 (LaneEqControlAddr);
>> +    Val = DSP_TX_PRESET0_SET (Val, DEFAULT_GEN3_PRESET);
>> +    Val = DSP_TX_PRESET1_SET (Val, DEFAULT_GEN3_PRESET);
>> +    MmioWrite32 (LaneEqControlAddr, Val);
>> +  }
>> +}
>> +
>> +/**
>> +  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       LaneEqControlAddr;
>> +  PHYSICAL_ADDRESS       Pl16gCapabilityBase;
>> +  UINT32                 Idx;
>> +  UINT32                 LinkWidth;
>> +  UINT32                 Val;
>> +  UINT8                  Preset;
>> +
>> +  // Get the Physical Layer 16.0 GT/s Extended capability base address
>> +  Pl16gCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, PL16G_CAPABILITY_ID);
>> +  if (Pl16gCapabilityBase == 0) {
>> +    DEBUG ((
>> +      DEBUG_ERROR,
>> +      "PCIE%d.%d: Cannot get PL16G capability address\n",
>> +      RootComplex->ID,
>> +      PcieIndex
>> +      ));
>> +    return;
>> +  }
>> +
>> +  if (RootComplex->PresetGen4[PcieIndex] == PRESET_INVALID) {
>> +    Preset = DEFAULT_GEN4_PRESET;
>> +  } else {
>> +    Preset = RootComplex->PresetGen4[PcieIndex];
>> +  }
>> +
>> +  LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
>> +
>> +  if (LinkWidth == CAP_MAX_LINK_WIDTH_X2) {
>> +    LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG;
>> +    Val = MmioRead32 (LaneEqControlAddr);
>> +    Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
>> +    Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
>> +    MmioWrite32 (LaneEqControlAddr, Val);
>> +  } else {
>> +    // Each register holds the Preset for 4 lanes
>> +    for (Idx = 0; Idx < (LinkWidth / 4); Idx++) {
>> +      LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG + Idx * sizeof (UINT32);
>> +      Val = MmioRead32 (LaneEqControlAddr);
>> +      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 (LaneEqControlAddr, Val);
>> +    }
>> +  }
>> +}
>> +
>> +VOID
>> +ProgramHostBridgeInfo (
>> +  AC01_ROOT_COMPLEX *RootComplex
>> +  )
>> +{
>> +  EFI_STATUS         Status;
>> +  PHYSICAL_ADDRESS   TargetAddress;
>> +  UINT32             Val;
>> +
>> +  // Program Root Complex Bifurcation
>> +  if (RootComplex->Active) {
>> +    if (RootComplex->Type == RootComplexTypeA) {
>> +      TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCA_DEV_MAP_REG;
>> +      Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
>> +      if (!RETURN_ERROR (Status)) {
>> +        Val = RCA_DEV_MAP_SET (Val, RootComplex->DevMapLow);
>> +        MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
>> +      }
>> +    } else {
>> +      TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCB_DEV_MAP_REG;
>> +      Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
>> +      if (!RETURN_ERROR (Status)) {
>> +        Val = RCB_DEV_MAP_LOW_SET (Val, RootComplex->DevMapLow);
>> +        Val = RCB_DEV_MAP_HIGH_SET (Val, RootComplex->DevMapHigh);
>> +        MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
>> +      }
>> +    }
>> +  }
>> +
>> +  // Program Vendor ID and Device ID
>> +  TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG;
>> +  Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
>> +  if (!RETURN_ERROR (Status)) {
>> +    Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
>> +    if (RootComplexTypeA == RootComplex->Type) {
>> +      Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCA);
>> +    } else {
>> +      Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCB);
>> +    }
>> +    MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
>> +  }
>> +}
>> +
>> +VOID
>> +ProgramRootPortInfo (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CfgBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32             Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  // Program Class Code
>> +  TargetAddress = CfgBase + TYPE1_CLASS_CODE_REV_ID_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = REVISION_ID_SET (Val, DEFAULT_REVISION_ID);
>> +  Val = SUB_CLASS_CODE_SET (Val, DEFAULT_SUB_CLASS_CODE);
>> +  Val = BASE_CLASS_CODE_SET (Val, DEFAULT_BASE_CLASS_CODE);
>> +  MmioWrite32 (TargetAddress, Val);
>> +
>> +  // Program Vendor ID and Device ID
>> +  TargetAddress = CfgBase + TYPE1_DEV_ID_VEND_ID_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
>> +  if (RootComplexTypeA == RootComplex->Type) {
>> +    Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCA + PcieIndex);
>> +  } else {
>> +    Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCB + PcieIndex);
>> +  }
>> +  MmioWrite32 (TargetAddress, Val);
>> +}
>> +
>> +VOID
>> +ProgramLinkCapabilities (
>> +  IN AC01_ROOT_COMPLEX *RootComplex,
>> +  IN UINT8             PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CfgBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 Val;
>> +  UINT8                  MaxWidth;
>> +  UINT8                  MaxGen;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  MaxWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
>> +  MaxGen = RootComplex->Pcie[PcieIndex].MaxGen;
>> +
>> +  TargetAddress = CfgBase + PORT_LINK_CTRL_OFF;
>> +  Val = MmioRead32 (TargetAddress);
>> +  switch (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 (TargetAddress, Val);
>> +
>> +  TargetAddress = CfgBase + GEN2_CTRL_OFF;
>> +  Val = MmioRead32 (TargetAddress);
>> +  switch (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 (TargetAddress, Val);
>> +
>> +  TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  switch (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 (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 (TargetAddress, Val);
>> +
>> +  TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL2_LINK_STATUS2_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  switch (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 (TargetAddress, Val);
>> +}
>> +
>> +VOID
>> +DisableCompletionTimeOut (
>> +  IN AC01_ROOT_COMPLEX  *RootComplex,
>> +  IN UINT8              PcieIndex,
>> +  IN BOOLEAN            IsMask
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CfgBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  TargetAddress = CfgBase + AER_CAPABILITY_BASE + UNCORR_ERR_MASK_OFF;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0);
>> +  MmioWrite32 (TargetAddress, Val);
>> +}
>> +
>> +BOOLEAN
>> +EnableItsMemory (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CsrBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 TimeOut;
>> +  UINT32                 Val;
>> +
>> +  CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
>> +
>> +  // Clear memory shutdown
>> +  TargetAddress = CsrBase + AC01_PCIE_CORE_RAM_SHUTDOWN_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = SD_SET (Val, 0);
>> +  MmioWrite32 (TargetAddress, Val);
>> +
>> +  // Poll till ITS Memory is ready
>> +  TimeOut = MEMRDY_TIMEOUT;
>> +  do {
>> +    Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_MEM_READY_REG);
>> +    if (Val & MEMORY_READY) {
>> +      return TRUE;
>> +    }
>> +
>> +    TimeOut--;
>> +    MicroSecondDelay (1);
>> +  } while (TimeOut > 0);
>> +
>> +  return FALSE;
>> +}
>> +
>> +BOOLEAN
>> +EnableAxiPipeClock (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CsrBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 TimeOut;
>> +  UINT32                 Val;
>> +
>> +  CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
>> +
>> +  // Enable subsystem clock and release reset
>> +  TargetAddress = CsrBase + AC01_PCIE_CORE_CLOCK_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = AXIPIPE_SET (Val, 1);
>> +  MmioWrite32 (TargetAddress, Val);
>> +
>> +  TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = DWC_PCIE_SET (Val, 0);
>> +  MmioWrite32 (TargetAddress, Val);
>> +
>> +  //
>> +  // Controller does not provide any indicator for reset released.
>> +  // Must wait at least 1us as per EAS.
>> +  //
>> +  MicroSecondDelay (1);
>> +
>> +  // Poll till PIPE clock is stable
>> +  TimeOut = PIPE_CLOCK_TIMEOUT;
>> +  do {
>> +    Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
>> +    if (!(Val & PHY_STATUS_MASK)) {
>> +      return TRUE;
>> +    }
>> +
>> +    TimeOut--;
>> +    MicroSecondDelay (1);
>> +  } while (TimeOut > 0);
>> +
>> +  return FALSE;
>> +}
>> +
>> +VOID
>> +SetLinkTimeout (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex,
>> +  UINTN             Timeout
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 Val;
>> +
>> +  TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
>> +                  + AMBA_LINK_TIMEOUT_OFF;
>> +
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, Timeout);
>> +  MmioWrite32 (TargetAddress, Val);
>> +}
>> +
>> +VOID
>> +StartLinkTraining (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex,
>> +  BOOLEAN           StartLink
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 Val;
>> +
>> +  TargetAddress = RootComplex->Pcie[PcieIndex].CsrBase + AC01_PCIE_CORE_LINK_CTRL_REG;
>> +
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = LTSSMENB_SET (Val, StartLink ? START_LINK_TRAINING : HOLD_LINK_TRAINING);
>> +  MmioWrite32 (TargetAddress, Val);
>> +}
>> +
>> +VOID
>> +EnableDbiAccess (
>> +  AC01_ROOT_COMPLEX *RootComplex,
>> +  UINT32            PcieIndex,
>> +  BOOLEAN           EnableDbi
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  UINT32                 Val;
>> +
>> +  TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
>> +                  + MISC_CONTROL_1_OFF;
>> +
>> +  Val = MmioRead32 (TargetAddress);
>> +  Val = DBI_RO_WR_EN_SET (Val, EnableDbi ? ENABLE_WR : DISABLE_WR);
>> +  MmioWrite32 (TargetAddress, Val);
>> +}
>> +
>> +/**
>> +  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 controller 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     CfgBase;
>> +  PHYSICAL_ADDRESS     CsrBase;
>> +  PHYSICAL_ADDRESS     TargetAddress;
>> +  RETURN_STATUS        Status;
>> +  UINT32               Val;
>> +  UINT8                PcieIndex;
>> +
>> +  DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex->Socket, RootComplex->ID));
>> +
>> +  ProgramHostBridgeInfo (RootComplex);
>> +
>> +  if (!ReInit) {
>> +    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;
>> +    CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +    // Put Controller into reset if not in reset already
>> +    TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
>> +    Val = MmioRead32 (TargetAddress);
>> +    if (!(Val & RESET_MASK)) {
>> +      Val = DWC_PCIE_SET (Val, ASSERT_RESET);
>> +      MmioWrite32 (TargetAddress, Val);
>> +
>> +      // Delay 50ms to ensure controller finish its reset
>> +      MicroSecondDelay (50000);
>> +    }
>> +
>> +    if (!EnableItsMemory (RootComplex, PcieIndex)) {
>> +      DEBUG ((DEBUG_ERROR, "- Pcie[%d] - ITS Memory is not ready\n", PcieIndex));
>> +      return RETURN_DEVICE_ERROR;
>> +    }
>> +
>> +    // Hold link training
>> +    StartLinkTraining (RootComplex, PcieIndex, FALSE);
>> +
>> +    if (!EnableAxiPipeClock (RootComplex, PcieIndex)) {
>> +      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
>> +    EnableDbiAccess (RootComplex, PcieIndex, TRUE);
>> +
>> +    // Program the power limit
>> +    TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + SLOT_CAPABILITIES_REG;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT_75W);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    // Program DTI for ATS support
>> +    TargetAddress = CfgBase + DTIM_CTRL0_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0);
>> +    MmioWrite32 (TargetAddress, 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
>> +    TargetAddress = CfgBase + FILTER_MASK_2_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    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 (TargetAddress, Val);
>> +
>> +    TargetAddress = CfgBase + AMBA_ORDERING_CTRL_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = AX_MSTR_ZEROLREAD_FW_SET (Val, 0);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    //
>> +    // Set Completion with CRS handling for CFG Request
>> +    // Set Completion with CA/UR handling non-CFG Request
>> +    //
>> +    TargetAddress = CfgBase + AMBA_ERROR_RESPONSE_DEFAULT_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    // 0x2: OKAY with FFFF_0001 and FFFF_FFFF
>> +    Val = AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    // Set Legacy PCIE interrupt map to INTA
>> +    TargetAddress = CfgBase + BRIDGE_CTRL_INT_PIN_INT_LINE_REG;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = INT_PIN_SET (Val, IRQ_INT_A);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    TargetAddress = CsrBase + AC01_PCIE_CORE_IRQ_SEL_REG;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = INTPIN_SET (Val, IRQ_INT_A);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN2) {
>> +      ConfigureEqualization (RootComplex, PcieIndex);
>> +      if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN3) {
>> +        ConfigurePresetGen3 (RootComplex, PcieIndex);
>> +        if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN4) {
>> +          ConfigurePresetGen4 (RootComplex, PcieIndex);
>> +        }
>> +      }
>> +    }
>> +
>> +    // Link timeout after 1ms
>> +    SetLinkTimeout (RootComplex, PcieIndex, 1);
>> +
>> +    DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
>> +
>> +    ProgramRootPortInfo (RootComplex, PcieIndex);
>> +
>> +    // Enable common clock for downstream
>> +    TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
>> +    Val = CAP_COMMON_CLK_SET (Val, 1);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    // Match aux_clk to system
>> +    TargetAddress = CfgBase + AUX_CLK_FREQ_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ);
>> +    MmioWrite32 (TargetAddress, Val);
>> +
>> +    // Assert PERST low to reset endpoint
>> +    BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE);
>> +
>> +    // Start link training
>> +    StartLinkTraining (RootComplex, PcieIndex, TRUE);
>> +
>> +    // Complete the PERST pulse
>> +    BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
>> +
>> +    // Lock programming of config space
>> +    EnableDbiAccess  (RootComplex, PcieIndex, FALSE);
>> +
>> +    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 + AC01_PCIE_CORE_LINK_STAT_REG);
>> +  LinkStat = LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT |
>> +                         SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT);
>> +  if (LinkStat == 0) {
>> +    return FALSE;
>> +  }
>> +
>> +  BlockEvent = MmioRead32 (CsrBase + AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG);
>> +  LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
>> +
>> +  if (((BlockEvent & LINKUP_MASK) != 0)
>> +      && (SMLH_LTSSM_STATE_GET(LinkStat) == LTSSM_STATE_L0)) {
>> +    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                TargetAddress;
>> +  UINT32                          PcieIndex;
>> +  UINT32                          Val;
>> +
>> +  if (RootComplex == NULL || !RootComplex->Active) {
>> +    return;
>> +  }
>> +
>> +  // Clear uncorrectable error during enumuration phase. Mainly completion timeout.
>> +  for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
>> +    if (!RootComplex->Pcie[PcieIndex].Active) {
>> +      continue;
>> +    }
>> +
>> +    if (!PcieLinkUpCheck(&RootComplex->Pcie[PcieIndex])) {
>> +      // If link down/disabled after enumeration, disable completed time out
>> +      DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
>> +    }
>> +
>> +    // Clear all errors
>> +    TargetAddress = RootComplex->MmcfgBase + ((PcieIndex + 1) << DEV_SHIFT) \
>> +                    + AER_CAPABILITY_BASE + UNCORR_ERR_STATUS_OFF;
>> +    Val = MmioRead32 (TargetAddress);
>> +    if (Val != 0) {
>> +      // Clear error by writting
>> +      MmioWrite32 (TargetAddress, Val);
>> +    }
>> +  }
>> +}
>> +
>> +/**
>> +  Comparing current link status with the max capabilities of the link
>> +
>> +  @param RootComplex   Pointer to AC01_ROOT_COMPLEX structure
>> +  @param PcieIndex     PCIe controller 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, CfgBase;
>> +  UINT32                Val, LinkStat;
>> +  UINT32                MaxWidth, MaxGen;
>> +
>> +  CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + 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 + AC01_PCIE_CORE_LINK_STAT_REG);
>> +  Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG);
>> +  DEBUG ((
>> +    DEBUG_INFO,
>> +    "PCIE%d.%d: Link MaxWidth %d MaxGen %d, AC01_PCIE_CORE_LINK_STAT_REG 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              RasDesCapabilityBase
>> +  )
>> +{
>> +  INT32                  Ret = LINK_CHECK_SUCCESS;
>> +  UINT32                 Val;
>> +  UINT8                  ErrCode, ErrGrpNum;
>> +
>> +  UINT32 ErrCtrlCfg[] = {
>> +    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 < ARRAY_SIZE (ErrCtrlCfg); ErrCode++) {
>> +    ErrGrpNum = GET_HIGH_8_BITS (ErrCtrlCfg[ErrCode]);
>> +    // Skipping per lane group
>> +    // Checking common lane group because AER error are included in common group only
>> +    if ((ErrGrpNum != 0) && (ErrGrpNum != 4)) {
>> +      Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG);
>> +      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 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG, Val);
>> +
>> +      // After setting Counter Control reg
>> +      // This delay just to make sure Counter Data reg is update with new value
>> +      MicroSecondDelay (1);
>> +      Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_DATA_REG);
>> +      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,
>> +          ErrGrpNum,
>> +          GET_LOW_8_BITS (ErrCtrlCfg[ErrCode])
>> +          ));
>> +      }
>> +    }
>> +  }
>> +
>> +  return Ret;
>> +}
>> +
>> +/**
>> +  Handle Predictive Failure Analysis command
>> +
>> +  @param RootComplex           Pointer to Root Complex structure
>> +  @param PcieIndex             PCIe controller index
>> +  @param PFAMode               The PFA mode
>> +
>> +  @retval                      The link status
>> +**/
>> +INT32
>> +Ac01PFACommand (
>> +  IN AC01_ROOT_COMPLEX   *RootComplex,
>> +  IN UINT8               PcieIndex,
>> +  IN UINT8               PFAMode
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS       CfgBase;
>> +  PHYSICAL_ADDRESS       RasDesCapabilityBase;
>> +  PHYSICAL_ADDRESS       TargetAddress;
>> +  INT32                  Ret = LINK_CHECK_SUCCESS;
>> +  UINT32                 Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +  // Allow programming to config space
>> +  EnableDbiAccess (RootComplex, PcieIndex, TRUE);
>> +
>> +  // Get the RAS D.E.S. capability base address
>> +  RasDesCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, RAS_DES_CAPABILITY_ID);
>> +  if (RasDesCapabilityBase == 0) {
>> +    DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\n", RootComplex->ID, PcieIndex));
>> +    return LINK_CHECK_WRONG_PARAMETER;
>> +  }
>> +
>> +  TargetAddress = RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG;
>> +
>> +  switch (PFAMode) {
>> +  case PFA_MODE_ENABLE:
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_ALL_ON);
>> +    Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_NO_CHANGE);
>> +    MmioWrite32 (TargetAddress, Val);
>> +    break;
>> +
>> +  case PFA_MODE_CLEAR:
>> +    Val = MmioRead32 (TargetAddress);
>> +    Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_NO_CHANGE);
>> +    Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_ALL_CLEAR);
>> +    MmioWrite32 (TargetAddress, Val);
>> +    break;
>> +
>> +  case PFA_MODE_READ:
>> +    Ret = PFACounterRead (RootComplex, PcieIndex, RasDesCapabilityBase);
>> +    break;
>> +
>> +  default:
>> +    DEBUG ((DEBUG_ERROR, "%a: Invalid PFA mode\n"));
>> +  }
>> +
>> +  // Disable programming to config space
>> +  EnableDbiAccess (RootComplex, PcieIndex, FALSE);
>> +
>> +  return Ret;
>> +}
>> +
>> +UINT32
>> +EndpointCfgReady (
>> +  IN AC01_ROOT_COMPLEX  *RootComplex,
>> +  IN UINT8              PcieIndex
>> +  )
>> +{
>> +  PHYSICAL_ADDRESS      CfgBase;
>> +  UINT32                TimeOut;
>> +  UINT32                Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
>> +
>> +  // Loop read CfgBase value until got valid value or
>> +  // reach to timeout EP_LINKUP_TIMEOUT (or more depend on card)
>> +  TimeOut = EP_LINKUP_TIMEOUT;
>> +  do {
>> +    Val = MmioRead32 (CfgBase);
>> +    if (Val != 0xFFFF0001 && Val != 0xFFFFFFFF) {
>> +      return TRUE;
>> +    }
>> +
>> +    TimeOut -= LINK_WAIT_INTERVAL_US;
>> +    MicroSecondDelay (LINK_WAIT_INTERVAL_US);
>> +  } while (TimeOut > 0);
>> +
>> +  return FALSE;
>> +}
>> +
>> +/**
>> +   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      CfgBase;
>> +  PHYSICAL_ADDRESS      PcieCapBase;
>> +  PHYSICAL_ADDRESS      SecLatTimerAddr;
>> +  PHYSICAL_ADDRESS      TargetAddress;
>> +  UINT32                RestoreVal;
>> +  UINT32                Val;
>> +
>> +  CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +  SecLatTimerAddr  = CfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG;
>> +
>> +  *EpMaxWidth = 0;
>> +  *EpMaxGen = 0;
>> +
>> +  // Allow programming to config space
>> +  EnableDbiAccess (RootComplex, PcieIndex, TRUE);
>> +
>> +  Val = MmioRead32 (SecLatTimerAddr);
>> +  RestoreVal = Val;
>> +  Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS);
>> +  Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum);
>> +  Val = PRIM_BUS_SET (Val, DEFAULT_PRIM_BUS);
>> +  MmioWrite32 (SecLatTimerAddr, Val);
>> +
>> +  if (EndpointCfgReady (RootComplex, PcieIndex)) {
>> +    PcieCapBase = GetCapabilityBase (RootComplex, PcieIndex, FALSE, PCIE_CAPABILITY_ID);
>> +    if (PcieCapBase == 0) {
>> +      DEBUG ((
>> +        DEBUG_ERROR,
>> +        "PCIE%d.%d Cannot get PCIe capability base address!\n",
>> +        RootComplex->ID,
>> +        PcieIndex
>> +        ));
>> +    } else {
>> +      Val = MmioRead32 (PcieCapBase + LINK_CAPABILITIES_REG);
>> +      *EpMaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
>> +      *EpMaxGen = CAP_MAX_LINK_SPEED_GET (Val);
>> +      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
>> +      TargetAddress = PcieCapBase + LINK_CONTROL_LINK_STATUS_REG;
>> +      Val = MmioRead32 (TargetAddress);
>> +      Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
>> +      Val = CAP_COMMON_CLK_SET (Val, 1);
>> +      MmioWrite32 (TargetAddress, Val);
>> +    }
>> +  }
>> +
>> +  // Restore value in order to not affect enumeration process
>> +  MmioWrite32 (SecLatTimerAddr, RestoreVal);
>> +
>> +  // Disable programming to config space
>> +  EnableDbiAccess (RootComplex, PcieIndex, FALSE);
>> +}
>> +
>> +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       LinkStatusCheck, RasdesChecking;
>> +  INT32       NumberOfReset = MAX_REINIT;
>> +  UINT8       EpMaxWidth, EpMaxGen;
>> +
>> +  // 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
>> +      Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_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 = Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_READ);
>> +
>> +      // Clear error counter
>> +      Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_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          CfgBase;
>> +  UINT8                     PcieIndex;
>> +  UINT32                    Index;
>> +  UINT32                    Val;
>> +
>> +  *IsNextRoundNeeded = FALSE;
>> +  *FailedPcieCount   = 0;
>> +  for (Index = 0; Index < MaxPcieControllerOfRootComplexB; Index++) {
>> +    FailedPciePtr[Index] = -1;
>> +  }
>> +
>> +  if (!RootComplex->Active) {
>> +    return;
>> +  }
>> +
>> +  // Loop for all controllers
>> +  for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
>> +    Pcie = &RootComplex->Pcie[PcieIndex];
>> +    CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
>> +
>> +    if (Pcie->Active && !Pcie->LinkUp) {
>> +      if (PcieLinkUpCheck (Pcie)) {
>> +        Pcie->LinkUp = TRUE;
>> +        Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + 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);
>> +
>> +        // Link timeout after 32ms
>> +        SetLinkTimeout (RootComplex, PcieIndex, 32);
>> +
>> +        // Un-mask Completion Timeout
>> +        DisableCompletionTimeOut (RootComplex, PcieIndex, 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, NextRoundNeeded;
>> +  UINT64  PrevTick, CurrTick, ElapsedCycle;
>> +  UINT64  TimerTicks64;
>> +  UINT8   ReInit;
>> +  INT8    FailedPciePtr[MaxPcieControllerOfRootComplexB];
>> +  INT8    FailedPcieCount;
>> +
>> +  ReInit = 0;
>> +
>> +_link_polling:
>> +  NextRoundNeeded = FALSE;
>> +  //
>> +  // 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 += MAX_UINT64 - 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 = TRUE;
>> +    }
>> +  }
>> +
>> +  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
>>

  reply	other threads:[~2021-11-18 13:34 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-17 16:46 [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform Nhi Pham
2021-11-17 16:46 ` [edk2-platforms][PATCH v5 01/30] Ampere: Initial support for Ampere Altra processor and " Nhi Pham
2021-11-17 16:46 ` [edk2-platforms][PATCH v5 02/30] AmpereAltraPkg: Add FlashLib library instance Nhi Pham
2021-11-18 12:50   ` Leif Lindholm
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 03/30] AmpereAltraPkg: Add DwI2cLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 04/30] AmpereAltraPkg: Add DwGpioLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 05/30] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 06/30] AmpereAltraPkg: Add BootProgress support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 07/30] AmpereAltraPkg: Support UEFI non-volatile variable Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 08/30] AmpereSiliconPkg: Add PlatformManagerUiLib library instance Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 09/30] AmpereAltraPkg, JadePkg: Add ACPI support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 10/30] AmpereAltraPkg: Add Root Complex HOB data structures Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance Nhi Pham
2021-11-18 12:33   ` Leif Lindholm
2021-11-18 13:33     ` Nhi Pham [this message]
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 12/30] JadePkg: Add BoardPcieLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 13/30] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 14/30] AmpereAltraPkg: Add PciHostBridgeLib library instance Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 15/30] AmpereAltraPkg: Add PciSegmentLib " Nhi Pham
2021-11-18 13:10   ` Leif Lindholm
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 16/30] JadePkg: Enable PciHostBridgeDxe driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 17/30] JadePkg: Add PciPlatformDxe driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 18/30] JadePkg: Add ACPI tables to support PCIe Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 19/30] JadePkg: Add ASpeed GOP driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 20/30] AmpereAltraPkg: Add Random Number Generator Support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 21/30] JadePkg: Add SMBIOS tables support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 22/30] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 23/30] AmpereAltraPkg: Add configuration screen for PCIe Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 24/30] Ampere: Utilize the PCIe User setting Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 25/30] AmpereAltraPkg: Add platform info screen Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 26/30] AmpereAltraPkg: Add configuration screen for Memory Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 27/30] AmpereAltraPkg: Add configuration screen for CPU Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 28/30] AmpereAltraPkg: Add configuration screen for ACPI Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 29/30] AmpereAltraPkg: Add configuration screen for RAS Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 30/30] AmpereAltraPkg: Add configuration screen for Watchdog timer Nhi Pham
2021-11-18 13:02 ` [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform Leif Lindholm
2021-11-18 13:45   ` Nhi Pham
2021-11-18 14:25     ` Leif Lindholm

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=f74dc867-5b1f-ad4c-1124-54b2b765711b@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