From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (NAM12-MW2-obe.outbound.protection.outlook.com [40.107.244.132]) by mx.groups.io with SMTP id smtpd.web08.1624.1637242939727601364 for ; Thu, 18 Nov 2021 05:42:20 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=BWyEi8ln; spf=pass (domain: os.amperecomputing.com, ip: 40.107.244.132, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LN2Ifua98pEqw1volGbXrWqUypSg3oH9tv9Gq0HOUK6ORp1JP5b0LfJw+qqMEaaTeW0LJ1AqCZ+gx374wfVprCM4AwDfZs9cyeXkiIm+5NLJIkhO1lGOMrW0QFzoPPS/WVnSm6B8mbV2RGnfLEzzc3T1VyLCEyGKrND0zt2yx+qcgS2470HFm7cDpxCn8Lj4gap/5ZQD7D6QK0QdaPogFivYQ7JL+QGMGYADeMF+hRNSd+/iOx25mqSwaY+e4Tp6bIh7kmjNTgLjBEaQve90OS3INSyAx93o4ooRl27IBJaj6kSFAqQUBp9ueHQM/OfxH84Wuq6AqZ5j/IB3v7Awfg== 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=b3rJJwRINCSKfpOi8gs1o5LrMxyrv9W0f1P48TFD6v4=; b=oVz7q5xp0ztABEju88Bl6AxI/tfmSKqEZxCjr/Z422sZhjear7Kgey/FnwNVh4sWjkhbEri218bQ9rpEDHvU1/3uYlXnXPFufKif5RYClce3xjz1Kh+p/69UGmnTOXgC1etAeW0B/8s2awT+YFDG7ts6CGXcX9r7I6QslvOz+H3q3Zs1fKw4jo5ZXfSLCZS27AwQN7kApB/uOnF9Cg3PoaDwRihbsE+s1zvkPw1RfeZhbFfSjsO1Xvrbw4LeQN5EgtN8JV0pyegywTsfbAYTXYeKVZFXCVOg0tS2LtrhMGDWVJIghvLcLTQnDn4W2nBkE/rNWaigI/1bcMMmlndkBQ== 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=b3rJJwRINCSKfpOi8gs1o5LrMxyrv9W0f1P48TFD6v4=; b=BWyEi8lndU9f+l04c/cQgKOoUg5OSNV7lKbyuvDKpiHHo6PWzPsFizIDakNA191CNf39O+cOxHiLIPrI53UXlVLPdAQBssIWn5GVf36T8u8TnyjitpYPMgCCf0fbk8dFgp1txIZmmBsZ43VyIv29DlQalcoKDVnxLBE6hoJnDxA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=os.amperecomputing.com; Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by PH0PR01MB6248.prod.exchangelabs.com (2603:10b6:510:c::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.19; Thu, 18 Nov 2021 13:42:15 +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.4713.019; Thu, 18 Nov 2021 13:42:15 +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 v6 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance Date: Thu, 18 Nov 2021 20:41:15 +0700 Message-ID: <20211118134115.29199-1-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 X-ClientProxiedBy: HK2PR02CA0182.apcprd02.prod.outlook.com (2603:1096:201:21::18) 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 HK2PR02CA0182.apcprd02.prod.outlook.com (2603:1096:201:21::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.19 via Frontend Transport; Thu, 18 Nov 2021 13:42:12 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: cca9b2d6-f5a5-4c7e-95fc-08d9aa993b44 X-MS-TrafficTypeDiagnostic: PH0PR01MB6248: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:626; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: JY7KhBHWgowmveip5J4oj5wgE190QQ2JXxEwUY9QEz9cR4MNGEmZpJhStx7lK7+0105SnOmhPn0l2NkVy/t7SPb/zeTEUFRRi19mAT7JJqzcBC3YmEHnz1qwU/sN0x9FJ1COMcOg+j1TteXBXuBp0m9LVHui40FhL4IMHozNUFBmWSm4vkAKM9eCpfqxDldJU7OUvLpCTQ1f2FUAS1Cl9tSJhRnmX9QpE7saADd/otaZX/j4Q3a+672OrzwKCTNIX7+I34M4Mg7n95Opa2QrX+Ob2ngcIGDIMQiU5Xr0btxcgKFutD2sjO5PitfleCxACWtJForHxffAhHUqLFMxZdssPqt7p9yDdGK4jzQRl7oZSu6CYIxgXwn0WipuVYwOeIqZc6BDy7TndvAEDs4hZ4+fVY9y9yFAclLfmz5B51soH8x9E7dd4NiLRQ1YynBp4jvmOOwFYxBsPfsf9sZ4yHOH1pP7CW0UCpusS4iD45vTnl0Dduf2iWm7Bhn8AS03ZpdHm86TifW57mJhqGyLfzspg48KanF8bcQf2Fz2MmVKiUDV5jjvRxnDd7aL3dIouY10cUpJM4Hn0H7DNeGvn2qmJj3OHUpAHPGg2aFTOy1LvEQJUioVf550EDoApynymr0knnMl+M2PPm6thzb8VcZPCZoeECZjWSizve5vopE12i6iTCjV702wks9g5r9aEZzulLBTimXY4UnOkRl0Haq30oKIeh0gY/yMnf2+RrXUbmJ/JXLwOUeQq6ArdsmoRvESv0JA6LNrrjgiB23BE8VdCxsI1jkdH3CemeiYybE= 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)(2616005)(956004)(508600001)(1076003)(30864003)(54906003)(6916009)(8936002)(6486002)(316002)(6512007)(38350700002)(38100700002)(4326008)(5660300002)(2906002)(26005)(83380400001)(966005)(86362001)(66946007)(8676002)(66476007)(66556008)(186003)(19627235002)(52116002)(6506007)(579004)(559001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?KWm/alM/9lIc+itP1sDPDpO2/k5QaSOzN8haDR0p+CtN2Ucwy0TAT+gY+vJH?= =?us-ascii?Q?j3nj4/iNU985q7M2JnwdpF1KBC+DwBenCe2NgEglbZEIEpFmmeED3I9rW2By?= =?us-ascii?Q?k+osO0V+x1Cdviko+WC37YLiyVIwgQKhUmVXC2uAjma7kdMsvqgr8EJ4XFqk?= =?us-ascii?Q?d+JHHT8zwkHwdzOQGh0dTDpdC5jf/bQm4WRTzaKhCKMEX2T3zCJckRysFlDG?= =?us-ascii?Q?Vq2QY/QWXR0iQwxIdklJMudsz3tgVQY2Vu/e/GsNHtAVa96c5mfCPyNiY1rr?= =?us-ascii?Q?QetTXWDcazDY6Gj73fUD2mDWBGYsAtald4+pQJH61M3k/npoN1tN/cNIqMu4?= =?us-ascii?Q?WWq5MYck39evk+pBVJOGTYCmL0ghWPCyEdsi9rNjMP4WCqQCK6UwEdJJO0SS?= =?us-ascii?Q?2g5vztof6djQacoj33zukQO+E2M+tmOrNFZEkoonGTmzgUcy5kgvMB72bGEC?= =?us-ascii?Q?IoWkCr9WTnaanWUSr1S/qFmsBOC2/BHLh38UAWwubQFUCrtJcb4/7nA96vIn?= =?us-ascii?Q?L55K2RF8SSxEf4yHuLRlJpuALnDy+IFCkpfR+Ldzsb1N3VZqd2385wfeOIM8?= =?us-ascii?Q?SrAMOkWkAKfzCtQjlZ1aw3VsrSr2ntkF7dA2GEf/4qqEnxGMWqGRCvl2Of/J?= =?us-ascii?Q?79MV0pWWmMRuH4U33FPx8aaNup4RQDMf1QJNgHv7Q8NfJSs/PXfrwD/7HT4P?= =?us-ascii?Q?iUUU7Ww+tpaLYlzASWhC11jgiUttm/rqXFgsg07aW/xh44HJTMrFIm0LdgL6?= =?us-ascii?Q?HSYMnaxihD/SHg4l/mMT6T5F+Vo2i1N4lB83laQYh2nYrskD85ig4yCFGRRl?= =?us-ascii?Q?VfwJLoGF08Y01p4YpeRzvDjj6T0YXTEijJk9Vto71/NRpYpIMdDoJOz1TEp1?= =?us-ascii?Q?BDH1sPcmWPVNPfmpJDRIVmU/1wcvsvZ3l//cTQH+KwiRaT3r+QuYqYQSZglx?= =?us-ascii?Q?S7LijdNYiixyiekVnf5fgX5Y8XFiBco7irmpknmkGS+YyhPWxcEt8kLeypLf?= =?us-ascii?Q?n5iOM3pe7U4p/WWU5AUJ92Q6wA+EquGSZhV+olRlTcUgnV1BwsbstzK29h6D?= =?us-ascii?Q?/rFZBEAXv/rpsaUZmDpG/pujDO589PeNViyJAtz3fiy1vj0ZyPtuGEXxo0pn?= =?us-ascii?Q?em6cE1O3fIQHBjuuteJBrG2vXWF+Srawmlvm4T/GJAvf9J0u+HYX93tIeHzo?= =?us-ascii?Q?QJVeGEL2zGl4VO7y1g5OAM7/kZqVf7dn/8isVDRuIn8Dd8rlaRJSbUIx5FWH?= =?us-ascii?Q?EaMja8he/btejmKqzLuxJ3FIrv7rMBBe+XMx1QB3YNGFkUXC+BRVPIVorJuy?= =?us-ascii?Q?eVvK8xT2MeH2cTvqrAJttDnaZxd0zlY87tp466h9OPdxk3R+/vwvKMwHLuRO?= =?us-ascii?Q?Yulbi+6JwTcR1rnneOcrxwsEJPmU6T65RIbHffev6pNN7pA8sz1jJgRbKEV/?= =?us-ascii?Q?kOCF+9fA5KjOqrWUn/J4b8NG8jRG+bzuDZYwe2bdRw/bCjkFrBIDGJVufH7E?= =?us-ascii?Q?Eoy8G70v8hk1zfZGU7ZwgyeUqbMj7XfVHlI2p3yzySzlSSBOzY/ohWaI4xaz?= =?us-ascii?Q?UoSk+CD5cRd5471oAphV88N4N1DjzMnDA+JARDWuNW5zQAYrdGl73pJkGn+W?= =?us-ascii?Q?2aM4dlGetb2sHPShtYnzqJWrDavGG42Y4ouce/xiY00nD/2HmqW5YVQlshVu?= =?us-ascii?Q?wD/EuPAYRiTKYLjAghVVCSKQ0yk=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: cca9b2d6-f5a5-4c7e-95fc-08d9aa993b44 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2021 13:42:15.7474 (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: 4n1JazOwglCWfqzgNp0OOUOVK6CUpU2jQvAKrZVw/PM8jrS7C78cEPGby7EmNj9AtLWjUdb9KeRivLJ7TMkVp6tAIeKMTCyu8rZc86OZCFs= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6248 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 --- Changes since v5: * Fixed an error with the NOOPT build. https://edk2.groups.io/g/devel/message/83855 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 = | 372 +++++ Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c = | 1416 ++++++++++++++++++++ Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c = | 47 + 10 files changed, 2009 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 fa9b120b2c2b..5b767ecb024f 100644 --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc @@ -81,6 +81,8 @@ [LibraryClasses.common] NVParamLib|Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.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..692bc2669915 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h @@ -0,0 +1,49 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef AC01_PCIE_LIB_H_ +#define AC01_PCIE_LIB_H_ + +/** + Setup and initialize the AC01 PCIe Root Complex and underneath PCIe cont= rollers + + @param RootComplex Pointer to Root Complex structure + @param ReInit Re-init status + @param ReInitPcieIndex PCIe controller index + + @retval RETURN_SUCCESS The Root Complex has been initialized 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..1db8a68b3df4 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h @@ -0,0 +1,372 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef AC01_PCIE_CORE_H_ +#define AC01_PCIE_CORE_H_ + +#define BUS_SHIFT 20 +#define DEV_SHIFT 15 + +#define GET_LOW_8_BITS(x) ((x) & 0xFF) +#define GET_HIGH_8_BITS(x) (((x) >> 8) & 0xFF) +#define GET_LOW_16_BITS(x) ((x) & 0xFFFF) +#define GET_HIGH_16_BITS(x) (((x) >> 16) & 0xFFFF) +#define GET_CAPABILITY_PTR(x) (GET_LOW_16_BITS (x) >> 8) +#define GET_EXT_CAPABILITY_PTR(x) (GET_HIGH_16_BITS (x) >> 4) + +#define WORD_ALIGN_MASK 0x3 + +#define MAX_REINIT 3 // Number of soft reset re= try + +#define SLOT_POWER_LIMIT_75W 75 // Watt + +#define LINK_CHECK_SUCCESS 0 +#define LINK_CHECK_FAILED -1 +#define LINK_CHECK_WRONG_PARAMETER 1 + +#define AMPERE_PCIE_VENDOR_ID 0x1DEF +#define AC01_HOST_BRIDGE_DEVICE_ID_RCA 0xE100 +#define AC01_HOST_BRIDGE_DEVICE_ID_RCB 0xE110 +#define AC01_PCIE_BRIDGE_DEVICE_ID_RCA 0xE101 +#define AC01_PCIE_BRIDGE_DEVICE_ID_RCB 0xE111 + +#define MEMRDY_TIMEOUT 10 // 10 us +#define PIPE_CLOCK_TIMEOUT 20000 // 20,000 us +#define LTSSM_TRANSITION_TIMEOUT 100000 // 100 ms in total +#define EP_LINKUP_TIMEOUT (10 * 1000) // 10ms +#define LINK_WAIT_INTERVAL_US 50 + +#define PFA_MODE_ENABLE 0 +#define PFA_MODE_CLEAR 1 +#define PFA_MODE_READ 2 + +// +// Host Bridge registers +// +#define AC01_HOST_BRIDGE_RCA_DEV_MAP_REG 0x0 +#define AC01_HOST_BRIDGE_RCB_DEV_MAP_REG 0x4 +#define AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG 0x10 + +// AC01_HOST_BRIDGE_RCA_DEV_MAP_REG +#define RCA_DEV_MAP_SET(dst, src) (((dst) & ~0x7) | (((UINT3= 2) (src)) & 0x7)) +#define RCA_DEV_MAP_GET(val) ((val) & 0x7) + +// AC01_HOST_BRIDGE_RCB_DEV_MAP_REG +#define RCB_DEV_MAP_LOW_SET(dst, src) (((dst) & ~0x7) | (((UINT3= 2) (src)) & 0x7)) +#define RCB_DEV_MAP_LOW_GET(val) ((val) & 0x7) + +#define RCB_DEV_MAP_HIGH_SET(dst, src) (((dst) & ~0x70) | (((UINT= 32) (src) << 4) & 0x70)) +#define RCB_DEV_MAP_HIGH_GET(val) (((val) & 0x7) >> 4) + +// AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG +#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UI= NT32) (src)) & 0xFFFF)) +#define VENDOR_ID_GET(val) ((val) & 0xFFFF) + +#define DEVICE_ID_SET(dst, src) (((dst) & ~0xFFFF0000) | (= ((UINT32) (src) << 16) & 0xFFFF0000)) +#define DEVICE_ID_GET(val) (((val) & 0xFFFF0000) >> 1= 6) + +// +// PCIe core registers +// +#define AC01_PCIE_CORE_LINK_CTRL_REG 0x0 +#define AC01_PCIE_CORE_LINK_STAT_REG 0x4 +#define AC01_PCIE_CORE_IRQ_SEL_REG 0xC +#define AC01_PCIE_CORE_HOT_PLUG_STAT_REG 0x28 +#define AC01_PCIE_CORE_IRQ_ENABLE_REG 0x30 +#define AC01_PCIE_CORE_IRQ_EVENT_STAT_REG 0x38 +#define AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG 0x3C +#define AC01_PCIE_CORE_RESET_REG 0xC000 +#define AC01_PCIE_CORE_CLOCK_REG 0xC004 +#define AC01_PCIE_CORE_MEM_READY_REG 0xC104 +#define AC01_PCIE_CORE_RAM_SHUTDOWN_REG 0xC10C + +// AC01_PCIE_CORE_LINK_CTRL_REG +#define LTSSMENB_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (= src)) & 0x1)) +#define HOLD_LINK_TRAINING 0 +#define START_LINK_TRAINING 1 +#define DEVICETYPE_SET(dst, src) (((dst) & ~0xF0) | (((UINT32) = (src) << 4) & 0xF0)) +#define DEVICETYPE_GET(val) (((val) & 0xF0) >> 4) + +// AC01_PCIE_CORE_LINK_STAT_REG +#define PHY_STATUS_MASK (1 << 2) +#define SMLH_LTSSM_STATE_MASK 0x3F00 +#define SMLH_LTSSM_STATE_GET(val) ((val & SMLH_LTSSM_STATE_MASK)= >> 8) +#define LTSSM_STATE_L0 0x11 +#define RDLH_SMLH_LINKUP_STATUS_GET(val) (val & 0x3) +#define PHY_STATUS_MASK_BIT 0x04 +#define SMLH_LINK_UP_MASK_BIT 0x02 +#define RDLH_LINK_UP_MASK_BIT 0x01 + +// AC01_PCIE_CORE_IRQ_SEL_REG +#define AER_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1= )) +#define PME_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) = & 0x2)) +#define LINKAUTOBW_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) = & 0x4)) +#define BWMGMT_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) = & 0x8)) +#define EQRQST_SET(dst, src) (((dst) & ~0x10) | (((UINT32) (src) << 4)= & 0x10)) +#define INTPIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << = 8) & 0xFF00)) +#define IRQ_INT_A 0x01 + +// AC01_PCIE_CORE_HOT_PLUG_STAT_REG +#define PWR_IND_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1= )) +#define ATTEN_IND_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) = & 0x2)) +#define PWR_CTRL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) = & 0x4)) +#define EML_CTRL_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) = & 0x8)) + +// AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG +#define LINKUP_MASK 0x1 + +// AC01_PCIE_CORE_RESET_REG +#define DWC_PCIE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1= )) +#define RESET_MASK 0x1 +#define ASSERT_RESET 0x1 + +// AC01_PCIE_CORE_CLOCK_REG +#define AXIPIPE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1= )) + +// AC01_PCIE_CORE_MEM_READY_REG +#define MEMORY_READY 0x1 + +// AC01_PCIE_CORE_RAM_SHUTDOWN_REG +#define SD_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1= )) + +// +// AC01 PCIe Type 1 configuration registers +// +#define TYPE1_DEV_ID_VEND_ID_REG 0 +#define TYPE1_CLASS_CODE_REV_ID_REG 0x8 +#define TYPE1_CAP_PTR_REG 0x34 +#define SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG 0x18 +#define BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3C +#define PCIE_CAPABILITY_BASE 0x70 +#define EXT_CAPABILITY_START_BASE 0x100 +#define AER_CAPABILITY_BASE 0x100 + +// TYPE1_DEV_ID_VEND_ID_REG +#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((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 DEFAULT_BASE_CLASS_CODE 6 +#define SUB_CLASS_CODE_SET(dst, src) (((dst) & ~0xFF0000) | ((= (UINT32) (src) << 16) & 0xFF0000)) +#define DEFAULT_SUB_CLASS_CODE 4 +#define PROGRAM_INTERFACE_SET(dst, src) (((dst) & ~0xFF00) | (((UI= NT32) (src) << 8) & 0xFF00)) +#define REVISION_ID_SET(dst, src) (((dst) & ~0xFF) | (((UINT= 32) (src)) & 0xFF)) +#define DEFAULT_REVISION_ID 4 + +// SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG +#define SUB_BUS_SET(dst, src) (((dst) & ~0xFF0000) | (((= UINT32) (src) << 16) & 0xFF0000)) +#define DEFAULT_SUB_BUS 0xFF +#define SEC_BUS_SET(dst, src) (((dst) & ~0xFF00) | (((UI= NT32) (src) << 8) & 0xFF00)) +#define PRIM_BUS_SET(dst, src) (((dst) & ~0xFF) | (((UINT= 32) (src)) & 0xFF)) +#define DEFAULT_PRIM_BUS 0x00 + +// BRIDGE_CTRL_INT_PIN_INT_LINE_REG +#define INT_PIN_SET(dst, src) (((dst) & ~0xFF00) | (((UI= NT32) (src) << 8) & 0xFF00)) + +// +// PCI Express Capability +// +#define PCIE_CAPABILITY_ID 0x10 +#define LINK_CAPABILITIES_REG 0xC +#define LINK_CONTROL_LINK_STATUS_REG 0x10 +#define SLOT_CAPABILITIES_REG 0x14 +#define DEVICE_CONTROL2_DEVICE_STATUS2_REG 0x28 +#define LINK_CAPABILITIES2_REG 0x2C +#define LINK_CONTROL2_LINK_STATUS2_REG 0x30 + +// LINK_CAPABILITIES_REG +#define CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET(dst, src) (((dst) & ~0xC00) |= (((UINT32)(src) << 10) & 0xC00)) +#define NO_ASPM_SUPPORTED 0x0 +#define L0S_SUPPORTED 0x1 +#define L1_SUPPORTED 0x2 +#define L0S_L1_SUPPORTED 0x3 +#define CAP_MAX_LINK_WIDTH_GET(val) ((val & 0x3F0) >> 4) +#define CAP_MAX_LINK_WIDTH_SET(dst, src) (((dst) & ~0x3F0) | (((UIN= T32) (src) << 4) & 0x3F0)) +#define CAP_MAX_LINK_WIDTH_X1 0x1 +#define CAP_MAX_LINK_WIDTH_X2 0x2 +#define CAP_MAX_LINK_WIDTH_X4 0x4 +#define CAP_MAX_LINK_WIDTH_X8 0x8 +#define CAP_MAX_LINK_WIDTH_X16 0x10 +#define CAP_MAX_LINK_SPEED_GET(val) ((val & 0xF)) +#define CAP_MAX_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT3= 2) (src)) & 0xF)) +#define MAX_LINK_SPEED_25 0x1 +#define MAX_LINK_SPEED_50 0x2 +#define MAX_LINK_SPEED_80 0x3 +#define MAX_LINK_SPEED_160 0x4 +#define MAX_LINK_SPEED_320 0x5 + +// LINK_CONTROL_LINK_STATUS_REG +#define CAP_DLL_ACTIVE_GET(val) ((val & 0x20000000) >> 29) +#define CAP_SLOT_CLK_CONFIG_SET(dst, src) (((dst) & ~0x10000000) | (= ((UINT32) (src) << 28) & 0x10000000)) +#define CAP_NEGO_LINK_WIDTH_GET(val) ((val & 0x3F00000) >> 20) +#define CAP_LINK_SPEED_GET(val) ((val & 0xF0000) >> 16) +#define CAP_LINK_SPEED_SET(dst, src) (((dst) & ~0xF0000) | (((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_COMMON_CLK_SET(dst, src) (((dst) & ~0x40) | (((UINT= 32) (src) << 6) & 0x40)) +#define CAP_RETRAIN_LINK_SET(dst, src) (((dst) & ~0x20) | (((UINT= 32) (src) << 5) & 0x20)) +#define CAP_LINK_TRAINING_GET(val) ((val & 0x8000000) >> 27) +#define CAP_LINK_DISABLE_SET(dst, src) (((dst) & ~0x10) | (((UINT= 32)(src) << 4) & 0x10)) + +// SLOT_CAPABILITIES_REG +#define SLOT_HPC_SET(dst, src) (((dst) & ~0x40) | (((UINT= 32) (src) << 6) & 0x40)) +#define SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET(dst, src) \ + (((dst) & ~0x7F80) | (((UI= NT32)(src) << 7) & 0x7F80)) + +// DEVICE_CONTROL2_DEVICE_STATUS2_REG +#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src) (((dst) & ~0xF) | (((UINT3= 2) (src)) & 0xF)) + +// LINK_CONTROL2_LINK_STATUS2_REG +#define CAP_TARGET_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT3= 2) (src)) & 0xF)) + +// +// Advanced Error Reporting Capability +// +#define AER_CAPABILITY_ID 0x0001 +#define UNCORR_ERR_STATUS_OFF 0x04 +#define UNCORR_ERR_MASK_OFF 0x08 + +// UNCORR_ERR_MASK_OFF +#define CMPLT_TIMEOUT_ERR_MASK_SET(dst, src) (((dst) & ~0x4000) | (((UI= NT32) (src) << 14) & 0x4000)) +#define SDES_ERR_MASK_SET(dst, src) (((dst) & ~0x20) | (((UINT= 32)(src) << 5) & 0x20)) + +// +// Vendor specific RAS D.E.S Capability +// +#define RAS_DES_CAPABILITY_ID 0x000B +#define EVENT_COUNTER_CONTROL_REG 0x08 +#define EVENT_COUNTER_DATA_REG 0x0C + +// EVENT_COUNTER_CONTROL_REG +#define ECCR_GROUP_EVENT_SEL_SET(dst, src) (((dst) & ~0xFFF0000) | ((= (UINT32)(src) << 16) & 0xFFF0000)) +#define ECCR_GROUP_SEL_SET(dst, src) (((dst) & ~0xF000000) | ((= (UINT32)(src) << 24) & 0xF000000)) +#define ECCR_EVENT_SEL_SET(dst, src) (((dst) & ~0xFF0000) | (((= UINT32)(src) << 16) & 0xFF0000)) +#define ECCR_LANE_SEL_SET(dst, src) (((dst) & ~0xF00) | (((UIN= T32)(src) << 8) & 0xF00)) +#define ECCR_EVENT_COUNTER_ENABLE_SET(dst, src) (((dst) & ~0x1C) | (((UINT= 32)(src) << 2) & 0x1C)) +#define EVENT_COUNTER_ENABLE_NO_CHANGE 0x00 +#define EVENT_COUNTER_ENABLE_ALL_ON 0x07 +#define ECCR_EVENT_COUNTER_CLEAR_SET(dst, src) (((dst) & ~0x3) | (((UINT3= 2)(src)) & 0x3)) +#define EVENT_COUNTER_CLEAR_NO_CHANGE 0x00 +#define EVENT_COUNTER_CLEAR_ALL_CLEAR 0x03 + +// +// Secondary PCI Express Capability +// +#define SPCIE_CAPABILITY_ID 0x0019 +#define SPCIE_CAP_OFF_0C_REG 0x0C + +// SPCIE_CAP_OFF_0C_REG +#define DSP_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT3= 2) (src)) & 0xF)) +#define DSP_TX_PRESET1_SET(dst,src) (((dst) & ~0xF0000) | (((U= INT32) (src) << 16) & 0xF0000)) +#define DEFAULT_GEN3_PRESET 0x05 + +// +// Physical Layer 16.0 GT/s Extended Capability +// +#define PL16G_CAPABILITY_ID 0x0026 +#define PL16G_STATUS_REG 0x0C +#define PL16G_CAP_OFF_20H_REG 0x20 + +// PL16G_STATUS_REG +#define PL16G_STATUS_EQ_CPL_GET(val) (val & 0x1) +#define PL16G_STATUS_EQ_CPL_P1_GET(val) ((val & 0x2) >> 1) +#define PL16G_STATUS_EQ_CPL_P2_GET(val) ((val & 0x4) >> 2) +#define PL16G_STATUS_EQ_CPL_P3_GET(val) ((val & 0x8) >> 3) + +// PL16G_CAP_OFF_20H_REG +#define DSP_16G_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT3= 2) (src)) & 0xF)) +#define DSP_16G_TX_PRESET1_SET(dst,src) (((dst) & ~0xF00) | (((UIN= T32) (src) << 8) & 0xF00)) +#define DSP_16G_TX_PRESET2_SET(dst,src) (((dst) & ~0xF0000) | (((U= INT32) (src) << 16) & 0xF0000)) +#define DSP_16G_TX_PRESET3_SET(dst,src) (((dst) & ~0xF000000) | ((= (UINT32) (src) << 24) & 0xF000000)) +#define DSP_16G_RXTX_PRESET0_SET(dst,src) (((dst) & ~0xFF) | (((UINT= 32) (src)) & 0xFF)) +#define DSP_16G_RXTX_PRESET1_SET(dst,src) (((dst) & ~0xFF00) | (((UI= NT32) (src) << 8) & 0xFF00)) +#define DSP_16G_RXTX_PRESET2_SET(dst,src) (((dst) & ~0xFF0000) | (((= UINT32) (src) << 16) & 0xFF0000)) +#define DSP_16G_RXTX_PRESET3_SET(dst,src) (((dst) & ~0xFF000000) | (= ((UINT32) (src) << 24) & 0xFF000000)) +#define DEFAULT_GEN4_PRESET 0x57 + +// +// Port Logic +// +#define PORT_LINK_CTRL_OFF 0x710 +#define FILTER_MASK_2_OFF 0x720 +#define GEN2_CTRL_OFF 0x80C +#define GEN3_RELATED_OFF 0x890 +#define GEN3_EQ_CONTROL_OFF 0x8A8 +#define MISC_CONTROL_1_OFF 0x8BC +#define AMBA_ERROR_RESPONSE_DEFAULT_OFF 0x8D0 +#define AMBA_LINK_TIMEOUT_OFF 0x8D4 +#define AMBA_ORDERING_CTRL_OFF 0x8D8 +#define DTIM_CTRL0_OFF 0xAB0 +#define AUX_CLK_FREQ_OFF 0xB40 +#define CCIX_CTRL_OFF 0xC20 + +// PORT_LINK_CTRL_OFF +#define LINK_CAPABLE_SET(dst, src) (((dst) & ~0x3F0000) | (((= UINT32) (src) << 16) & 0x3F0000)) +#define LINK_CAPABLE_X1 0x1 +#define LINK_CAPABLE_X2 0x3 +#define LINK_CAPABLE_X4 0x7 +#define LINK_CAPABLE_X8 0xF +#define LINK_CAPABLE_X16 0x1F +#define LINK_CAPABLE_X32 0x3F +#define FAST_LINK_MODE_SET(dst, src) (((dst) & ~0x80) | (((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_SET(dst, src) (((dst) & ~0x1F00) | (((UI= NT32) (src) << 8) & 0x1F00)) +#define NUM_OF_LANES_X2 0x2 +#define NUM_OF_LANES_X4 0x4 +#define NUM_OF_LANES_X8 0x8 +#define NUM_OF_LANES_X16 0x10 + +// GEN3_RELATED_OFF +#define RATE_SHADOW_SEL_SET(dst, src) (((dst) & ~0x3000000) | ((= (UINT32) (src) << 24) & 0x3000000)) +#define GEN3_DATA_RATE 0x00 +#define GEN4_DATA_RATE 0x01 +#define EQ_PHASE_2_3_SET(dst, src) (((dst) & ~0x200) | (((UIN= T32) (src) << 9) & 0x200)) +#define ENABLE_EQ_PHASE_2_3 0x00 +#define DISABLE_EQ_PHASE_2_3 0x01 +#define RXEQ_REGRDLESS_SET(dst, src) (((dst) & ~0x2000) | (((UI= NT32) (src) << 13) & 0x2000)) +#define ASSERT_RXEQ 0x01 + +// GEN3_EQ_CONTROL_OFF +#define GEN3_EQ_FB_MODE(dst, src) (((dst) & ~0xF) | ((UINT32= ) (src) & 0xF)) +#define FOM_METHOD 0x01 +#define GEN3_EQ_PRESET_VEC(dst, src) (((dst) & 0xFF0000FF) | ((= (UINT32) (src) << 8) & 0xFFFF00)) +#define EQ_DEFAULT_PRESET_VECTOR 0x370 +#define GEN3_EQ_INIT_EVAL(dst,src) (((dst) & ~0x1000000) | ((= (UINT32) (src) << 24) & 0x1000000)) +#define INCLUDE_INIT_FOM 0x01 + +// MISC_CONTROL_1_OFF +#define DBI_RO_WR_EN_SET(dst, src) (((dst) & ~0x1) | (((UINT3= 2) (src)) & 0x1)) +#define ENABLE_WR 0x01 +#define DISABLE_WR 0x00 + +// AMBA_ERROR_RESPONSE_DEFAULT_OFF +#define AMBA_ERROR_RESPONSE_CRS_SET(dst, src) (((dst) & ~0x18) | (((= UINT32) (src) << 3) & 0x18)) +#define AMBA_ERROR_RESPONSE_GLOBAL_SET(dst, src) (((dst) & ~0x1) | (((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_FREQ_SET(dst, src) (((dst) & ~0x1FF) | ((= (UINT32) (src)) & 0x1FF)) +#define AUX_CLK_500MHZ 500 + +#endif /* AC01_PCIE_CORE_H_ */ diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c b= /Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c new file mode 100644 index 000000000000..ad648b1b9efd --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c @@ -0,0 +1,1416 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PcieCore.h" + +/** + Return the next extended capability base address + + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex PCIe controller index + @param IsRootComplex TRUE: Checking RootComplex configuration space + FALSE: Checking EP configuration space + @param ExtCapabilityId +**/ +PHYSICAL_ADDRESS +GetCapabilityBase ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex, + IN BOOLEAN IsRootComplex, + IN UINT16 ExtCapabilityId + ) +{ + BOOLEAN IsExtCapability =3D FALSE; + PHYSICAL_ADDRESS CfgBase; + UINT32 CapabilityId; + UINT32 NextCapabilityPtr; + UINT32 Val; + + if (IsRootComplex) { + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev= Num << DEV_SHIFT); + } else { + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev= Num << BUS_SHIFT); + } + + Val =3D MmioRead32 (CfgBase + TYPE1_CAP_PTR_REG); + NextCapabilityPtr =3D GET_LOW_8_BITS (Val); + + // Loop untill desired capability is found else return 0 + while (1) { + if ((NextCapabilityPtr & WORD_ALIGN_MASK) !=3D 0) { + // Not alignment, just return + return 0; + } + + Val =3D MmioRead32 (CfgBase + NextCapabilityPtr); + if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) { + CapabilityId =3D GET_LOW_8_BITS (Val); + } else { + CapabilityId =3D GET_LOW_16_BITS (Val); + } + + if (CapabilityId =3D=3D ExtCapabilityId) { + return (CfgBase + NextCapabilityPtr); + } + + if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) { + NextCapabilityPtr =3D GET_CAPABILITY_PTR (Val); + } else { + NextCapabilityPtr =3D GET_EXT_CAPABILITY_PTR (Val); + } + + if ((NextCapabilityPtr =3D=3D 0) && !IsExtCapability) { + IsExtCapability =3D TRUE; + NextCapabilityPtr =3D EXT_CAPABILITY_START_BASE; + } + + if ((NextCapabilityPtr =3D=3D 0) && IsExtCapability) { + return 0; + } + } +} + +/** + Configure equalization settings for Gen3 and Gen4 + + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex PCIe controller index +**/ +STATIC +VOID +ConfigureEqualization ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + PHYSICAL_ADDRESS CfgBase; + PHYSICAL_ADDRESS Gen3RelatedAddr; + PHYSICAL_ADDRESS Gen3EqControlAddr; + UINT32 Val; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + + // + // Gen3 and Gen4 EQ process use the same setting registers which are + // GEN3_RELATED_OFF and GEN3_EQ_CONTROL_OFF. Both are shadow registers + // and controlled by GEN3_RELATED_OFF[25:24]. + // + Gen3RelatedAddr =3D CfgBase + GEN3_RELATED_OFF; + Gen3EqControlAddr =3D CfgBase + GEN3_EQ_CONTROL_OFF; + + // + // Equalization setting for Gen3 + // + Val =3D MmioRead32 (Gen3RelatedAddr); + Val =3D RATE_SHADOW_SEL_SET (Val, GEN3_DATA_RATE); + MmioWrite32 (Gen3RelatedAddr, Val); + + Val =3D EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3); + Val =3D RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ); + MmioWrite32 (Gen3RelatedAddr, Val); + + Val =3D MmioRead32 (Gen3EqControlAddr); + Val =3D GEN3_EQ_FB_MODE (Val, FOM_METHOD); + Val =3D GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR); + Val =3D GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM); + MmioWrite32 (Gen3EqControlAddr, Val); + + // + // Equalization setting for Gen4 + // + Val =3D MmioRead32 (Gen3RelatedAddr); + Val =3D RATE_SHADOW_SEL_SET (Val, GEN4_DATA_RATE); + MmioWrite32 (Gen3RelatedAddr, Val); + + Val =3D EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3); + Val =3D RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ); + MmioWrite32 (Gen3RelatedAddr, Val); + + Val =3D MmioRead32 (Gen3EqControlAddr); + Val =3D GEN3_EQ_FB_MODE (Val, FOM_METHOD); + Val =3D GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR); + Val =3D GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM); + MmioWrite32 (Gen3EqControlAddr, Val); +} + +/** + Configure presets for Gen3 equalization + + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex PCIe controller index +**/ +STATIC +VOID +ConfigurePresetGen3 ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + PHYSICAL_ADDRESS LaneEqControlAddr; + PHYSICAL_ADDRESS SpcieCapabilityBase; + UINT32 Idx; + UINT32 LinkWidth; + UINT32 Val; + + // Get the Secondary PCI Express Extended capability base address + SpcieCapabilityBase =3D GetCapabilityBase (RootComplex, PcieIndex, TRUE,= SPCIE_CAPABILITY_ID); + if (SpcieCapabilityBase =3D=3D 0) { + DEBUG (( + DEBUG_ERROR, + "PCIE%d.%d: Cannot get SPCIE capability address\n", + RootComplex->ID, + PcieIndex + )); + return; + } + + LinkWidth =3D RootComplex->Pcie[PcieIndex].MaxWidth; + + // Each register holds the Preset for 2 lanes + for (Idx =3D 0; Idx < (LinkWidth / 2); Idx++) { + LaneEqControlAddr =3D SpcieCapabilityBase + SPCIE_CAP_OFF_0C_REG + Idx= * sizeof (UINT32); + Val =3D MmioRead32 (LaneEqControlAddr); + Val =3D DSP_TX_PRESET0_SET (Val, DEFAULT_GEN3_PRESET); + Val =3D DSP_TX_PRESET1_SET (Val, DEFAULT_GEN3_PRESET); + MmioWrite32 (LaneEqControlAddr, Val); + } +} + +/** + Configure presets for Gen4 equalization + + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex PCIe controller index +**/ +STATIC +VOID +ConfigurePresetGen4 ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + PHYSICAL_ADDRESS LaneEqControlAddr; + PHYSICAL_ADDRESS Pl16gCapabilityBase; + UINT32 Idx; + UINT32 LinkWidth; + UINT32 Val; + UINT8 Preset; + + // Get the Physical Layer 16.0 GT/s Extended capability base address + Pl16gCapabilityBase =3D GetCapabilityBase (RootComplex, PcieIndex, TRUE,= PL16G_CAPABILITY_ID); + if (Pl16gCapabilityBase =3D=3D 0) { + DEBUG (( + DEBUG_ERROR, + "PCIE%d.%d: Cannot get PL16G capability address\n", + RootComplex->ID, + PcieIndex + )); + return; + } + + if (RootComplex->PresetGen4[PcieIndex] =3D=3D PRESET_INVALID) { + Preset =3D DEFAULT_GEN4_PRESET; + } else { + Preset =3D RootComplex->PresetGen4[PcieIndex]; + } + + LinkWidth =3D RootComplex->Pcie[PcieIndex].MaxWidth; + + if (LinkWidth =3D=3D CAP_MAX_LINK_WIDTH_X2) { + LaneEqControlAddr =3D Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG; + Val =3D MmioRead32 (LaneEqControlAddr); + Val =3D DSP_16G_RXTX_PRESET0_SET (Val, Preset); + Val =3D DSP_16G_RXTX_PRESET1_SET (Val, Preset); + MmioWrite32 (LaneEqControlAddr, Val); + } else { + // Each register holds the Preset for 4 lanes + for (Idx =3D 0; Idx < (LinkWidth / 4); Idx++) { + LaneEqControlAddr =3D Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG + = Idx * sizeof (UINT32); + Val =3D MmioRead32 (LaneEqControlAddr); + 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 (LaneEqControlAddr, Val); + } + } +} + +VOID +ProgramHostBridgeInfo ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + EFI_STATUS Status; + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + // Program Root Complex Bifurcation + if (RootComplex->Active) { + if (RootComplex->Type =3D=3D RootComplexTypeA) { + TargetAddress =3D RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCA= _DEV_MAP_REG; + Status =3D MailboxMsgRegisterRead (RootComplex->Socket, TargetAddres= s, &Val); + if (!RETURN_ERROR (Status)) { + Val =3D RCA_DEV_MAP_SET (Val, RootComplex->DevMapLow); + MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val); + } + } else { + TargetAddress =3D RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCB= _DEV_MAP_REG; + Status =3D MailboxMsgRegisterRead (RootComplex->Socket, TargetAddres= s, &Val); + if (!RETURN_ERROR (Status)) { + Val =3D RCB_DEV_MAP_LOW_SET (Val, RootComplex->DevMapLow); + Val =3D RCB_DEV_MAP_HIGH_SET (Val, RootComplex->DevMapHigh); + MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val); + } + } + } + + // Program Vendor ID and Device ID + TargetAddress =3D RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_VENDOR_= DEVICE_ID_REG; + Status =3D MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &= Val); + if (!RETURN_ERROR (Status)) { + Val =3D VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID); + if (RootComplexTypeA =3D=3D RootComplex->Type) { + Val =3D DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCA); + } else { + Val =3D DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCB); + } + MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val); + } +} + +VOID +ProgramRootPortInfo ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex + ) +{ + PHYSICAL_ADDRESS CfgBase; + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + + // Program Class Code + TargetAddress =3D CfgBase + TYPE1_CLASS_CODE_REV_ID_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D REVISION_ID_SET (Val, DEFAULT_REVISION_ID); + Val =3D SUB_CLASS_CODE_SET (Val, DEFAULT_SUB_CLASS_CODE); + Val =3D BASE_CLASS_CODE_SET (Val, DEFAULT_BASE_CLASS_CODE); + MmioWrite32 (TargetAddress, Val); + + // Program Vendor ID and Device ID + TargetAddress =3D CfgBase + TYPE1_DEV_ID_VEND_ID_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID); + if (RootComplexTypeA =3D=3D RootComplex->Type) { + Val =3D DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCA + PcieIndex= ); + } else { + Val =3D DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCB + PcieIndex= ); + } + MmioWrite32 (TargetAddress, Val); +} + +VOID +ProgramLinkCapabilities ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + PHYSICAL_ADDRESS CfgBase; + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + UINT8 MaxWidth; + UINT8 MaxGen; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + + MaxWidth =3D RootComplex->Pcie[PcieIndex].MaxWidth; + MaxGen =3D RootComplex->Pcie[PcieIndex].MaxGen; + + TargetAddress =3D CfgBase + PORT_LINK_CTRL_OFF; + Val =3D MmioRead32 (TargetAddress); + switch (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 (TargetAddress, Val); + + TargetAddress =3D CfgBase + GEN2_CTRL_OFF; + Val =3D MmioRead32 (TargetAddress); + switch (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 (TargetAddress, Val); + + TargetAddress =3D CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG= ; + Val =3D MmioRead32 (TargetAddress); + switch (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 (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 (TargetAddress, Val); + + TargetAddress =3D CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL2_LINK_ST= ATUS2_REG; + Val =3D MmioRead32 (TargetAddress); + switch (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 (TargetAddress, Val); +} + +VOID +DisableCompletionTimeOut ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex, + IN BOOLEAN IsMask + ) +{ + PHYSICAL_ADDRESS CfgBase; + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + + TargetAddress =3D CfgBase + AER_CAPABILITY_BASE + UNCORR_ERR_MASK_OFF; + Val =3D MmioRead32 (TargetAddress); + Val =3D CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0); + MmioWrite32 (TargetAddress, Val); +} + +BOOLEAN +EnableItsMemory ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex + ) +{ + PHYSICAL_ADDRESS CsrBase; + PHYSICAL_ADDRESS TargetAddress; + UINT32 TimeOut; + UINT32 Val; + + CsrBase =3D RootComplex->Pcie[PcieIndex].CsrBase; + + // Clear memory shutdown + TargetAddress =3D CsrBase + AC01_PCIE_CORE_RAM_SHUTDOWN_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D SD_SET (Val, 0); + MmioWrite32 (TargetAddress, Val); + + // Poll till ITS Memory is ready + TimeOut =3D MEMRDY_TIMEOUT; + do { + Val =3D MmioRead32 (CsrBase + AC01_PCIE_CORE_MEM_READY_REG); + if (Val & MEMORY_READY) { + return TRUE; + } + + TimeOut--; + MicroSecondDelay (1); + } while (TimeOut > 0); + + return FALSE; +} + +BOOLEAN +EnableAxiPipeClock ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex + ) +{ + PHYSICAL_ADDRESS CsrBase; + PHYSICAL_ADDRESS TargetAddress; + UINT32 TimeOut; + UINT32 Val; + + CsrBase =3D RootComplex->Pcie[PcieIndex].CsrBase; + + // Enable subsystem clock and release reset + TargetAddress =3D CsrBase + AC01_PCIE_CORE_CLOCK_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D AXIPIPE_SET (Val, 1); + MmioWrite32 (TargetAddress, Val); + + TargetAddress =3D CsrBase + AC01_PCIE_CORE_RESET_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D DWC_PCIE_SET (Val, 0); + MmioWrite32 (TargetAddress, Val); + + // + // Controller does not provide any indicator for reset released. + // Must wait at least 1us as per EAS. + // + MicroSecondDelay (1); + + // Poll till PIPE clock is stable + TimeOut =3D PIPE_CLOCK_TIMEOUT; + do { + Val =3D MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG); + if (!(Val & PHY_STATUS_MASK)) { + return TRUE; + } + + TimeOut--; + MicroSecondDelay (1); + } while (TimeOut > 0); + + return FALSE; +} + +VOID +SetLinkTimeout ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex, + UINTN Timeout + ) +{ + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + TargetAddress =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex]= .DevNum << DEV_SHIFT) + + AMBA_LINK_TIMEOUT_OFF; + + Val =3D MmioRead32 (TargetAddress); + Val =3D LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, Timeout); + MmioWrite32 (TargetAddress, Val); +} + +VOID +StartLinkTraining ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex, + BOOLEAN StartLink + ) +{ + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + TargetAddress =3D RootComplex->Pcie[PcieIndex].CsrBase + AC01_PCIE_CORE_= LINK_CTRL_REG; + + Val =3D MmioRead32 (TargetAddress); + Val =3D LTSSMENB_SET (Val, StartLink ? START_LINK_TRAINING : HOLD_LINK_T= RAINING); + MmioWrite32 (TargetAddress, Val); +} + +VOID +EnableDbiAccess ( + AC01_ROOT_COMPLEX *RootComplex, + UINT32 PcieIndex, + BOOLEAN EnableDbi + ) +{ + PHYSICAL_ADDRESS TargetAddress; + UINT32 Val; + + TargetAddress =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex]= .DevNum << DEV_SHIFT) + + MISC_CONTROL_1_OFF; + + Val =3D MmioRead32 (TargetAddress); + Val =3D DBI_RO_WR_EN_SET (Val, EnableDbi ? ENABLE_WR : DISABLE_WR); + MmioWrite32 (TargetAddress, Val); +} + +/** + Setup and initialize the AC01 PCIe Root Complex and underneath PCIe cont= rollers + + @param RootComplex Pointer to Root Complex structure + @param ReInit Re-init status + @param ReInitPcieIndex PCIe controller index + + @retval RETURN_SUCCESS The Root Complex has been initialized 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 CfgBase; + PHYSICAL_ADDRESS CsrBase; + PHYSICAL_ADDRESS TargetAddress; + RETURN_STATUS Status; + UINT32 Val; + UINT8 PcieIndex; + + DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex= ->Socket, RootComplex->ID)); + + ProgramHostBridgeInfo (RootComplex); + + if (!ReInit) { + Status =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; + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev= Num << DEV_SHIFT); + + // Put Controller into reset if not in reset already + TargetAddress =3D CsrBase + AC01_PCIE_CORE_RESET_REG; + Val =3D MmioRead32 (TargetAddress); + if (!(Val & RESET_MASK)) { + Val =3D DWC_PCIE_SET (Val, ASSERT_RESET); + MmioWrite32 (TargetAddress, Val); + + // Delay 50ms to ensure controller finish its reset + MicroSecondDelay (50000); + } + + if (!EnableItsMemory (RootComplex, PcieIndex)) { + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - ITS Memory is not ready\n", PcieI= ndex)); + return RETURN_DEVICE_ERROR; + } + + // Hold link training + StartLinkTraining (RootComplex, PcieIndex, FALSE); + + if (!EnableAxiPipeClock (RootComplex, PcieIndex)) { + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - PIPE clock is not stable\n", Pcie= Index)); + return RETURN_DEVICE_ERROR; + } + + // Start PERST pulse + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE); + + // Allow programming to config space + EnableDbiAccess (RootComplex, PcieIndex, TRUE); + + // Program the power limit + TargetAddress =3D CfgBase + PCIE_CAPABILITY_BASE + SLOT_CAPABILITIES_R= EG; + Val =3D MmioRead32 (TargetAddress); + Val =3D SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT_75W= ); + MmioWrite32 (TargetAddress, Val); + + // Program DTI for ATS support + TargetAddress =3D CfgBase + DTIM_CTRL0_OFF; + Val =3D MmioRead32 (TargetAddress); + Val =3D DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0); + MmioWrite32 (TargetAddress, Val); + + // + // Program number of lanes used + // - Reprogram LINK_CAPABLE of PORT_LINK_CTRL_OFF + // - Reprogram NUM_OF_LANES of GEN2_CTRL_OFF + // - Reprogram CAP_MAX_LINK_WIDTH of LINK_CAPABILITIES_REG + // + ProgramLinkCapabilities (RootComplex, PcieIndex); + + // Set Zero byte request handling + TargetAddress =3D CfgBase + FILTER_MASK_2_OFF; + Val =3D MmioRead32 (TargetAddress); + 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 (TargetAddress, Val); + + TargetAddress =3D CfgBase + AMBA_ORDERING_CTRL_OFF; + Val =3D MmioRead32 (TargetAddress); + Val =3D AX_MSTR_ZEROLREAD_FW_SET (Val, 0); + MmioWrite32 (TargetAddress, Val); + + // + // Set Completion with CRS handling for CFG Request + // Set Completion with CA/UR handling non-CFG Request + // + TargetAddress =3D CfgBase + AMBA_ERROR_RESPONSE_DEFAULT_OFF; + Val =3D MmioRead32 (TargetAddress); + // 0x2: OKAY with FFFF_0001 and FFFF_FFFF + Val =3D AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2); + MmioWrite32 (TargetAddress, Val); + + // Set Legacy PCIE interrupt map to INTA + TargetAddress =3D CfgBase + BRIDGE_CTRL_INT_PIN_INT_LINE_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D INT_PIN_SET (Val, IRQ_INT_A); + MmioWrite32 (TargetAddress, Val); + + TargetAddress =3D CsrBase + AC01_PCIE_CORE_IRQ_SEL_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D INTPIN_SET (Val, IRQ_INT_A); + MmioWrite32 (TargetAddress, Val); + + if (RootComplex->Pcie[PcieIndex].MaxGen >=3D LINK_SPEED_GEN2) { + ConfigureEqualization (RootComplex, PcieIndex); + if (RootComplex->Pcie[PcieIndex].MaxGen >=3D LINK_SPEED_GEN3) { + ConfigurePresetGen3 (RootComplex, PcieIndex); + if (RootComplex->Pcie[PcieIndex].MaxGen >=3D LINK_SPEED_GEN4) { + ConfigurePresetGen4 (RootComplex, PcieIndex); + } + } + } + + // Link timeout after 1ms + SetLinkTimeout (RootComplex, PcieIndex, 1); + + DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE); + + ProgramRootPortInfo (RootComplex, PcieIndex); + + // Enable common clock for downstream + TargetAddress =3D CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_S= TATUS_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D CAP_SLOT_CLK_CONFIG_SET (Val, 1); + Val =3D CAP_COMMON_CLK_SET (Val, 1); + MmioWrite32 (TargetAddress, Val); + + // Match aux_clk to system + TargetAddress =3D CfgBase + AUX_CLK_FREQ_OFF; + Val =3D MmioRead32 (TargetAddress); + Val =3D AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ); + MmioWrite32 (TargetAddress, Val); + + // Assert PERST low to reset endpoint + BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE); + + // Start link training + StartLinkTraining (RootComplex, PcieIndex, TRUE); + + // Complete the PERST pulse + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE); + + // Lock programming of config space + EnableDbiAccess (RootComplex, PcieIndex, FALSE); + + if (ReInit) { + return RETURN_SUCCESS; + } + } + + return RETURN_SUCCESS; +} + +BOOLEAN +PcieLinkUpCheck ( + IN AC01_PCIE_CONTROLLER *Pcie + ) +{ + PHYSICAL_ADDRESS CsrBase; + UINT32 BlockEvent; + UINT32 LinkStat; + + CsrBase =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 + AC01_PCIE_CORE_LINK_STAT_REG); + 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 0) { + return FALSE; + } + + BlockEvent =3D MmioRead32 (CsrBase + AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG= ); + LinkStat =3D MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG); + + if (((BlockEvent & LINKUP_MASK) !=3D 0) + && (SMLH_LTSSM_STATE_GET(LinkStat) =3D=3D LTSSM_STATE_L0)) { + return TRUE; + } + + return FALSE; +} + +/** + Callback function when the Host Bridge enumeration end. + + @param RootComplex Pointer to the Root Complex structure +**/ +VOID +Ac01PcieCoreEndEnumeration ( + IN AC01_ROOT_COMPLEX *RootComplex + ) +{ + + PHYSICAL_ADDRESS TargetAddress; + UINT32 PcieIndex; + UINT32 Val; + + if (RootComplex =3D=3D NULL || !RootComplex->Active) { + return; + } + + // Clear uncorrectable error during enumuration phase. Mainly completion= timeout. + for (PcieIndex =3D 0; PcieIndex < RootComplex->MaxPcieController; PcieIn= dex++) { + if (!RootComplex->Pcie[PcieIndex].Active) { + continue; + } + + if (!PcieLinkUpCheck(&RootComplex->Pcie[PcieIndex])) { + // If link down/disabled after enumeration, disable completed time o= ut + DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE); + } + + // Clear all errors + TargetAddress =3D RootComplex->MmcfgBase + ((PcieIndex + 1) << DEV_SHI= FT) \ + + AER_CAPABILITY_BASE + UNCORR_ERR_STATUS_OFF; + Val =3D MmioRead32 (TargetAddress); + if (Val !=3D 0) { + // Clear error by writting + MmioWrite32 (TargetAddress, Val); + } + } +} + +/** + Comparing current link status with the max capabilities of the link + + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex PCIe controller index + @param EpMaxWidth EP max link width + @param EpMaxGen EP max link speed + + @retval -1: Link status do not match with link max 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, CfgBase; + UINT32 Val, LinkStat; + UINT32 MaxWidth, MaxGen; + + CsrBase =3D RootComplex->Pcie[PcieIndex].CsrBase; + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + + Val =3D MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_R= EG); + 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 + AC01_PCIE_CORE_LINK_STAT_REG); + Val =3D MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_S= TATUS_REG); + DEBUG (( + DEBUG_INFO, + "PCIE%d.%d: Link MaxWidth %d MaxGen %d, AC01_PCIE_CORE_LINK_STAT_REG 0= x%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 RasDesCapabilityBase + ) +{ + INT32 Ret =3D LINK_CHECK_SUCCESS; + UINT32 Val; + UINT8 ErrCode, ErrGrpNum; + + UINT32 ErrCtrlCfg[] =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 < ARRAY_SIZE (ErrCtrlCfg); ErrCode++) { + ErrGrpNum =3D GET_HIGH_8_BITS (ErrCtrlCfg[ErrCode]); + // Skipping per lane group + // Checking common lane group because AER error are included in common= group only + if ((ErrGrpNum !=3D 0) && (ErrGrpNum !=3D 4)) { + Val =3D MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG= ); + 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 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG, Val); + + // After setting Counter Control reg + // This delay just to make sure Counter Data reg is update with new = value + MicroSecondDelay (1); + Val =3D MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_DATA_REG); + 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, + ErrGrpNum, + GET_LOW_8_BITS (ErrCtrlCfg[ErrCode]) + )); + } + } + } + + return Ret; +} + +/** + Handle Predictive Failure Analysis command + + @param RootComplex Pointer to Root Complex structure + @param PcieIndex PCIe controller index + @param PFAMode The PFA mode + + @retval The link status +**/ +INT32 +Ac01PFACommand ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex, + IN UINT8 PFAMode + ) +{ + PHYSICAL_ADDRESS RasDesCapabilityBase; + PHYSICAL_ADDRESS TargetAddress; + INT32 Ret =3D LINK_CHECK_SUCCESS; + UINT32 Val; + + // Allow programming to config space + EnableDbiAccess (RootComplex, PcieIndex, TRUE); + + // Get the RAS D.E.S. capability base address + RasDesCapabilityBase =3D GetCapabilityBase (RootComplex, PcieIndex, TRUE= , RAS_DES_CAPABILITY_ID); + if (RasDesCapabilityBase =3D=3D 0) { + DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\= n", RootComplex->ID, PcieIndex)); + return LINK_CHECK_WRONG_PARAMETER; + } + + TargetAddress =3D RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG; + + switch (PFAMode) { + case PFA_MODE_ENABLE: + Val =3D MmioRead32 (TargetAddress); + Val =3D ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_ALL_O= N); + Val =3D ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_NO_CHAN= GE); + MmioWrite32 (TargetAddress, Val); + break; + + case PFA_MODE_CLEAR: + Val =3D MmioRead32 (TargetAddress); + Val =3D ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_NO_CH= ANGE); + Val =3D ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_ALL_CLE= AR); + MmioWrite32 (TargetAddress, Val); + break; + + case PFA_MODE_READ: + Ret =3D PFACounterRead (RootComplex, PcieIndex, RasDesCapabilityBase); + break; + + default: + DEBUG ((DEBUG_ERROR, "%a: Invalid PFA mode\n")); + } + + // Disable programming to config space + EnableDbiAccess (RootComplex, PcieIndex, FALSE); + + return Ret; +} + +UINT32 +EndpointCfgReady ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + PHYSICAL_ADDRESS CfgBase; + UINT32 TimeOut; + UINT32 Val; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << BUS_SHIFT); + + // Loop read CfgBase 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 (CfgBase); + if (Val !=3D 0xFFFF0001 && Val !=3D 0xFFFFFFFF) { + return TRUE; + } + + TimeOut -=3D LINK_WAIT_INTERVAL_US; + MicroSecondDelay (LINK_WAIT_INTERVAL_US); + } while (TimeOut > 0); + + return FALSE; +} + +/** + Get link capabilities link width and speed of endpoint + + @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure + @param PcieIndex[in] PCIe controller index + @param EpMaxWidth[out] EP max link width + @param EpMaxGen[out] EP max link speed +**/ +VOID +Ac01PcieCoreGetEndpointInfo ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex, + OUT UINT8 *EpMaxWidth, + OUT UINT8 *EpMaxGen + ) +{ + PHYSICAL_ADDRESS CfgBase; + PHYSICAL_ADDRESS PcieCapBase; + PHYSICAL_ADDRESS SecLatTimerAddr; + PHYSICAL_ADDRESS TargetAddress; + UINT32 RestoreVal; + UINT32 Val; + + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNu= m << DEV_SHIFT); + SecLatTimerAddr =3D CfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG= ; + + *EpMaxWidth =3D 0; + *EpMaxGen =3D 0; + + // Allow programming to config space + EnableDbiAccess (RootComplex, PcieIndex, TRUE); + + Val =3D MmioRead32 (SecLatTimerAddr); + RestoreVal =3D Val; + Val =3D SUB_BUS_SET (Val, DEFAULT_SUB_BUS); + Val =3D SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum); + Val =3D PRIM_BUS_SET (Val, DEFAULT_PRIM_BUS); + MmioWrite32 (SecLatTimerAddr, Val); + + if (EndpointCfgReady (RootComplex, PcieIndex)) { + PcieCapBase =3D GetCapabilityBase (RootComplex, PcieIndex, FALSE, PCIE= _CAPABILITY_ID); + if (PcieCapBase =3D=3D 0) { + DEBUG (( + DEBUG_ERROR, + "PCIE%d.%d Cannot get PCIe capability base address!\n", + RootComplex->ID, + PcieIndex + )); + } else { + Val =3D MmioRead32 (PcieCapBase + LINK_CAPABILITIES_REG); + *EpMaxWidth =3D CAP_MAX_LINK_WIDTH_GET (Val); + *EpMaxGen =3D CAP_MAX_LINK_SPEED_GET (Val); + DEBUG (( + DEBUG_INFO, + "PCIE%d.%d EP MaxWidth %d EP MaxGen %d \n", RootComplex->ID, + PcieIndex, + *EpMaxWidth, + *EpMaxGen + )); + + // From EP, enabling common clock for upstream + TargetAddress =3D PcieCapBase + LINK_CONTROL_LINK_STATUS_REG; + Val =3D MmioRead32 (TargetAddress); + Val =3D CAP_SLOT_CLK_CONFIG_SET (Val, 1); + Val =3D CAP_COMMON_CLK_SET (Val, 1); + MmioWrite32 (TargetAddress, Val); + } + } + + // Restore value in order to not affect enumeration process + MmioWrite32 (SecLatTimerAddr, RestoreVal); + + // Disable programming to config space + EnableDbiAccess (RootComplex, PcieIndex, FALSE); +} + +VOID +PollLinkUp ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 PcieIndex + ) +{ + UINT32 TimeOut; + + // Poll until link up + // This checking for linkup status and + // give LTSSM state the time to transit from DECTECT state to L0 state + // Total delay are 100ms, smaller number of delay cannot always make 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 LinkStatusCheck, RasdesChecking; + INT32 NumberOfReset =3D MAX_REINIT; + UINT8 EpMaxWidth, EpMaxGen; + + // PCIe controller is not active or Link is not up + // Nothing to be done + if ((!RootComplex->Pcie[PcieIndex].Active) || (!RootComplex->Pcie[PcieIn= dex].LinkUp)) { + return LINK_CHECK_WRONG_PARAMETER; + } + + do { + if (RootComplex->Pcie[PcieIndex].LinkUp) { + // Enable all of RASDES register to detect any training error + Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_ENABLE); + + // Accessing Endpoint and checking current link capabilities + Ac01PcieCoreGetEndpointInfo (RootComplex, PcieIndex, &EpMaxWidth, &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 Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_= READ); + + // Clear error counter + Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_CLEAR); + + // If link check functions return passed, then breaking out + // else go to soft reset + if (LinkStatusCheck !=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 CfgBase; + UINT8 PcieIndex; + UINT32 Index; + UINT32 Val; + + *IsNextRoundNeeded =3D FALSE; + *FailedPcieCount =3D 0; + for (Index =3D 0; Index < MaxPcieControllerOfRootComplexB; 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]; + CfgBase =3D RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].Dev= Num << DEV_SHIFT); + + if (Pcie->Active && !Pcie->LinkUp) { + if (PcieLinkUpCheck (Pcie)) { + Pcie->LinkUp =3D TRUE; + Val =3D MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_= LINK_STATUS_REG); + + DEBUG (( + DEBUG_INFO, + "%a Socket%d RootComplex%d RP%d NEGO_LINK_WIDTH: 0x%x LINK_SPEED= : 0x%x\n", + __FUNCTION__, + RootComplex->Socket, + RootComplex->ID, + PcieIndex, + CAP_NEGO_LINK_WIDTH_GET (Val), + CAP_LINK_SPEED_GET (Val) + )); + + // Doing link checking and recovery if needed + Ac01PcieCoreQoSLinkCheckRecovery (RootComplex, PcieIndex); + + // Link timeout after 32ms + SetLinkTimeout (RootComplex, PcieIndex, 32); + + // Un-mask Completion Timeout + DisableCompletionTimeOut (RootComplex, PcieIndex, FALSE); + + } else { + *IsNextRoundNeeded =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, NextRoundNeeded; + UINT64 PrevTick, CurrTick, ElapsedCycle; + UINT64 TimerTicks64; + UINT8 ReInit; + INT8 FailedPciePtr[MaxPcieControllerOfRootComplexB]; + INT8 FailedPcieCount; + + ReInit =3D 0; + +_link_polling: + NextRoundNeeded =3D FALSE; + // + // 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 MAX_UINT64 - 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 TRUE; + } + } + + 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