From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by mx.groups.io with SMTP id smtpd.web08.878.1637238805075503642 for ; Thu, 18 Nov 2021 04:33:25 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=vliHPl3S; spf=pass (domain: nuviainc.com, ip: 209.85.221.50, mailfrom: leif@nuviainc.com) Received: by mail-wr1-f50.google.com with SMTP id d27so11232546wrb.6 for ; Thu, 18 Nov 2021 04:33:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20210112.gappssmtp.com; s=20210112; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=Vbi/k4+0676UlYmTocS2Um0m1m7trInxiC0BIndM+IE=; b=vliHPl3SXOFzJJIOlN+Ici5e5m2hFGgig0qa7xhKNYNoCHCxdKOXDoVf48lT/WWv41 gSa7WMMMWtXvKUNV1AbognE3PKA3yDxL2BrdFYXtTty/ycx98Kq8N6Smiv+CCqjnNY2x wY3OtwyjXRjGgYloHUvvDRplTe1OAiJengNabKKQt61a85/AUv6SRpAQstRVrDIyY9sb NmY9wFJhde5CFwUwsUyN/Y8UaQxmlZ7QlMpvpFn/N5wa6sl1yCJtP5u30EC8voCQgTCQ tGQ2m8VAoOlx2sBAOi7UWqHkFlc8LzyF9cwsIUoWt26JBpfQPCTSE90IjiAPRjvCpEZc 1k1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=Vbi/k4+0676UlYmTocS2Um0m1m7trInxiC0BIndM+IE=; b=SG+hHBjqNe/CMwVP0zsMq+o1AA/IrgYErtbRJYFt6vOtQfmuRFk17uFtebr9k9v5r/ p67Ewtuw0rrrKuUCSzPWyoURzSF3d8aLBF+0NQBQeGKrvW2tYAUikYAqp0lHZru8neU6 mSn/toGGLRCQ5u63YKszOfQH+quusC3PQ/+irlyrGc1CwWCRNJCuP8IpmwEDpD36TNJh /RU59MJ2BkwTbCkqfNAffNK2oGjEub3Yb5Ww5ASRnnZIz3QOnmirzNwn5DhjwNjAq3rE gBI/13vrOogLvrBbVKuuI+TVv0ctVg84SWxMAWpOkYxFpyD6F5qoGnO4yaM+7lZp99Sz TOfQ== X-Gm-Message-State: AOAM532R22r8vKAFRjOcJv8oYExtJ3uAqUo3KtvkSH9cY+RlUr84tjON jbRoY/ipNwhqT1GLFoSzAzb+tQ== X-Google-Smtp-Source: ABdhPJxn3q+RjdUov1qnWC0eNQEZqh6+Y5wuIS06I1RHpx/OoSvyeR3Par77CjwQm62DnTiJeCm0cw== X-Received: by 2002:adf:f08d:: with SMTP id n13mr31743279wro.395.1637238803207; Thu, 18 Nov 2021 04:33:23 -0800 (PST) Return-Path: Received: from leviathan (cpc92314-cmbg19-2-0-cust559.5-4.cable.virginm.net. [82.11.186.48]) by smtp.gmail.com with ESMTPSA id i15sm10488172wmq.18.2021.11.18.04.33.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Nov 2021 04:33:22 -0800 (PST) Date: Thu, 18 Nov 2021 12:33:20 +0000 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, patches@amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v5 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance Message-ID: References: <20211117164727.10922-1-nhi@os.amperecomputing.com> <20211117164727.10922-12-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20211117164727.10922-12-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hi Nhi, On Wed, Nov 17, 2021 at 23:47:08 +0700, Nhi Pham wrote: > From: Vu Nguyen > > 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. In case your toolchain does not expose this bug, I'm using: gcc version 10.2.1 20210110 (Debian 10.2.1-6) Best Regards, Leif > Cc: Thang Nguyen > Cc: Chuong Tran > Cc: Phong Vo > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Ard Biesheuvel > Cc: Nate DeSimone > > Signed-off-by: Nhi Pham > --- > 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.
> +# > +# 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.
> +# > +# 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.
> + > + 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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef BOARD_PCIE_LIB_H_ > +#define BOARD_PCIE_LIB_H_ > + > +#include > + > +/** > + 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.
> + > + 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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +/** > + 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 >