From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from NAM11-BN8-obe.outbound.protection.outlook.com (NAM11-BN8-obe.outbound.protection.outlook.com [40.107.236.117])
 by mx.groups.io with SMTP id smtpd.web08.4749.1634883607712135541
 for <devel@edk2.groups.io>;
 Thu, 21 Oct 2021 23:20:08 -0700
Authentication-Results: mx.groups.io;
 dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=jq+jScMS;
 spf=pass (domain: os.amperecomputing.com, ip: 40.107.236.117, mailfrom: nhi@os.amperecomputing.com)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=cocUrjOhu8o6pRjd7S+hv2OCUdg7KRyMEXNO/yvYqDEQ15T4lCg9CM8DqbQL17t3ebwfgMzI/MY0YNnD1S232utjpquLV1XWHIpJUMdIMhvkEcEqcSW6Qzt34AROuD+VLH1AVcSupp3zE5aiDKnNlzoYEV2t3JhePBzD0M/7V5iNROL6Bm2YSZFcSdeIYZs+G8PMGQFxhFAHvNjS9NOGcxEY/EgSfwsmXhflC4XEcOG6DatbQydUl+TQ6OuTQLpA6ld7hjyWNiWVFYHdUSa8NRncT8FV/Off2DzEQSczZXkflqB/0Bey6lMjq2SgVTHKVDDIzVOFS5cQpyicNDVvog==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=McDJsno1yOW8rJEZS4YKlj1V0WjarJ4Waw2kVGjEi90=;
 b=LJ17qFbUmn2zBLxiMK0xeyidCUftgALYgo0sObORQRESxNMZTYgs7HwDvBk7FN9tQF9m80tBoGlVS+TM2NMt+uHNLnOU3MSLK1OHE3oEa1G0/1v151LxQjuP3aVpa2NFrfTXhlQJIrTTLU7qGD/l7ZFa3TJLX6Dh50Oypap5wDoABACO3JhDD16Ut1zm15W0sdGXUE8FuNUG76d3/X+te6evjAIJZRHvBVGfJD5FKI+1tW818tXeDOLDjgEqXrpwDRRbUGzKQ/X9KwjBlaDDgnW388Qu/00Q8/QPQ4ATzPAm+qOQCDcAmrq5nr9YkxysswhqC+zj1gxgzj/zY0p3zA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none
 header.from=os.amperecomputing.com; dkim=pass
 header.d=os.amperecomputing.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=os.amperecomputing.com; s=selector2;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=McDJsno1yOW8rJEZS4YKlj1V0WjarJ4Waw2kVGjEi90=;
 b=jq+jScMSNbJS40N+0mQ2nQN3z/z8T9k+ADiuz6ZZ/E/g5O7yxCtQAo4p6jJOVYedvPO2ttbsyhH4WJjPSA84yG3BJKKtcpimyl2r6wOSdqfncBeqcRIVM7ffxE3BrK0Ruz3za+ak6c9V/ePCiLhXC20CrXieifBh7PdFnHMdtds=
Authentication-Results: edk2.groups.io; dkim=none (message not signed)
 header.d=none;edk2.groups.io; dmarc=none action=none
 header.from=os.amperecomputing.com;
Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by
 PH0PR01MB6325.prod.exchangelabs.com (2603:10b6:510:1e::15) with Microsoft
 SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.4628.18; Fri, 22 Oct 2021 06:20:05 +0000
Received: from PH0PR01MB7287.prod.exchangelabs.com
 ([fe80::254c:9533:7f35:aee]) by PH0PR01MB7287.prod.exchangelabs.com
 ([fe80::254c:9533:7f35:aee%4]) with mapi id 15.20.4628.016; Fri, 22 Oct 2021
 06:20:05 +0000
From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: devel@edk2.groups.io
CC: patches@amperecomputing.com,
	nhi@os.amperecomputing.com,
	vunguyen@os.amperecomputing.com,
	Thang Nguyen <thang@os.amperecomputing.com>,
	Chuong Tran <chuong@os.amperecomputing.com>,
	Phong Vo <phong@os.amperecomputing.com>,
	Leif Lindholm <leif@nuviainc.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance
Date: Fri, 22 Oct 2021 13:17:50 +0700
Message-ID: <20211022061809.31087-13-nhi@os.amperecomputing.com>
X-Mailer: git-send-email 2.17.1
In-Reply-To: <20211022061809.31087-1-nhi@os.amperecomputing.com>
References: <20211022061809.31087-1-nhi@os.amperecomputing.com>
X-ClientProxiedBy: HK2PR02CA0168.apcprd02.prod.outlook.com
 (2603:1096:201:1f::28) To PH0PR01MB7287.prod.exchangelabs.com
 (2603:10b6:510:10a::21)
Return-Path: nhi@os.amperecomputing.com
MIME-Version: 1.0
Received: from sw004.amperecomputing.com (118.69.219.201) by HK2PR02CA0168.apcprd02.prod.outlook.com (2603:1096:201:1f::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4628.16 via Frontend Transport; Fri, 22 Oct 2021 06:20:02 +0000
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: 2ea2cc47-a069-41b1-437c-08d99523fcb5
X-MS-TrafficTypeDiagnostic: PH0PR01MB6325:
X-Microsoft-Antispam-PRVS: 
	<PH0PR01MB6325527A0130ED7EC6548BF396809@PH0PR01MB6325.prod.exchangelabs.com>
X-MS-Oob-TLC-OOBClassifiers: OLM:2657;
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: 
	EMCBTXuL8381YsWHo0uJH7WiramoFJ9CQHNpAmMpnO67hXSEnSB8ySkbRL0tDKnH4gTzTl1qnHaajjqQLu4iGqw90PhY1Qk8DhCSo1M1M7Kg8yPuPEByRhHws9WKOCNZUUisMYW/d1o3/3/KHfeD20TpyyusQIDP0Y3ga0an0l6kGJffcgIE2xfHlW3yFpf/jyNuoA+cj71WpDHqsybgmRwSKomuSHcCG/UUVhJVF06+kxMAdezHu4hSiJ2caE8oSygQPPPJK5/noHp3Isn0Ilj35/vpUWRBjEbB6qeglUgFcbwtGvI4Yexd5I6DjBtE2zmyI1bA8auVoAgP8+FAv2j4FpspT6sl59EamvVW5E3gUoB2lNxVEklybDX55o1HGG+0DfR/1pCkM0l1Si9sVjCB5jKdk72n0ft1IbayvQXbjzFwS2J/RrJ8W5/zcgD3fQjfmZAOgAHvObQPr4CVLEA7yqiCGkId3ON6xWmmSHqEebCskqndjUmP/5/9x+xBwqElHXP2dVsK7PHYu3VFgQDFkwE7I1IDoM3DwhwifFy9xkQbExCumVJaFz2lkgQ4z+MtDktRi2V2EYSp8dQrwJx2zNttIx55WVu+NTb9TbMoycKekU7xd342lIRiMR66Gb9/YuRWwXDjSxs5kiK7vts71wLdmwKCxdRWRnYRdKBJ2ZC9HqVCFkxwfklJTDqzZO4q1vaEpA+0uLn9OnvVDg==
X-Forefront-Antispam-Report: 
	CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR01MB7287.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6506007)(5660300002)(6666004)(8936002)(19627235002)(38100700002)(38350700002)(6486002)(186003)(26005)(508600001)(1076003)(316002)(8676002)(54906003)(6916009)(66476007)(66556008)(6512007)(66946007)(83380400001)(86362001)(956004)(4326008)(30864003)(2616005)(52116002)(2906002)(559001)(579004);DIR:OUT;SFP:1102;
