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