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 ; 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" To: devel@edk2.groups.io CC: patches@amperecomputing.com, nhi@os.amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Leif Lindholm , Michael D Kinney , Ard Biesheuvel , Nate DeSimone 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: 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 Provides essential functions to initialize the PCIe Root Complex on Ampere Altra processor. 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.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. +# +# 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.
+# +# 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. + + 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. + + 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 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. + + 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. + + 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 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.
+ + 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 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