X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
X-MS-Exchange-AntiSpam-MessageData-0: 
	=?us-ascii?Q?+V3f5BxRuE+HDPMxgmFTFHXiLIvytl8kjHaiDFLZD068OtowOJ/WbAMpTN6X?=
 =?us-ascii?Q?hoG6uWQzwRoCBTz46oGJS7SyzL60/0+KRupqVIPhk/gLQpBo7yPrZuiuVUlB?=
 =?us-ascii?Q?+sldWJGImY6gU+OM1xMphfwykHqDnCufa6FlpMnaIF+HA9haBp5Wp2S/3fiQ?=
 =?us-ascii?Q?RM9hrGMW7I3/Lbyirspq31u3FIQBMpcyhRO/RqZ7ZJ/qrmazXsuO80wciVBS?=
 =?us-ascii?Q?kC0OFm59DoUq01cpEyFdxYz4ZdzDUU/mQKKhB69C41apmqNf1RPa8nmYe5ZM?=
 =?us-ascii?Q?Piide8msBi4O/tzFTgcFtUVK0ddeXrJ2OsMcAJEne63BW6+u/iycEqDCjw2U?=
 =?us-ascii?Q?n829m45eR0d+7FPaJtkEYP5wAvTDegCcYsdWOLcf3qB7QW8VqOsPA5uT8APE?=
 =?us-ascii?Q?eNRG0s0MZw16nZDOEU3rRzAEbuEhiNGTuqA6NEte3ECamR6hkWWwmN3VLzoz?=
 =?us-ascii?Q?93YRfkWSURi9OmnPJqM9IK0wXNYYpeTmFAcAx30B1ad9raldChBrUy+f9aT0?=
 =?us-ascii?Q?Ci06wm3hXxwTVcH7hAW9DJWgVRnoiKZmvBY++YZibyueDK9SM7BuawlJwJDn?=
 =?us-ascii?Q?xUaCu+On86OeqbkyrtcfKdBLUCAhWH/c9jn/iH33nRGZpvDXEsohgAF02bOI?=
 =?us-ascii?Q?HybFpmNrBcRYCypQaLboxmuf9PapzwmjQjah3nHVEBsRgxjWsGet/gBgQmuV?=
 =?us-ascii?Q?aWDUX8XACsQafYT4A41QFTLVrHdh5s/YuPtjrI4caKZV14iweN/sNZq5zZjx?=
 =?us-ascii?Q?ZYFHGxwoA4R6w/kcH8lmTS2SxxlG2VEDoO1IE0KuSA2XSfZhpTirVCx5rHxN?=
 =?us-ascii?Q?PR7cCIv3Rlg1rhmdYwCNOzngYFOa9sYcmuwh+/jPbIXc3BKKLTCwoFwxiCMl?=
 =?us-ascii?Q?gtsJPOykS+3Khi+3oZVbWucSn29uXUmNUX5jl7/xjs09cURXSyu02MyaLpCY?=
 =?us-ascii?Q?iOEdVFTNm7N7bvE+gk3VcqJhRwVuKpuDDpR8OYx+898D22+okGr1UgiAPrgD?=
 =?us-ascii?Q?4Y1wjs8grIuSG8jpNoFTR5LiIB4eJysdbYDVlVJi8+OAZgMsAy4ti/EfPY60?=
 =?us-ascii?Q?B/LFjugPL6DoqeAyJEB+YlDgkLqcRnq4x6ZnNuMHZPeOXYEuG92Lb43ScD8E?=
 =?us-ascii?Q?DeVqJpJhCXIvQ91o+Uv7hhEaNDlGxijFC9Gr2kdRbItywv3nRH+9F3F7ZfYj?=
 =?us-ascii?Q?R0Ih3ZrBZ0lOiFHQaRI7cMdmlmOTqpvQYU6ejArvMnX9HucIfs8oqYGQ2XMa?=
 =?us-ascii?Q?deMVARCpp3A8FlLtQew0ZFnPHVmnOzodRDPuvPoYETSDOdYXzyQ7pvcIrbjk?=
 =?us-ascii?Q?W0frgS+w10kfgZF3pRLJImXntIQQ+S4F9sz+cLXMB+5UKTU/yASu+vkKjCdK?=
 =?us-ascii?Q?MYfnEyZY5VcrvIXTP3aerJR8ww2Z7YXUTPbPk0zbHnIPdSMd/wz8WYzAbkFs?=
 =?us-ascii?Q?QZZ29VcSSEx4r/qylMyzU56gUQMuUC9dyX9J8l4UC6zjKYzLAd9y2g=3D=3D?=
X-OriginatorOrg: os.amperecomputing.com
X-MS-Exchange-CrossTenant-Network-Message-Id: 2ea2cc47-a069-41b1-437c-08d99523fcb5
X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Oct 2021 06:20:04.9570
 (UTC)
X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7
X-MS-Exchange-CrossTenant-MailboxType: HOSTED
X-MS-Exchange-CrossTenant-UserPrincipalName: nhi@amperemail.onmicrosoft.com
X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6325
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain

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.in=
f |   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/Amp=
ere/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
=20
+  ##  @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               =3D { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0=
x36, 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.i=
nf
   MailboxInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfa=
ceLib/MailboxInterfaceLib.inf
   SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemF=
irmwareInterfaceLib/SystemFirmwareInterfaceLib.inf
+  PciePhyLib|Silicon/Ampere/AmpereAltraBinPkg/Library/PciePhyLib/PciePhyLi=
b.inf
+  Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLi=
b.inf
   AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCp=
uLib.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/Jad=
e.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
=20
+  #
+  # Pcie Board
+  #
+  BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/Boar=
dPcieLibNull.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                    =3D 0x0001001B
+  BASE_NAME                      =3D Ac01PcieLib
+  FILE_GUID                      =3D 8ABFA0FC-313E-11E8-B467-0ED5F89F718B
+  MODULE_TYPE                    =3D BASE
+  VERSION_STRING                 =3D 1.0
+  LIBRARY_CLASS                  =3D 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/BoardPc=
ieLibNull.inf b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/Boar=
dPcieLibNull.inf
new file mode 100644
index 000000000000..435092b864ec
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNu=
ll.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                    =3D 0x0001001B
+  BASE_NAME                      =3D BoardPcieLibNull
+  FILE_GUID                      =3D 7820C925-F525-4101-8E64-87838356B7A6
+  MODULE_TYPE                    =3D BASE
+  VERSION_STRING                 =3D 1.0
+  LIBRARY_CLASS                  =3D 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 cont=
rollers
+
+  @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 succe=
ssfully.
+  @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 Co=
mplex.
+  @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 num=
ber.
+
+  @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) (sr=
c)) & 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) | (((UINT3=
2) (src) << 24) & 0xF000000))
+#define DSP_16G_RXTX_PRESET0_SET(dst,src) (((dst) & ~0xFF) | (((UINT32) (s=
rc)) & 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) | (((UINT=
32) (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) | (((UI=
NT32) (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) | (((UI=
NT32) (src) << 8) & 0xFF00))
+#define REVISION_ID_SET(dst, src)               (((dst) & ~0xFF) | (((UINT=
32) (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) | (((UI=
NT32) (src) << 8) & 0xFF00))
+#define PRIM_BUS_SET(dst, src)                  (((dst) & ~0xFF) | (((UINT=
32) (src)) & 0xFF))
+
+// BRIDGE_CTRL_INT_PIN_INT_LINE_REG
+#define INT_PIN_SET(dst, src)                   (((dst) & ~0xFF00) | (((UI=
NT32) (src) << 8) & 0xFF00))
+
+// CON_STATUS_REG
+#define POWER_STATE_SET(dst, src)               (((dst) & ~0x3) | (((UINT3=
2) (src)) & 0x3))
+
+// DEVICE_CONTROL2_DEVICE_STATUS2_REG
+#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src)     (((dst) & ~0xF) | (((UINT3=
2) (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) | (((UIN=
T32) (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) | (((UINT3=
2) (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) | (((U=
INT32) (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) | (((UIN=
T32) (src) << 8) & 0x100))
+#define CAP_RETRAIN_LINK_SET(dst, src)          (((dst) & ~0x20) | (((UINT=
32) (src) << 5) & 0x20))
+#define CAP_COMMON_CLK_SET(dst, src)            (((dst) & ~0x40) | (((UINT=
32) (src) << 6) & 0x40))
+#define CAP_LINK_TRAINING_GET(val)              ((val & 0x8000000) >> 27)
+#define CAP_LINK_DISABLE_SET(dst, src)          (((dst) & ~0x10) | (((UINT=
32)(src) << 4) & 0x10))
+
+// LINK_CONTROL2_LINK_STATUS2_REG
+#define CAP_TARGET_LINK_SPEED_SET(dst, src)     (((dst) & ~0xF) | (((UINT3=
2) (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) | (((UINT3=
2) (src)) & 0xF))
+#define DSP_TX_PRESET1_SET(dst,src)             (((dst) & ~0xF0000) | (((U=
INT32) (src) << 16) & 0xF0000))
+
+// UNCORR_ERR_MASK_OFF
+#define CMPLT_TIMEOUT_ERR_MASK_SET(dst, src)    (((dst) & ~0x4000) | (((UI=
NT32) (src) << 14) & 0x4000))
+#define SDES_ERR_MASK_SET(dst, src)             (((dst) & ~0x20) | (((UINT=
32)(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) | (((UINT=
32) (src) << 7) & 0x80))
+
+// FILTER_MASK_2_OFF
+#define CX_FLT_MASK_VENMSG0_DROP_SET(dst, src)  (((dst) & ~0x1) | (((UINT3=
2) (src)) & 0x1))
+#define CX_FLT_MASK_VENMSG1_DROP_SET(dst, src)  (((dst) & ~0x2) | (((UINT3=
2) (src) << 1) & 0x2))
+#define CX_FLT_MASK_DABORT_4UCPL_SET(dst, src)  (((dst) & ~0x4) | (((UINT3=
2) (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) (s=
rc) << 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) | ((UI=
NT32) (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) | (((U=
INT32) (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) | (((U=
INT32) (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) | (((U=
INT32)(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,
+  IN UINT16            ExtendedCapId
+  )
+{
+  PHYSICAL_ADDRESS       CfgAddr;
+  UINT32                 Val =3D 0, NextCap =3D 0, CapId =3D 0, ExCap =3D =
0;
+
+  if (IsRC) {
+    CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 15);
+  } else {
+    CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 20);
+  }
+
+  Val =3D MmioRead32 (CfgAddr + TYPE1_CAP_PTR_REG);
+  NextCap =3D Val & 0xFF;
+
+  // Loop untill desired capability is found else return 0
+  while (1) {
+    if ((NextCap & 0x3) !=3D 0) {
+      // Not alignment, just return
+      return 0;
+    }
+    Val =3D MmioRead32 (CfgAddr + NextCap);
+    if (NextCap < EXT_CAP_OFFSET_START) {
+      CapId =3D Val & 0xFF;
+    } else {
+      CapId =3D Val & 0xFFFF;
+    }
+
+    if (CapId =3D=3D ExtendedCapId) {
+      return (UINT64)(CfgAddr + NextCap);
+    }
+
+    if (NextCap < EXT_CAP_OFFSET_START) {
+      NextCap =3D (Val & 0xFFFF) >> 8;
+    } else {
+      NextCap =3D (Val & 0xFFFF0000) >> 20;
+    }
+
+    if ((NextCap =3D=3D 0) && (ExCap =3D=3D 0)) {
+      ExCap =3D 1;
+      NextCap =3D EXT_CAP_OFFSET_START;
+    }
+
+    if ((NextCap =3D=3D 0) && (ExCap =3D=3D 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 =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  // Select the FoM method, need double-write to convey settings
+  Val =3D MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF);
+  Val =3D GEN3_EQ_FB_MODE (Val, 0x1);
+  Val =3D GEN3_EQ_PRESET_VEC (Val, 0x3FF);
+  Val =3D GEN3_EQ_INIT_EVAL (Val, 0x1);
+  MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val);
+  MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val);
+  Val =3D MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF);
+}
+
+/**
+  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 =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  // Bring to legacy mode
+  Val =3D MmioRead32 (CfgAddr + GEN3_RELATED_OFF);
+  Val =3D RATE_SHADOW_SEL_SET (Val, 0);
+  MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
+  Val =3D EQ_PHASE_2_3_SET (Val, 0);
+  Val =3D RXEQ_REGRDLESS_SET (Val, 1);
+  MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
+
+  // Generate SPCIE capability address
+  SpcieBaseAddr =3D PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_=
ID);
+  if (SpcieBaseAddr =3D=3D 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "PCIE%d.%d: Cannot get SPCIE capability address\n",
+      RootComplex->ID,
+      PcieIndex
+      ));
+    return;
+  }
+
+  for (Idx=3D0; Idx < RootComplex->Pcie[PcieIndex].MaxWidth/2; Idx++) {
+    // Program Preset to Gen3 EQ Lane Control
+    Val =3D MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4);
+    Val =3D DSP_TX_PRESET0_SET (Val, 0x7);
+    Val =3D DSP_TX_PRESET1_SET (Val, 0x7);
+    MmioWrite32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4, 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       CfgAddr, SpcieBaseAddr, Pl16BaseAddr;
+  UINT32                 LinkWidth, Idx;
+  UINT32                 Val;
+  UINT8                  Preset;
+
+  CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  // Bring to legacy mode
+  Val =3D MmioRead32 (CfgAddr + GEN3_RELATED_OFF);
+  Val =3D RATE_SHADOW_SEL_SET (Val, 1);
+  MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
+  Val =3D EQ_PHASE_2_3_SET (Val, 0);
+  Val =3D RXEQ_REGRDLESS_SET (Val, 1);
+  MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val);
+
+  // Generate the PL16 capability address
+  Pl16BaseAddr =3D PcieCheckCap (RootComplex, PcieIndex, TRUE, PL16_CAP_ID=
);
+  if (Pl16BaseAddr =3D=3D 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "PCIE%d.%d: Cannot get PL16 capability address\n",
+      RootComplex->ID,
+      PcieIndex
+      ));
+    return;
+  }
+
+  // Generate the SPCIE capability address
+  SpcieBaseAddr =3D PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_=
ID);
+  if (SpcieBaseAddr =3D=3D 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] =3D=3D PRESET_INVALID) {
+    Preset =3D 0x57; // Default Gen4 preset
+  } else {
+    Preset =3D RootComplex->PresetGen4[PcieIndex];
+  }
+
+  LinkWidth =3D RootComplex->Pcie[PcieIndex].MaxWidth;
+  if (LinkWidth =3D=3D 0x2) {
+    Val =3D MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF);
+    Val =3D DSP_16G_RXTX_PRESET0_SET (Val, Preset);
+    Val =3D DSP_16G_RXTX_PRESET1_SET (Val, Preset);
+    MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF, Val);
+  } else {
+    for (Idx =3D 0; Idx < LinkWidth/4; Idx++) {
+      Val =3D MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4=
);
+      Val =3D DSP_16G_RXTX_PRESET0_SET (Val, Preset);
+      Val =3D DSP_16G_RXTX_PRESET1_SET (Val, Preset);
+      Val =3D DSP_16G_RXTX_PRESET2_SET (Val, Preset);
+      Val =3D DSP_16G_RXTX_PRESET3_SET (Val, Preset);
+      MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4, Val);
+    }
+  }
+
+  // Configure Gen3 preset
+  for (Idx =3D 0; Idx < LinkWidth/2; Idx++) {
+    Val =3D MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4);
+    Val =3D DSP_TX_PRESET0_SET (Val, 0x7);
+    Val =3D 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 =3D RootComplex->Pcie[PcieIndex].SnpsRamBase;
+  CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  Hob =3D GetFirstGuidHob (&gPlatformInfoHobGuid);
+  PlatformHob =3D (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+  if ((PlatformHob->ScuProductId[0] & 0xff) =3D=3D 0x01
+      && AsciiStrCmp ((CONST CHAR8 *)PlatformHob->CpuVer, "A0") =3D=3D 0
+      && (RootComplex->Type =3D=3D RootComplexTypeB || PcieIndex > 0)) {
+    // Change the Read Margin dual ported RAMs
+    Val =3D 0x10; // Margin to 0x0 (most conservative setting)
+    MmioWrite32 (SnpsRamBase + TPSRAM_RMR, Val);
+
+    // Generate the DLINK capability address
+    DlinkBaseAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieInde=
x].DevNum << 15);
+    NextExtendedCapabilityOff =3D 0x100; // This is the 1st extended capab=
ility offset
+    do {
+      Val =3D MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff);
+      if (Val =3D=3D 0xFFFFFFFF) {
+        DlinkBaseAddr =3D 0x0;
+        break;
+      }
+      if ((Val & 0xFFFF) =3D=3D DLINK_VENDOR_CAP_ID) {
+        VsecVal =3D MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff =
+ 0x4);
+        if (VsecVal =3D=3D DLINK_VSEC) {
+          DlinkBaseAddr =3D DlinkBaseAddr + NextExtendedCapabilityOff;
+          break;
+        }
+      }
+      NextExtendedCapabilityOff =3D (Val >> 20);
+    } while (NextExtendedCapabilityOff !=3D 0);
+
+    // Disable the scaled credit mode
+    if (DlinkBaseAddr !=3D 0x0) {
+      Val =3D 1;
+      MmioWrite32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF, Val);
+      Val =3D MmioRead32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF);
+      if (Val !=3D 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 featur=
e 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=3D0x40201020;
+    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 =3D=3D RootComplexTypeA) {
+      if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootCom=
plex->HostBridgeBase + HBRCAPDMR, &Val))) {
+        Val =3D RCAPCIDEVMAP_SET (Val, RootComplex->DevMapLow);
+        MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBri=
dgeBase + HBRCAPDMR, Val);
+      }
+    } else {
+      if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootCom=
plex->HostBridgeBase + HBRCBPDMR, &Val))) {
+        Val =3D RCBPCIDEVMAPLO_SET (Val, RootComplex->DevMapLow);
+        Val =3D RCBPCIDEVMAPHI_SET (Val, RootComplex->DevMapHigh);
+        MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBri=
dgeBase + HBRCBPDMR, Val);
+      }
+    }
+  }
+
+  // Program VendorID and DeviceId
+  if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex=
->HostBridgeBase  + HBPDVIDR, &Val))) {
+    Val =3D PCIVENDID_SET (Val, AMPERE_PCIE_VENDORID);
+    if (RootComplexTypeA =3D=3D RootComplex->Type) {
+      Val =3D PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCA);
+    } else {
+      Val =3D PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCB);
+    }
+    MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeB=
ase  + HBPDVIDR, Val);
+  }
+}
+
+VOID
+ProgramLinkCapabilities (
+  IN AC01_ROOT_COMPLEX *RootComplex,
+  IN UINT8             PcieIndex
+  )
+{
+  PHYSICAL_ADDRESS       CfgAddr;
+  UINT32                 Val;
+
+  CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  Val =3D MmioRead32 (CfgAddr + PORT_LINK_CTRL_OFF);
+  switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
+  case LINK_WIDTH_X2:
+    Val =3D LINK_CAPABLE_SET (Val, LINK_CAPABLE_X2);
+    break;
+
+  case LINK_WIDTH_X4:
+    Val =3D LINK_CAPABLE_SET (Val, LINK_CAPABLE_X4);
+    break;
+
+  case LINK_WIDTH_X8:
+    Val =3D LINK_CAPABLE_SET (Val, LINK_CAPABLE_X8);
+    break;
+
+  case LINK_WIDTH_X16:
+  default:
+    Val =3D LINK_CAPABLE_SET (Val, LINK_CAPABLE_X16);
+    break;
+  }
+  MmioWrite32 (CfgAddr + PORT_LINK_CTRL_OFF, Val);
+  Val =3D MmioRead32 (CfgAddr + GEN2_CTRL_OFF);
+  switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
+  case LINK_WIDTH_X2:
+    Val =3D NUM_OF_LANES_SET (Val, NUM_OF_LANES_X2);
+    break;
+
+  case LINK_WIDTH_X4:
+    Val =3D NUM_OF_LANES_SET (Val, NUM_OF_LANES_X4);
+    break;
+
+  case LINK_WIDTH_X8:
+    Val =3D NUM_OF_LANES_SET (Val, NUM_OF_LANES_X8);
+    break;
+
+  case LINK_WIDTH_X16:
+  default:
+    Val =3D NUM_OF_LANES_SET (Val, NUM_OF_LANES_X16);
+    break;
+  }
+  MmioWrite32 (CfgAddr + GEN2_CTRL_OFF, Val);
+  Val =3D MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG);
+  switch (RootComplex->Pcie[PcieIndex].MaxWidth) {
+  case LINK_WIDTH_X2:
+    Val =3D CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X2);
+    break;
+
+  case LINK_WIDTH_X4:
+    Val =3D CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X4);
+    break;
+
+  case LINK_WIDTH_X8:
+    Val =3D CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X8);
+    break;
+
+  case LINK_WIDTH_X16:
+  default:
+    Val =3D CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X16);
+    break;
+  }
+
+  switch (RootComplex->Pcie[PcieIndex].MaxGen) {
+  case LINK_SPEED_GEN1:
+    Val =3D CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
+    break;
+
+  case LINK_SPEED_GEN2:
+    Val =3D CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
+    break;
+
+  case LINK_SPEED_GEN3:
+    Val =3D CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
+    break;
+
+  default:
+    Val =3D CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
+    break;
+  }
+  /* Enable ASPM Capability */
+  Val =3D CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET (Val, L0S_L1_SUPPORTED);
+  MmioWrite32 (CfgAddr + LINK_CAPABILITIES_REG, Val);
+
+  Val =3D MmioRead32 (CfgAddr + LINK_CONTROL2_LINK_STATUS2_REG);
+  switch (RootComplex->Pcie[PcieIndex].MaxGen) {
+  case LINK_SPEED_GEN1:
+    Val =3D CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
+    break;
+
+  case LINK_SPEED_GEN2:
+    Val =3D CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
+    break;
+
+  case LINK_SPEED_GEN3:
+    Val =3D CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
+    break;
+
+  default:
+    Val =3D 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 =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  Val =3D MmioRead32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF);
+  Val =3D LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, TimeOut);
+  MmioWrite32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF, Val);
+  Val =3D MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
+  Val =3D 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
+  TimeOut =3D MEMRDY_TIMEOUT;
+  do {
+    Val =3D MmioRead32 (CsrBase + MEMRDYR);
+    if (Val & 1) {
+      break;
+    }
+
+    TimeOut--;
+    MicroSecondDelay (1);
+  } while (TimeOut > 0);
+
+  if (TimeOut <=3D 0) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+BOOLEAN
+PollPipeReady (
+  PHYSICAL_ADDRESS       CsrBase
+  )
+{
+  UINT32                 TimeOut;
+  UINT32                 Val;
+
+  // Poll till PIPE clock is stable
+  TimeOut =3D PIPE_CLOCK_TIMEOUT;
+  do {
+    Val =3D MmioRead32 (CsrBase + LINKSTAT);
+    if (!(Val & PHY_STATUS_MASK)) {
+      break;
+    }
+
+    TimeOut--;
+    MicroSecondDelay (1);
+  } while (TimeOut > 0);
+
+  if (TimeOut <=3D 0) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Setup and initialize the AC01 PCIe Root Complex and underneath PCIe cont=
rollers
+
+  @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 succe=
ssfully.
+  @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 =3D PciePhyInit (RootComplex->SerdesBase);
+    if (RETURN_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a: Failed to initialize the PCIe PHY\n", __FU=
NCTION__));
+      return RETURN_DEVICE_ERROR;
+    }
+  }
+
+  // Setup each controller
+  for (PcieIndex =3D 0; PcieIndex < RootComplex->MaxPcieController; PcieIn=
dex++) {
+
+    if (ReInit) {
+      PcieIndex =3D ReInitPcieIndex;
+    }
+
+    if (!RootComplex->Pcie[PcieIndex].Active) {
+      continue;
+    }
+
+    DEBUG ((DEBUG_INFO, "Initializing Controller %d\n", PcieIndex));
+
+    CsrBase =3D RootComplex->Pcie[PcieIndex].CsrBase;
+    CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 15);
+
+    // Put Controller into reset if not in reset already
+    Val =3D MmioRead32 (CsrBase +  RESET);
+    if (!(Val & RESET_MASK)) {
+      Val =3D DWCPCIE_SET (Val, 1);
+      MmioWrite32 (CsrBase + RESET, Val);
+
+      // Delay 50ms to ensure controller finish its reset
+      MicroSecondDelay (50000);
+    }
+
+    // Clear memory shutdown
+    Val =3D MmioRead32 (CsrBase + RAMSDR);
+    Val =3D 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 =3D MmioRead32 (CsrBase + LINKCTRL);
+    Val =3D LTSSMENB_SET (Val, 0);
+    MmioWrite32 (CsrBase + LINKCTRL, Val);
+
+    // Enable subsystem clock and release reset
+    Val =3D MmioRead32 (CsrBase + CLOCK);
+    Val =3D AXIPIPE_SET (Val, 1);
+    MmioWrite32 (CsrBase + CLOCK, Val);
+    Val =3D MmioRead32 (CsrBase +  RESET);
+    Val =3D 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", Pcie=
Index));
+      return RETURN_DEVICE_ERROR;
+    }
+
+    // Start PERST pulse
+    BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
+
+    // Allow programming to config space
+    Val =3D MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
+    Val =3D 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 =3D MmioRead32 (CfgAddr + SLOT_CAPABILITIES_REG);
+    Val =3D SLOT_HPC_SET (Val, 1);
+    // Program the power limit
+    Val =3D 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 RootComple=
xTypeA 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 =3D MmioRead32 (CfgAddr + DTIM_CTRL0_OFF);
+    Val =3D 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 =3D MmioRead32 (CfgAddr + FILTER_MASK_2_OFF);
+    Val =3D CX_FLT_MASK_VENMSG0_DROP_SET (Val, 0);
+    Val =3D CX_FLT_MASK_VENMSG1_DROP_SET (Val, 0);
+    Val =3D CX_FLT_MASK_DABORT_4UCPL_SET (Val, 0);
+    MmioWrite32 (CfgAddr + FILTER_MASK_2_OFF, Val);
+    Val =3D MmioRead32 (CfgAddr + AMBA_ORDERING_CTRL_OFF);
+    Val =3D 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 =3D MmioRead32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF);
+    Val =3D AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2);
+    MmioWrite32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF, Val);
+
+    // Set Legacy PCIE interrupt map to INTA
+    Val =3D MmioRead32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG);
+    Val =3D INT_PIN_SET (Val, 1);
+    MmioWrite32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG, Val);
+    Val =3D MmioRead32 (CsrBase + IRQSEL);
+    Val =3D INTPIN_SET (Val, 1);
+    MmioWrite32 (CsrBase + IRQSEL, Val);
+
+    if (RootComplex->Pcie[PcieIndex].MaxGen !=3D LINK_SPEED_GEN1) {
+      ConfigureEqualization (RootComplex, PcieIndex);
+      if (RootComplex->Pcie[PcieIndex].MaxGen =3D=3D LINK_SPEED_GEN3) {
+        ConfigurePresetGen3 (RootComplex, PcieIndex);
+      } else if (RootComplex->Pcie[PcieIndex].MaxGen =3D=3D LINK_SPEED_GEN=
4) {
+        ConfigurePresetGen4 (RootComplex, PcieIndex);
+      }
+    }
+
+    // Mask Completion Timeout
+    MaskCompletionTimeOut (RootComplex, PcieIndex, 1, TRUE);
+
+    // AER surprise link down error should be masked due to hotplug is ena=
bled
+    // This event must be handled by Hotplug handler, instead of error han=
dler
+    Val =3D MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
+    Val =3D SDES_ERR_MASK_SET (Val, 1);
+    MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val);
+
+    // Program Class Code
+    Val =3D MmioRead32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG);
+    Val =3D REVISION_ID_SET (Val, 4);
+    Val =3D SUBCLASS_CODE_SET (Val, 4);
+    Val =3D BASE_CLASS_CODE_SET (Val, 6);
+    MmioWrite32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG, Val);
+
+    // Program VendorID and DeviceID
+    Val =3D MmioRead32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG);
+    Val =3D VENDOR_ID_SET (Val, AMPERE_PCIE_VENDORID);
+    if (RootComplexTypeA =3D=3D RootComplex->Type) {
+      Val =3D DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCA + PcieInde=
x);
+    } else {
+      Val =3D DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCB + PcieInde=
x);
+    }
+    MmioWrite32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG, Val);
+
+    // Enable common clock for downstream
+    Val =3D MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG);
+    Val =3D CAP_SLOT_CLK_CONFIG_SET (Val, 1);
+    Val =3D CAP_COMMON_CLK_SET (Val, 1);
+    MmioWrite32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG, Val);
+
+    // Match aux_clk to system
+    Val =3D MmioRead32 (CfgAddr + AUX_CLK_FREQ_OFF);
+    Val =3D 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 =3D MmioRead32 (CsrBase + LINKCTRL);
+    Val =3D LTSSMENB_SET (Val, 1);
+    MmioWrite32 (CsrBase + LINKCTRL, Val);
+
+    // Complete the PERST pulse
+    BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
+
+    // Lock programming of config space
+    Val =3D MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
+    Val =3D 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 =3D Pcie->CsrBase;
+
+  // Check if card present
+  // smlh_ltssm_state[13:8] =3D 0
+  // phy_status[2] =3D 0
+  // smlh_link_up[1] =3D 0
+  // rdlh_link_up[0] =3D 0
+  LinkStat =3D MmioRead32 (CsrBase + LINKSTAT);
+  LinkStat =3D LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT |
+                         SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT);
+  if (LinkStat =3D=3D 0x0000) {
+    return FALSE;
+  }
+
+  BlockEvent =3D MmioRead32 (CsrBase +  BLOCKEVENTSTAT);
+  LinkStat =3D MmioRead32 (CsrBase +  LINKSTAT);
+
+  if (((BlockEvent & LINKUP_MASK) !=3D 0)
+      && (SMLH_LTSSM_STATE_GET(LinkStat) =3D=3D 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 =3D=3D NULL || !RootComplex->Active) {
+    return;
+  }
+
+  // Clear uncorrectable error during enumuration phase. Mainly completion=
 timeout.
+  for (Index =3D 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 o=
ut
+      CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[Index].DevNu=
m << 15);
+      Val =3D MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF);
+      Val =3D CMPLT_TIMEOUT_ERR_MASK_SET (Val, 1);
+      MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val);
+    }
+    // Clear all errors
+    Reg =3D RootComplex->MmcfgBase + ((Index + 1) << 15) + UNCORR_ERR_STAT=
US_OFF;
+    Val =3D MmioRead32 (Reg);
+    if (Val !=3D 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 capabili=
ties
+                        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 =3D RootComplex->Pcie[PcieIndex].CsrBase;
+  CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  Val =3D MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG);
+  if ((CAP_MAX_LINK_WIDTH_GET (Val) =3D=3D 0) ||
+      (CAP_MAX_LINK_SPEED_GET (Val) =3D=3D 0)) {
+    DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong RootComplex capabilities\n", R=
ootComplex->ID, PcieIndex));
+    return LINK_CHECK_WRONG_PARAMETER;
+  }
+
+  if ((EpMaxWidth =3D=3D 0) || (EpMaxGen =3D=3D 0)) {
+    DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong EP capabilities\n", RootComple=
x->ID, PcieIndex));
+    return LINK_CHECK_FAILED;
+  }
+
+  // Compare RootComplex and EP capabilities
+  if (CAP_MAX_LINK_WIDTH_GET (Val) > EpMaxWidth) {
+    MaxWidth =3D EpMaxWidth;
+  } else {
+    MaxWidth =3D CAP_MAX_LINK_WIDTH_GET (Val);
+  }
+
+  // Compare RootComplex and EP capabilities
+  if (CAP_MAX_LINK_SPEED_GET (Val) > EpMaxGen) {
+    MaxGen =3D EpMaxGen;
+  } else {
+    MaxGen =3D CAP_MAX_LINK_SPEED_GET (Val);
+  }
+
+  LinkStat =3D MmioRead32 (CsrBase + LINKSTAT);
+  Val =3D 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) !=3D MaxWidth) ||
+      (CAP_LINK_SPEED_GET (Val) !=3D MaxGen) ||
+      (RDLH_SMLH_LINKUP_STATUS_GET (LinkStat) !=3D (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 =3D LINK_CHECK_SUCCESS;
+  UINT32                 Val;
+  UINT8                  ErrCode, ErrGrpNum;
+
+  UINT32 ErrCtrlCfg[MAX_NUM_ERROR_CODE] =3D {
+    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 =3D 0; ErrCode < MAX_NUM_ERROR_CODE; ErrCode++) {
+    ErrGrpNum =3D (ErrCtrlCfg[ErrCode] & 0xF00) >> 8;
+    // Skipping per lane group
+    // Checking common lane group because AER error are included in common=
 group only
+    if ((ErrGrpNum !=3D 0) && (ErrGrpNum !=3D 4)) {
+      Val =3D MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
+      if (RootComplex->Type =3D=3D RootComplexTypeA) {
+        // RootComplexTypeA - 4 PCIe controller per port, 1 controller in =
charge of 4 lanes
+        Val =3D ECCR_LANE_SEL_SET (Val, PcieIndex*4);
+      } else {
+        // RootComplexTypeB - 8 PCIe controller per port, 1 controller in =
charge of 2 lanes
+        Val =3D ECCR_LANE_SEL_SET (Val, PcieIndex*2);
+      }
+      Val =3D 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 =3D MmioRead32 (RasDesVSecBase + EVENT_COUNTER_DATA_REG_OFF);
+      if (Val !=3D 0) {
+        Ret =3D 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 =3D LINK_CHECK_SUCCESS;
+  UINT32                 Val;
+
+  CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu=
m << 15);
+
+  // Allow programming to config space
+  Val =3D MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
+  Val =3D DBI_RO_WR_EN_SET (Val, 1);
+  MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val);
+
+  // Generate the RAS DES capability address
+  // RAS_DES_CAP_ID =3D 0xB
+  RasDesVSecBase =3D PcieCheckCap (RootComplex, PcieIndex, TRUE, RAS_DES_C=
AP_ID);
+  if (RasDesVSecBase =3D=3D 0) {
+    DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\=
n", RootComplex->ID, PcieIndex));
+    return LINK_CHECK_WRONG_PARAMETER;
+  }
+
+  if (PFAMode =3D=3D PFA_REG_ENABLE) {
+    // PFA Counters Enable
+    Val =3D MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
+    Val =3D ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0x7);
+    Val =3D ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0);
+    MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val);
+  } else if (PFAMode =3D=3D PFA_REG_CLEAR) {
+    // PFA Counters Clear
+    Val =3D MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF);
+    Val =3D ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0);
+    Val =3D ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0x3);
+    MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val);
+  } else {
+    // PFA Counters Read
+    Ret =3D PFACounterRead (RootComplex, PcieIndex, RasDesVSecBase);
+  }
+
+  // Disable programming to config space
+  Val =3D MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF);
+  Val =3D 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 =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 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 =3D EP_LINKUP_TIMEOUT;
+  do {
+    Val =3D MmioRead32 (EpCfgAddr);
+    if (Val !=3D 0xFFFF0001 && Val !=3D 0xFFFFFFFF) {
+      break;
+    }
+    MicroSecondDelay (LINK_WAIT_INTERVAL_US);
+    TimeOut -=3D 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 =3D CheckEndpointCfg (RootComplex, PcieIndex);
+  if (Val =3D=3D 0xFFFFFFFF) {
+    *EpMaxWidth =3D 0;   // Invalid Width
+    *EpMaxGen =3D 0;     // Invalid Speed
+    DEBUG ((DEBUG_ERROR, "PCIE%d.%d Cannot access EP config space!\n", Roo=
tComplex->ID, PcieIndex));
+  } else {
+    PcieCapBaseAddr =3D PcieCheckCap (RootComplex, PcieIndex, FALSE, CAP_I=
D);
+    if (PcieCapBaseAddr =3D=3D 0) {
+      *EpMaxWidth =3D 0;   // Invalid Width
+      *EpMaxGen =3D 0;     // Invalid Speed
+      DEBUG ((
+        DEBUG_ERROR,
+        "PCIE%d.%d Cannot get PCIe capability extended address!\n",
+        RootComplex->ID,
+        PcieIndex
+        ));
+    } else {
+      Val =3D MmioRead32 (PcieCapBaseAddr + LINK_CAPABILITIES_REG_OFF);
+      *EpMaxWidth =3D (Val >> 4) & 0x3F;
+      *EpMaxGen =3D 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 =3D MmioRead32 (PcieCapBaseAddr + LINK_CONTROL_LINK_STATUS_OFF);
+      Val =3D CAP_SLOT_CLK_CONFIG_SET (Val, 1);
+      Val =3D 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 =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 15);
+
+  // Allow programming to config space
+  Val =3D MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF);
+  Val =3D DBI_RO_WR_EN_SET (Val, 1);
+  MmioWrite32 (RcCfgAddr + MISC_CONTROL_1_OFF, Val);
+
+  Val =3D MmioRead32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_RE=
G);
+  RestoreVal =3D Val;
+  Val =3D SUB_BUS_SET (Val, DEFAULT_SUB_BUS);             /* Set DEFAULT_S=
UB_BUS to Subordinate bus */
+  Val =3D SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum);  /* Set =
RootComplex->Pcie[PcieIndex].DevNum to Secondary bus */
+  Val =3D PRIM_BUS_SET (Val, 0x0);                        /* Set 0x0 to Pr=
imary 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, Rest=
oreVal);
+
+  // Disable programming to config space
+  Val =3D MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF);
+  Val =3D 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 sur=
e
+  // the state transition is completed
+  TimeOut =3D 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 =3D TRUE;
+      break;
+    }
+
+    MicroSecondDelay (100);
+    TimeOut -=3D 100;
+  } while (TimeOut > 0);
+
+  if (TimeOut <=3D 0) {
+    DEBUG ((DEBUG_ERROR, "\tPCIE%d.%d LinkStat TIMEOUT after re-init\n", R=
ootComplex->ID, PcieIndex));
+  } else {
+    DEBUG ((DEBUG_INFO, "PCIE%d.%d Link re-initialization passed!\n", Root=
Complex->ID, PcieIndex));
+  }
+}
+
+/**
+  Check active PCIe controllers of RootComplex, retrain or soft reset if n=
eeded
+
+  @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 =3D 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[PcieIn=
dex].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, &E=
pMaxGen);
+      LinkStatusCheck =3D Ac01PcieCoreLinkCheck (RootComplex, PcieIndex, E=
pMaxWidth, EpMaxGen);
+
+      // Delay to allow the link to perform internal operation and generat=
e
+      // any error status update. This allows detection of any error obser=
ved
+      // during initial link training. Possible evaluation time can be
+      // between 100ms to 200ms.
+      MicroSecondDelay (100000);
+
+      // Check for error
+      RasdesChecking =3D 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 !=3D LINK_CHECK_FAILED &&
+          RasdesChecking !=3D LINK_CHECK_FAILED &&
+          PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex]))
+      {
+        return LINK_CHECK_SUCCESS;
+      }
+
+      RootComplex->Pcie[PcieIndex].LinkUp =3D FALSE;
+    }
+
+    // Trigger controller soft reset
+    DEBUG ((DEBUG_INFO, "PCIE%d.%d Start link re-initialization..\n", Root=
Complex->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 =3D FALSE;
+  *FailedPcieCount   =3D 0;
+  for (Index =3D 0; Index < MaxPcieControllerB; Index++) {
+    FailedPciePtr[Index] =3D -1;
+  }
+
+  if (!RootComplex->Active) {
+    return;
+  }
+
+  // Loop for all controllers
+  for (PcieIndex =3D 0; PcieIndex < RootComplex->MaxPcieController; PcieIn=
dex++) {
+    Pcie =3D &RootComplex->Pcie[PcieIndex];
+    CfgAddr =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev=
Num << 15);
+
+    if (Pcie->Active && !Pcie->LinkUp) {
+      if (PcieLinkUpCheck (Pcie)) {
+        Pcie->LinkUp =3D TRUE;
+        Val =3D 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 =3D FALSE;
+        FailedPciePtr[*FailedPcieCount] =3D PcieIndex;
+        *FailedPcieCount +=3D 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 =3D FALSE, NextRoundNeeded;
+  UINT64  PrevTick, CurrTick, ElapsedCycle;
+  UINT64  TimerTicks64;
+  UINT8   ReInit;
+  INT8    FailedPciePtr[MaxPcieControllerB];
+  INT8    FailedPcieCount;
+
+  ReInit =3D 0;
+
+_link_polling:
+  NextRoundNeeded =3D 0;
+  //
+  // It is not guaranteed the timer service is ready prior to PCI Dxe.
+  // Calculate system ticks for link training.
+  //
+  TimerTicks64 =3D ArmGenericTimerGetTimerFreq (); /* 1 Second */
+  PrevTick =3D ArmGenericTimerGetSystemCount ();
+  ElapsedCycle =3D 0;
+
+  do {
+    CurrTick =3D ArmGenericTimerGetSystemCount ();
+    if (CurrTick < PrevTick) {
+      ElapsedCycle +=3D (UINT64)(~0x0ULL) - PrevTick;
+      PrevTick =3D 0;
+    }
+    ElapsedCycle +=3D (CurrTick - PrevTick);
+    PrevTick =3D CurrTick;
+  } while (ElapsedCycle < TimerTicks64);
+
+  for (RCIndex =3D 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
+    Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded,=
 FailedPciePtr, &FailedPcieCount);
+    if (IsNextRoundNeeded) {
+      NextRoundNeeded =3D 1;
+    }
+  }
+
+  if (NextRoundNeeded && ReInit < MAX_REINIT) {
+    //
+    // Timer is up. Give another chance to re-program controller
+    //
+    ReInit++;
+    for (RCIndex =3D 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
+      Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeede=
d, FailedPciePtr, &FailedPcieCount);
+      if (IsNextRoundNeeded) {
+        for (Idx =3D 0; Idx < FailedPcieCount; Idx++) {
+          if (FailedPciePtr[Idx] =3D=3D -1) {
+            continue;
+          }
+
+          //
+          // Some controller still observes link-down. Re-init controller
+          //
+          Ac01PcieCoreSetupRC (&RootComplexList[RCIndex], TRUE, FailedPcie=
Ptr[Idx]);
+        }
+      }
+    }
+
+    goto _link_polling;
+  }
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPc=
ieLibNull.c b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardP=
cieLibNull.c
new file mode 100644
index 000000000000..0916adb77539
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNu=
ll.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 Co=
mplex.
+  @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 num=
ber.
+
+  @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;
+}
--=20
2.17.1