From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (NAM12-BN8-obe.outbound.protection.outlook.com [40.107.237.122]) by mx.groups.io with SMTP id smtpd.web10.5419.1635932397393298993 for ; Wed, 03 Nov 2021 02:39:57 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=cODR41mx; spf=pass (domain: os.amperecomputing.com, ip: 40.107.237.122, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=aoVApePw9bG+R6VIW/4pGIenfTsiiKi8jhxDBerZJXfZreeCHHFhjUTsrwai3ZIO3ePTzuEixbGnzTuk9oyJveA0ACvZ0roHRlEgYKdetHuBK13724ox7BKJohf0NRCUFKCkEA5I4q82Fk5LGu33cxH5IN3+Ew3VEMui2kD5H+3KgqL7ngeOOBLNtM5ppXkntPn5KNmsjtuo4fjW1cczQKWvPM5fvEgqlpM2SoswLQOSwp3gzB22uOhjniedssOfbdXq144z0rXcz8NDp7/lk9IVzxwEB9AdIBu30aXdG6klschShgH8vt8z/nHqcHdn73Q1/udioTvBUmbuSNlubA== 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=ts7HWrmEbl6V0NBb4tQh03vRYgo4c6pFQ0DASE9rxzw=; b=Eb1yxpYVSe8r+X3XHKRtuHMKBx6Smnz+VVFa3w555NY+0V7vKorLBg4z9ynmvMWa8DCY6AI7e2HzNu/kuyhiMPEjjtsi49NfggO7dVsrh8nPpwW2AYrbHG6bM9qDlU4+k5EsEOBqSt+QwOi3nt1/AYOW8Z/yUvB5OIZaU/e7r8Y3RlqoHRlG5SLVPQ1sp6y0DqMfN/0d6kfTN0GIJRLS9tvdhw7IcGJdIiuwnlOOka03SIE8Qnf2qNgWJ+ktEbfrrCMwhDTNNu++X8/EBb4I4HV9kkGWxxx/hVF9X6G7ZWVGqy1iqxo8ceYWGdxj+Oq08FcvipGGX5frRWTjlHC9Mg== 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=ts7HWrmEbl6V0NBb4tQh03vRYgo4c6pFQ0DASE9rxzw=; b=cODR41mx9yznb5jVSuq17tu72XcSfdmOvL7Z4377PF40BLzyH1IhTqK6qfZwsE4/6BHZeay8QZl3szllFOPTTBfpurYmGkb66xpTuL8WLpCQqH20fT76N5uVqVwRFSQiqgEysljuttu+IOQcRachbK7C9cffC5jMVG0qrZp71Wo= Authentication-Results: nuviainc.com; dkim=none (message not signed) header.d=none;nuviainc.com; dmarc=none action=none header.from=os.amperecomputing.com; Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by PH0PR01MB7333.prod.exchangelabs.com (2603:10b6:510:dd::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.11; Wed, 3 Nov 2021 09:39:54 +0000 Received: from PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee]) by PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee%5]) with mapi id 15.20.4669.011; Wed, 3 Nov 2021 09:39:54 +0000 Message-ID: Date: Wed, 3 Nov 2021 16:33:24 +0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.2.1 Subject: Re: [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance To: Leif Lindholm Cc: devel@edk2.groups.io, patches@amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone References: <20211022061809.31087-1-nhi@os.amperecomputing.com> <20211022061809.31087-13-nhi@os.amperecomputing.com> <20211026124524.ogphzlh34uhc5vga@leviathan> From: "Nhi Pham" In-Reply-To: <20211026124524.ogphzlh34uhc5vga@leviathan> X-ClientProxiedBy: HKAPR03CA0009.apcprd03.prod.outlook.com (2603:1096:203:c8::14) To PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 Received: from [192.168.1.3] (113.188.173.157) by HKAPR03CA0009.apcprd03.prod.outlook.com (2603:1096:203:c8::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.6 via Frontend Transport; Wed, 3 Nov 2021 09:39:49 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: fae79bd7-89e1-4ec7-5fb1-08d99eade3c5 X-MS-TrafficTypeDiagnostic: PH0PR01MB7333: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4gMprFT8t4p9dxjGrKZOSW0gCuOcUVnhWFKI/yLUToPlfsgKeI/REmNmOG/gOKxukwst0AE+DGeOBWYaVNiuDHgziPNw6eaI8KsZQC4ublFDHyVS8GB5u8oj/Ut8OSOZ7DVtjz6g+I8gX6ikC+LK9QS5rpwv4UebR+AeWi7tXyCd9SmdhczGb1KOvv1Ehh3p0/EmGiAkeQQQrnV9T3ByPViLC9YXZiPDK/bZmM5p6YmWtie4xGxlBrQzRXmZM/TXO0xJ7PzRBaRbBgwTB798YAU49e7OHC0canTeW5y7LdM6LL5kTZSXto+YpccYsus7R9AcqSabJuvixqYM86RIjhqUgGQ6nd4giEoyHjCQeFkrzwHOYXXITyOaWUmQR0zDCKoKEXG3zMogHLBALb/UIuf7rjJG+H6q9tFoj5lScthbY4chtHSLDgKrBbCqKQ2GDF5ApE9zxaT7QVeYO7uVMAB/+WfEOY1Z2oW3RHqlz/UFS7lFkSLv8N1nE7oD/oNEOFg/VgLX2J9x9U2NyWpMH5ZkrhWl8T9PzY8S6e3+VQ9hVAeHgEGss5V5eyajh7+YyTKRuZiZlp1xQ40bBxY9lTi91LG7Sb+T1pSYZRXYA4K/CtSqtSjctmXLhP9w+HqpgElHCka2eyhF2gEJMTG23WpKxjeZW5eB/lozSSvb6fHLHeCwRbCsBA7VbRYOCbNq9zosR7rhO3E2vhu9r3UU7866G4awytsBhbVQEOC7Ps+Aj6g3vdDo0DMzt02UbeANvn+E9xIlRtEuHd3hElb+FSjN/Y2Yg2CQHx4JUSEOWY0= 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)(6666004)(30864003)(38350700002)(66946007)(2906002)(2616005)(86362001)(38100700002)(52116002)(6486002)(53546011)(16576012)(186003)(54906003)(8676002)(5660300002)(508600001)(316002)(31696002)(83380400001)(66476007)(31686004)(66556008)(26005)(6916009)(19627235002)(4326008)(956004)(8936002)(9186005)(45980500001)(43740500002)(579004)(559001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dTZsK0w2Y1dIUVFGZTl4cVZkYU1IZjBncGhPYkYxNmc2RE5STEZxdmRhVDFq?= =?utf-8?B?S1B4UXhxN25xY0pxMmx2VGpyM09VL1RJdjRGekNQUnlURkxkUmMxTlFnYjNL?= =?utf-8?B?aWlJTndlRGFGSVpZYTVmN2lsQzlYVFhnRXd6ZkJlMTFXMzZvTFVSeXpLY0NQ?= =?utf-8?B?K2NwRjM3d2JybmsyRU9NVDZGYVJpanpOdU1VZ2duTm1WcENhUjdHL3JhWVho?= =?utf-8?B?Y0dCdjRQVjQ5NzlYYjlpREFpSUJJSEdnaTE1WXg0SnFGWUs1Ymp5bnFXMVMv?= =?utf-8?B?N2dHVThYMFU0YWFvTzZIZytkMXE3cUhTS25WZmtiaVdLL1owd2hPbVlMNnY5?= =?utf-8?B?QVJOZzJKazFtUnpzSjg0K05pWFRsVHlkTFA3d1RueDNUWlpyZUdDeElkeGU2?= =?utf-8?B?K2ZidXEwR0I1cUpGWUJoV2lvdGFnSTJiNmIzZytHMHVudmt6YTViWTFYQzY4?= =?utf-8?B?UUVrVzhYM3BCVWEzY25LS1lqeXR3NWlYbWNJOXZndVBNLzV2QlAyVFZ6dGMy?= =?utf-8?B?d0JUcENjU1RZclR6YXVPY1VwTFJyanU1NjhMRVpQYlpOT2FlOUpiVnpuekcr?= =?utf-8?B?QjB5OHZNSndCTXB2SURtM3V5WFRWR2ZlWGNSdTlIS1p0RXNMY05aUFI5V1Na?= =?utf-8?B?VFhFdVV1TllPa2ZLR2FEdkJxTWUrM2o0NDgxZWNzVnpQZDREMWVvZWs0YkRy?= =?utf-8?B?dWFFYXl1V1g3b0w1UFltM2N3T0g3U3F3RXp1QXhvbVhxMS8xVGVyZjZoL0c1?= =?utf-8?B?UFJjbFVkUC9BY2QwV0EwN1VuYzdPM3lLS1orQllnbGt4YjU2b28yajdvVFlX?= =?utf-8?B?MkpXK1h6dXlJRDIrYjlzNmVuQXg1OGUydXBhTXFPbnB2eng2RlZ0SVcwOGlp?= =?utf-8?B?dmJUUFRHcmpvTGF0cVFmOHAvaCsvL1U3TjJ6TDZXUXh4VTlITEUybndNcHBG?= =?utf-8?B?MWFhT0xYRXNZZUFyTDlGV214bGxselo2c3c1Ylg0dEltNVFweWVoVm85Vyt6?= =?utf-8?B?eWRkL09CTXQrV1IyZm0rSElDNzlKRkVTMEwzSERVbFdCWmljMlRWakpkUjFX?= =?utf-8?B?N2p0UnR3S1BXRUxlVklHQWVkTUhLYWlJVkE5R0pQenRtM3RjbXlvNStydEY1?= =?utf-8?B?OHE4UDExZ01May9zT2hqVldWb3RDSmY0aGZFUEx1K3k0S09KZkc3aHdhdCt3?= =?utf-8?B?cWpkZWVzMjljUEwyRG9WWVhQa2l1SG4zbFRaQklEMHpHMHZkYXlHU0xMV2o2?= =?utf-8?B?czV2eUZkYjYwNmZlYzZKMnp1QjIxU3JFeWtGR0hBcldKRExaTmRpUDF5UTl1?= =?utf-8?B?VkVQOG1QQy9OeXMwWXFZRDFmT0UvRiszQmFVeVFQL2ZkczNvb2tuUkhzZE5w?= =?utf-8?B?bU9lMFRPOS9FVnFWNktEQ2lTVWxWdjB4bnlMYng5KytOOHBhK2tBYTE1M096?= =?utf-8?B?UlZYeWNSRU0vRStvTVJ5OGJrQ3B4Vmh2Tk9xNTIxY043by9xQTYrWm5EK1Vy?= =?utf-8?B?SEk1SmY0K00yMTJkclZpd3ZpWi9GN3RiaHNkUlJkVUNhZU5KbUJ1ckEwOTdk?= =?utf-8?B?YytCVEhUOXljTmFtRmJOaVNIcGpTWFZpdE9ETTJSTkVSeE9Hb3VLNW1TMHo0?= =?utf-8?B?ZkNpQWFXY001ZTN2TDU1Ym1jQzZNcTU5L2tkWXBMSEhLV2o4MVZOWVZXUUJa?= =?utf-8?B?b3cyWFRIUTJuK0RFajNPVFZDQ085UTFCaXBIaFFna1Zoa2wrK3ZuRHk5OHNK?= =?utf-8?B?MEw4c0x3TVRLQVJRUElvWmpTT08xT3YzS0tId0h1TnJmN3ZodzF4Y1NHcWhk?= =?utf-8?B?cjV0RDl3MjJWNjlHU0Z0MTFMNVYvTFFScmpIcmNwQStWUHI0RnowSklxNDFu?= =?utf-8?B?VWhkRVRsSzUyL2NXaHBVaGd2Nkt3cEVYMzFQOXhxREMrYzQ3ekxUK2xZc2Rs?= =?utf-8?B?VXR5WEtGNGVPRkt4MGpYZEM1THpET1g5d3RhWlgyUHl5RU41ejRHbHBpS1dD?= =?utf-8?B?eFFpZzM1emQ0ZGZQcUMvRzY2NUMzQ2JFRnZmRTNGblFaSXdFdmx6cnpUaS9L?= =?utf-8?B?d2NBNk01YVNRWW5tWUc3dUpHZUYxSDFFcnRrcW5xeDJ2TlhNU0ZYZ3pDdk9L?= =?utf-8?B?NVNaeDlNL0hMUzA4empBR3dDcnZWQnllaU5oNVZwMHNDM1VXRWU2eDNIT2ZB?= =?utf-8?B?NDl0T2RGcnVkTzdJdGxGdFVDRWFhcWxYbzVoS21HRDVMRWF0MHAwTXVNMHlK?= =?utf-8?Q?zbLjWpSc3WyXEICGGqfvBO2NbyeAjY4EbzUyOdis+U=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: fae79bd7-89e1-4ec7-5fb1-08d99eade3c5 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Nov 2021 09:39:54.3155 (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: WxUT8GrUZ/Itwgd7wXp8WRHI7hKLYGXLCT4Mgr8gOK8350XWLYYFEQvyHPCi4UBM885ij80l4YRO8w9hG7GCVNlPgfMf3DsqnZmHEMjOJjc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB7333 Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi Leif, Thanks a lot for reviewing. I will address all your comments and review carefully through this module as well. Best regards, Nhi On 26/10/2021 19:45, Leif Lindholm wrote: > On Fri, Oct 22, 2021 at 13:17:50 +0700, Nhi Pham wrote: >> 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.inf | 25 + >> Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h | 49 + >> Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h | 45 + >> Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h | 451 +++++++ >> Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c | 1391 ++++++++++++++++++++ >> Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c | 47 + >> 10 files changed, 2063 insertions(+) >> >> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> index e19925c68a0e..7bd4d3ac9462 100644 >> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> @@ -43,6 +43,12 @@ [LibraryClasses] >> ## @libraryclass Defines a set of methods to access flash memory. >> FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h >> >> + ## @libraryclass Defines a set of platform dependent functions >> + BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h >> + >> + ## @libraryclass Defines a set of methods to initialize Pcie >> + Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h >> + >> [Guids] >> ## NVParam MM GUID >> gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } } >> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> index c01a8be3c607..a6f7d87769fe 100644 >> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> @@ -81,6 +81,8 @@ [LibraryClasses.common] >> NVParamLib|Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.inf >> MailboxInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.inf >> SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf >> + PciePhyLib|Silicon/Ampere/AmpereAltraBinPkg/Library/PciePhyLib/PciePhyLib.inf >> + Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf >> AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf >> TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf >> I2cLib|Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf >> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc >> index e4b29e36fc8d..23a297d0dbeb 100644 >> --- a/Platform/Ampere/JadePkg/Jade.dsc >> +++ b/Platform/Ampere/JadePkg/Jade.dsc >> @@ -82,6 +82,11 @@ [LibraryClasses] >> # >> AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf >> >> + # >> + # Pcie Board >> + # >> + BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf >> + >> ################################################################################ >> # >> # Specific Platform Pcds >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf >> new file mode 100644 >> index 000000000000..8c8661265cd5 >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf >> @@ -0,0 +1,42 @@ >> +## @file >> +# >> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x0001001B >> + BASE_NAME = Ac01PcieLib >> + FILE_GUID = 8ABFA0FC-313E-11E8-B467-0ED5F89F718B >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = Ac01PcieLib >> + >> +[Sources] >> + PcieCore.c >> + PcieCore.h >> + >> +[Packages] >> + ArmPkg/ArmPkg.dec >> + MdePkg/MdePkg.dec >> + Silicon/Ampere/AmpereAltraBinPkg/AmpereAltraBinPkg.dec >> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> + >> +[LibraryClasses] >> + ArmGenericTimerCounterLib >> + BaseLib >> + BoardPcieLib >> + DebugLib >> + HobLib >> + IoLib >> + PciePhyLib >> + SystemFirmwareInterfaceLib >> + TimerLib >> + >> +[Guids] >> + gPlatformInfoHobGuid >> + >> +[Depex] >> + TRUE >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf >> new file mode 100644 >> index 000000000000..435092b864ec >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf >> @@ -0,0 +1,25 @@ >> +## @file >> +# >> +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x0001001B >> + BASE_NAME = BoardPcieLibNull >> + FILE_GUID = 7820C925-F525-4101-8E64-87838356B7A6 >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = BoardPcieLib >> + >> +[Sources.common] >> + BoardPcieLibNull.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> + >> +[LibraryClasses] >> + BaseLib >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h >> new file mode 100644 >> index 000000000000..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 controllers >> + >> + @param RootComplex Pointer to Root Complex structure >> + @param ReInit Re-init status >> + @param ReInitPcieIndex PCIe index >> + >> + @retval RETURN_SUCCESS The Root Complex has been initialized successfully. >> + @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready. >> +**/ >> +RETURN_STATUS >> +Ac01PcieCoreSetupRC ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN BOOLEAN ReInit, >> + IN UINT8 ReInitPcieIndex >> + ); >> + >> +/** >> + Verify the link status and retry to initialize the Root Complex if there's any issue. >> + >> + @param RootComplexList Pointer to the Root Complex list >> +**/ >> +VOID >> +Ac01PcieCorePostSetupRC ( >> + IN AC01_ROOT_COMPLEX *RootComplexList >> + ); >> + >> +/** >> + Callback function when the Host Bridge enumeration end. >> + >> + @param RootComplex Pointer to the Root Complex structure >> +**/ >> +VOID >> +Ac01PcieCoreEndEnumeration ( >> + IN AC01_ROOT_COMPLEX *RootComplex >> + ); >> + >> +#endif /* AC01_PCIE_LIB_H_ */ >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h >> new file mode 100644 >> index 000000000000..34e7dee702ec >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h >> @@ -0,0 +1,45 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef BOARD_PCIE_LIB_H_ >> +#define BOARD_PCIE_LIB_H_ >> + >> +#include >> + >> +/** >> + Assert PERST of the PCIe controller >> + >> + @param[in] RootComplex Root Complex instance. >> + @param[in] PcieIndex PCIe controller index of input Root Complex. >> + @param[in] IsPullToHigh Target status for the PERST. >> + >> + @retval RETURN_SUCCESS The operation is successful. >> + @retval Others An error occurred. >> +**/ >> +RETURN_STATUS >> +EFIAPI >> +BoardPcieAssertPerst ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN BOOLEAN IsPullToHigh >> + ); >> + >> +/** >> + Override the segment number for a root complex with a board specific number. >> + >> + @param[in] RootComplex Root Complex instance with properties. >> + >> + @retval Segment number corresponding to the input root complex. >> + Default segment number is 0x0F. >> +**/ >> +UINT16 >> +BoardPcieGetSegmentNumber ( >> + IN AC01_ROOT_COMPLEX *RootComplex >> + ); >> + >> +#endif /* BOARD_PCIE_LIB_H_ */ >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h >> new file mode 100644 >> index 000000000000..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) (src)) & 0xF)) >> +#define DSP_16G_TX_PRESET1_SET(dst,src) (((dst) & ~0xF00) | (((UINT32) (src) << 8) & 0xF00)) >> +#define DSP_16G_TX_PRESET2_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000)) >> +#define DSP_16G_TX_PRESET3_SET(dst,src) (((dst) & ~0xF000000) | (((UINT32) (src) << 24) & 0xF000000)) >> +#define DSP_16G_RXTX_PRESET0_SET(dst,src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> +#define DSP_16G_RXTX_PRESET1_SET(dst,src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00)) >> +#define DSP_16G_RXTX_PRESET2_SET(dst,src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000)) >> +#define DSP_16G_RXTX_PRESET3_SET(dst,src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000)) >> + >> +// >> +// PCIe PF0_PORT_LOGIC registers >> +// >> +#define PORT_LOCIG_VC0_P_RX_Q_CTRL_OFF 0x748 >> +#define PORT_LOCIG_VC0_NP_RX_Q_CTRL_OFF 0x74C >> + >> +// >> +// SNPSRAM Synopsys Memory Read/Write Margin registers >> +// >> +#define SPRF_RMR 0x0 >> +#define SPSRAM_RMR 0x4 >> +#define TPRF_RMR 0x8 >> +#define TPSRAM_RMR 0xC >> + >> +// >> +// Host bridge registers >> +// >> +#define HBRCAPDMR 0x0 >> +#define HBRCBPDMR 0x4 >> +#define HBPDVIDR 0x10 >> +#define HBPRBNR 0x14 >> +#define HBPREVIDR 0x18 >> +#define HBPSIDR 0x1C >> +#define HBPCLSSR 0x20 >> + >> +// HBRCAPDMR >> +#define RCAPCIDEVMAP_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7)) >> +#define RCAPCIDEVMAP_GET(val) ((val) & 0x7) >> + >> +// HBRCBPDMR >> +#define RCBPCIDEVMAPLO_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7)) >> +#define RCBPCIDEVMAPLO_GET(val) ((val) & 0x7) >> + >> +#define RCBPCIDEVMAPHI_SET(dst, src) (((dst) & ~0x70) | (((UINT32) (src) << 4) & 0x70)) >> +#define RCBPCIDEVMAPHI_GET(val) (((val) & 0x7) >> 4) >> + >> +// HBPDVIDR >> +#define PCIVENDID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF)) >> +#define PCIVENDID_GET(val) ((val) & 0xFFFF) >> + >> +#define PCIDEVID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000)) >> +#define PCIDEVID_GET(val) (((val) & 0xFFFF0000) >> 16) >> + >> +// HBPRBNR >> +#define PCIRBNUM_SET(dst, src) (((dst) & ~0x1F) | (((UINT32) (src)) & 0x1F)) >> + >> +// HBPREVIDR >> +#define PCIREVID_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> + >> +// HBPSIDR >> +#define PCISUBSYSVENDID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF)) >> + >> +#define PCISUBSYSID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000)) >> + >> +// HBPCLSSR >> +#define CACHELINESIZE_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> + >> +// >> +// PCIE core register >> +// >> +#define LINKCTRL 0x0 >> +#define LINKSTAT 0x4 >> +#define IRQSEL 0xC >> +#define HOTPLUGSTAT 0x28 >> +#define IRQENABLE 0x30 >> +#define IRQEVENTSTAT 0x38 >> +#define BLOCKEVENTSTAT 0x3c >> +#define RESET 0xC000 >> +#define CLOCK 0xC004 >> +#define MEMRDYR 0xC104 >> +#define RAMSDR 0xC10C >> + >> +// LINKCTRL >> +#define LTSSMENB_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> +#define DEVICETYPE_SET(dst, src) (((dst) & ~0xF0) | (((UINT32) (src) << 4) & 0xF0)) >> +#define DEVICETYPE_GET(val) (((val) & 0xF0) >> 4) >> + >> +// LINKSTAT >> +#define PHY_STATUS_MASK (1 << 2) >> +#define SMLH_LTSSM_STATE_MASK 0x3f00 >> +#define SMLH_LTSSM_STATE_GET(val) ((val & 0x3F00) >> 8) >> +#define RDLH_SMLH_LINKUP_STATUS_GET(val) (val & 0x3) >> +#define PHY_STATUS_MASK_BIT 0x04 >> +#define SMLH_LINK_UP_MASK_BIT 0x02 >> +#define RDLH_LINK_UP_MASK_BIT 0x01 >> + >> +#define LTSSM_STATE_L0 0x11 >> + >> +// IRQSEL >> +#define AER_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> +#define PME_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2)) >> +#define LINKAUTOBW_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4)) >> +#define BWMGMT_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8)) >> +#define EQRQST_SET(dst, src) (((dst) & ~0x10) | (((UINT32) (src) << 4) & 0x10)) >> +#define INTPIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00)) >> + >> +// SLOTCAP >> +#define SLOT_HPC_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40)) >> + >> +// SLOT_CAPABILITIES_REG, PCIE_CAP_SLOT_POWER_LIMIT_VALUE bits[14:7] >> +#define SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET(dst, src) \ >> + (((dst) & ~0x7F80) | (((UINT32)(src) << 7) & 0x7F80)) >> + >> +// HOTPLUGSTAT >> +#define PWR_IND_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> +#define ATTEN_IND_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2)) >> +#define PWR_CTRL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4)) >> +#define EML_CTRL_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8)) >> + >> +// IRQENABLE >> +#define LINKUP_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40)) >> + >> +// IRQEVENTSTAT >> +#define BLOCK_INT_MASK BIT4 >> +#define INT_MASK BIT3 >> + >> +// BLOCKEVENTSTAT >> +#define LINKUP_MASK BIT0 >> + >> +// RESET >> +#define DWCPCIE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> +#define RESET_MASK 0x1 >> + >> +// CLOCK >> +#define AXIPIPE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// RAMSDR >> +#define SD_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// >> +// PHY registers >> +// >> +#define RSTCTRL 0x0 >> +#define PHYCTRL 0x4 >> +#define RAMCTRL 0x8 >> +#define RAMSTAT 0xC >> +#define PLLCTRL 0x10 >> +#define PHYLPKCTRL 0x14 >> +#define PHYTERMOFFSET0 0x18 >> +#define PHYTERMOFFSET1 0x1C >> +#define PHYTERMOFFSET2 0x20 >> +#define PHYTERMOFFSET3 0x24 >> +#define RXTERM 0x28 >> +#define PHYDIAGCTRL 0x2C >> + >> +// RSTCTRL >> +#define PHY_RESET_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// PHYCTRL >> +#define PWR_STABLE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// >> +// PCIe config space registers >> +// >> +#define TYPE1_DEV_ID_VEND_ID_REG 0 >> +#define TYPE1_CLASS_CODE_REV_ID_REG 0x8 >> +#define TYPE1_CAP_PTR_REG 0x34 >> +#define SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG 0x18 >> +#define BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3c >> +#define CON_STATUS_REG (PM_CAP + 0x4) >> +#define LINK_CAPABILITIES_REG (PCIE_CAP + 0xc) >> +#define LINK_CONTROL_LINK_STATUS_REG (PCIE_CAP + 0x10) >> +#define SLOT_CAPABILITIES_REG (PCIE_CAP + 0x14) >> +#define DEVICE_CONTROL2_DEVICE_STATUS2_REG (PCIE_CAP + 0x28) >> +#define LINK_CAPABILITIES2_REG (PCIE_CAP + 0x2c) >> +#define LINK_CONTROL2_LINK_STATUS2_REG (PCIE_CAP + 0x30) >> +#define UNCORR_ERR_STATUS_OFF (AER_CAP + 0x4) >> +#define UNCORR_ERR_MASK_OFF (AER_CAP + 0x8) >> +#define RESOURCE_CON_REG_VC0 (VC_CAP + 0x14) >> +#define RESOURCE_CON_REG_VC1 (VC_CAP + 0x20) >> +#define RESOURCE_STATUS_REG_VC1 (VC_CAP + 0x24) >> +#define SD_CONTROL1_REG (RAS_DES_CAP+0xA0) >> +#define CCIX_TP_CAP_TP_HDR2_OFF (CCIX_TP_CAP + 0x8) >> +#define ESM_MNDTRY_RATE_CAP_OFF (CCIX_TP_CAP + 0xc) >> +#define ESM_STAT_OFF (CCIX_TP_CAP + 0x14) >> +#define ESM_CNTL_OFF (CCIX_TP_CAP + 0x18) >> +#define ESM_LN_EQ_CNTL_25G_0_OFF (CCIX_TP_CAP + 0x2c) >> +#define PORT_LINK_CTRL_OFF 0x710 >> +#define FILTER_MASK_2_OFF 0x720 >> +#define GEN2_CTRL_OFF 0x80c >> +#define GEN3_RELATED_OFF 0x890 >> +#define GEN3_EQ_CONTROL_OFF 0x8A8 >> +#define MISC_CONTROL_1_OFF 0x8bc >> +#define AMBA_ERROR_RESPONSE_DEFAULT_OFF 0x8d0 >> +#define AMBA_LINK_TIMEOUT_OFF 0x8d4 >> +#define AMBA_ORDERING_CTRL_OFF 0x8d8 >> +#define DTIM_CTRL0_OFF 0xab0 >> +#define AUX_CLK_FREQ_OFF 0xb40 >> +#define CCIX_CTRL_OFF 0xc20 >> + >> +// TYPE1_DEV_ID_VEND_ID_REG >> +#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF)) >> +#define DEVICE_ID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000)) >> + >> +// TYPE1_CLASS_CODE_REV_ID_REG >> +#define BASE_CLASS_CODE_SET(dst, src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000)) >> +#define SUBCLASS_CODE_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000)) >> +#define PROGRAM_INTERFACE_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00)) >> +#define REVISION_ID_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> + >> +// SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG >> +#define DEFAULT_SUB_BUS 0xFF >> +#define SUB_BUS_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000)) >> +#define SEC_BUS_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00)) >> +#define PRIM_BUS_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> + >> +// BRIDGE_CTRL_INT_PIN_INT_LINE_REG >> +#define INT_PIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00)) >> + >> +// CON_STATUS_REG >> +#define POWER_STATE_SET(dst, src) (((dst) & ~0x3) | (((UINT32) (src)) & 0x3)) >> + >> +// DEVICE_CONTROL2_DEVICE_STATUS2_REG >> +#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF)) >> + >> +// LINK_CAPABILITIES_REG >> +#define CAP_ID 0x10 >> +#define LINK_CAPABILITIES_REG_OFF 0xC >> +#define LINK_CONTROL_LINK_STATUS_OFF 0x10 >> +#define CAP_MAX_LINK_WIDTH_X1 0x1 >> +#define CAP_MAX_LINK_WIDTH_X2 0x2 >> +#define CAP_MAX_LINK_WIDTH_X4 0x4 >> +#define CAP_MAX_LINK_WIDTH_X8 0x8 >> +#define CAP_MAX_LINK_WIDTH_X16 0x10 >> +#define CAP_MAX_LINK_WIDTH_GET(val) ((val & 0x3F0) >> 4) >> +#define CAP_MAX_LINK_WIDTH_SET(dst, src) (((dst) & ~0x3F0) | (((UINT32) (src) << 4) & 0x3F0)) >> +#define MAX_LINK_SPEED_25 0x1 >> +#define MAX_LINK_SPEED_50 0x2 >> +#define MAX_LINK_SPEED_80 0x3 >> +#define MAX_LINK_SPEED_160 0x4 >> +#define MAX_LINK_SPEED_320 0x5 >> +#define CAP_MAX_LINK_SPEED_GET(val) ((val & 0xF)) >> +#define CAP_MAX_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF)) >> +#define CAP_SLOT_CLK_CONFIG_SET(dst, src) (((dst) & ~0x10000000) | (((UINT32) (src) << 28) & 0x10000000)) >> +#define NO_ASPM_SUPPORTED 0x0 >> +#define L0S_SUPPORTED 0x1 >> +#define L1_SUPPORTED 0x2 >> +#define L0S_L1_SUPPORTED 0x3 >> +#define CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET(dst, src) (((dst) & ~0xC00) | (((UINT32)(src) << 10) & 0xC00)) >> + >> +// LINK_CONTROL_LINK_STATUS_REG >> +#define CAP_DLL_ACTIVE_GET(val) ((val & 0x20000000) >> 29) >> +#define CAP_NEGO_LINK_WIDTH_GET(val) ((val & 0x3F00000) >> 20) >> +#define CAP_LINK_SPEED_GET(val) ((val & 0xF0000) >> 16) >> +#define CAP_LINK_SPEED_SET(dst, src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000)) >> +#define CAP_LINK_SPEED_TO_VECTOR(val) (1 << ((val)-1)) >> +#define CAP_EN_CLK_POWER_MAN_GET(val) ((val & 0x100) >> 8) >> +#define CAP_EN_CLK_POWER_MAN_SET(dst, src) (((dst) & ~0x100) | (((UINT32) (src) << 8) & 0x100)) >> +#define CAP_RETRAIN_LINK_SET(dst, src) (((dst) & ~0x20) | (((UINT32) (src) << 5) & 0x20)) >> +#define CAP_COMMON_CLK_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40)) >> +#define CAP_LINK_TRAINING_GET(val) ((val & 0x8000000) >> 27) >> +#define CAP_LINK_DISABLE_SET(dst, src) (((dst) & ~0x10) | (((UINT32)(src) << 4) & 0x10)) >> + >> +// LINK_CONTROL2_LINK_STATUS2_REG >> +#define CAP_TARGET_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF)) >> + >> +// Secondary Capability >> +#define SPCIE_CAP_ID 0x19 >> +#define CAP_OFF_0C 0x0C >> +#define LINK_CONTROL3_REG_OFF 0x4 >> +#define DSP_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF)) >> +#define DSP_TX_PRESET1_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000)) >> + >> +// UNCORR_ERR_MASK_OFF >> +#define CMPLT_TIMEOUT_ERR_MASK_SET(dst, src) (((dst) & ~0x4000) | (((UINT32) (src) << 14) & 0x4000)) >> +#define SDES_ERR_MASK_SET(dst, src) (((dst) & ~0x20) | (((UINT32)(src) << 5) & 0x20)) >> + >> +// PORT_LINK_CTRL_OFF >> +#define LINK_CAPABLE_X1 0x1 >> +#define LINK_CAPABLE_X2 0x3 >> +#define LINK_CAPABLE_X4 0x7 >> +#define LINK_CAPABLE_X8 0xF >> +#define LINK_CAPABLE_X16 0x1F >> +#define LINK_CAPABLE_X32 0x3F >> +#define LINK_CAPABLE_SET(dst, src) (((dst) & ~0x3F0000) | (((UINT32) (src) << 16) & 0x3F0000)) >> +#define FAST_LINK_MODE_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80)) >> + >> +// FILTER_MASK_2_OFF >> +#define CX_FLT_MASK_VENMSG0_DROP_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> +#define CX_FLT_MASK_VENMSG1_DROP_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2)) >> +#define CX_FLT_MASK_DABORT_4UCPL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4)) >> + >> +// GEN2_CTRL_OFF >> +#define NUM_OF_LANES_X2 0x2 >> +#define NUM_OF_LANES_X4 0x4 >> +#define NUM_OF_LANES_X8 0x8 >> +#define NUM_OF_LANES_X16 0x10 >> +#define NUM_OF_LANES_SET(dst, src) (((dst) & ~0x1F00) | (((UINT32) (src) << 8) & 0x1F00)) >> + >> +// GEN3_RELATED_OFF >> +#define RATE_SHADOW_SEL_SET(dst, src) (((dst) & ~0x3000000) | (((UINT32) (src) << 24) & 0x3000000)) >> +#define EQ_PHASE_2_3_SET(dst, src) (((dst) & ~0x200) | (((UINT32) (src) << 9) & 0x200)) >> +#define RXEQ_REGRDLESS_SET(dst, src) (((dst) & ~0x2000) | (((UINT32) (src) << 13) & 0x2000)) >> + >> +// GEN3_EQ_CONTROL_OFF >> +#define GEN3_EQ_FB_MODE(dst, src) (((dst) & ~0xF) | ((UINT32) (src) & 0xF)) >> +#define GEN3_EQ_PRESET_VEC(dst, src) (((dst) & 0xFF0000FF) | (((UINT32) (src) << 8) & 0xFFFF00)) >> +#define GEN3_EQ_INIT_EVAL(dst,src) (((dst) & ~0x1000000) | (((UINT32) (src) << 24) & 0x1000000)) >> + >> +// MISC_CONTROL_1_OFF >> +#define DBI_RO_WR_EN_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// AMBA_ERROR_RESPONSE_DEFAULT_OFF >> +#define AMBA_ERROR_RESPONSE_CRS_SET(dst, src) (((dst) & ~0x18) | (((UINT32) (src) << 3) & 0x18)) >> +#define AMBA_ERROR_RESPONSE_GLOBAL_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1)) >> + >> +// AMBA_LINK_TIMEOUT_OFF >> +#define LINK_TIMEOUT_PERIOD_DEFAULT_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF)) >> + >> +// AMBA_ORDERING_CTRL_OFF >> +#define AX_MSTR_ZEROLREAD_FW_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80)) >> + >> +// DTIM_CTRL0_OFF >> +#define DTIM_CTRL0_ROOT_PORT_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF)) >> + >> +// AUX_CLK_FREQ_OFF >> +#define AUX_CLK_500MHZ 500 >> +#define AUX_CLK_FREQ_SET(dst, src) (((dst) & ~0x1FF) | (((UINT32) (src)) & 0x1FF)) >> + >> +#define EXT_CAP_OFFSET_START 0x100 >> + >> +// EVENT_COUNTER_CONTROL_REG >> +#define ECCR_GROUP_EVENT_SEL_SET(dst, src) (((dst) & ~0xFFF0000) | (((UINT32)(src) << 16) & 0xFFF0000)) >> +#define ECCR_GROUP_SEL_SET(dst, src) (((dst) & ~0xF000000) | (((UINT32)(src) << 24) & 0xF000000)) >> +#define ECCR_EVENT_SEL_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32)(src) << 16) & 0xFF0000)) >> +#define ECCR_LANE_SEL_SET(dst, src) (((dst) & ~0xF00) | (((UINT32)(src) << 8) & 0xF00)) >> +#define ECCR_EVENT_COUNTER_ENABLE_SET(dst, src) (((dst) & ~0x1C) | (((UINT32)(src) << 2) & 0x1C)) >> +#define ECCR_EVENT_COUNTER_CLEAR_SET(dst, src) (((dst) & ~0x3) | (((UINT32)(src)) & 0x3)) >> + >> +// PFA Registers offests >> +#define RAS_DES_CAP_ID 0xB >> +#define EVENT_COUNTER_CONTROL_REG_OFF 0x8 >> +#define EVENT_COUNTER_DATA_REG_OFF 0xC >> + >> +#define MAX_NUM_ERROR_CODE 47 >> + >> +#endif /* AC01_PCIE_CORE_H_ */ >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c >> new file mode 100644 >> index 000000000000..c546ee8330b9 >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c >> @@ -0,0 +1,1391 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + 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, > IsRootComplex. > >> + IN UINT16 ExtendedCapId >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + UINT32 Val = 0, NextCap = 0, CapId = 0, ExCap = 0; > NextCap is clear...ish, CapId likewise. ExCap is not. Please give it a > proper name. > >> + >> + if (IsRC) { >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + } else { >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 20); > Please, some macros for those live integers. > >> + } >> + >> + Val = MmioRead32 (CfgAddr + TYPE1_CAP_PTR_REG); >> + NextCap = Val & 0xFF; > Macro. > >> + >> + // Loop untill desired capability is found else return 0 >> + while (1) { >> + if ((NextCap & 0x3) != 0) { > Macro. > >> + // Not alignment, just return >> + return 0; >> + } >> + Val = MmioRead32 (CfgAddr + NextCap); >> + if (NextCap < EXT_CAP_OFFSET_START) { >> + CapId = Val & 0xFF; > Macro. > >> + } else { >> + CapId = Val & 0xFFFF; > Macro. > (OK, I'll stop here - but please excise every single instance of a > live-coded integer, with the potential exception of 0, from .c files.) > >> + } >> + >> + if (CapId == ExtendedCapId) { >> + return (UINT64)(CfgAddr + NextCap); >> + } >> + >> + if (NextCap < EXT_CAP_OFFSET_START) { >> + NextCap = (Val & 0xFFFF) >> 8; >> + } else { >> + NextCap = (Val & 0xFFFF0000) >> 20; >> + } >> + >> + if ((NextCap == 0) && (ExCap == 0)) { >> + ExCap = 1; >> + NextCap = EXT_CAP_OFFSET_START; >> + } >> + >> + if ((NextCap == 0) && (ExCap == 1)) { >> + return (UINT64)0; >> + } >> + } >> +} >> + >> +/** >> + Configure equalization settings >> + >> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex PCIe index >> +**/ >> +STATIC >> +VOID >> +ConfigureEqualization ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + UINT32 Val; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Select the FoM method, need double-write to convey settings >> + Val = MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF); >> + Val = GEN3_EQ_FB_MODE (Val, 0x1); >> + Val = GEN3_EQ_PRESET_VEC (Val, 0x3FF); >> + Val = GEN3_EQ_INIT_EVAL (Val, 0x1); > The double-write part of the above comment should be moved here, and > improved. Explain why the double-write is needed. > >> + MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val); >> + MmioWrite32 (CfgAddr + GEN3_EQ_CONTROL_OFF, Val); >> + Val = MmioRead32 (CfgAddr + GEN3_EQ_CONTROL_OFF); > This function retrieves CfgAddr once and gives it a variable. > It then performs four accesses to same offset from that address, > and writes out the arithmetic on each instance. > This is not the balance I would have chosen. > >> +} >> + >> +/** >> + Configure presets for GEN3 equalization >> + >> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex PCIe index >> +**/ >> +STATIC >> +VOID >> +ConfigurePresetGen3 ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr, SpcieBaseAddr; >> + UINT32 Val, Idx; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Bring to legacy mode >> + Val = MmioRead32 (CfgAddr + GEN3_RELATED_OFF); >> + Val = RATE_SHADOW_SEL_SET (Val, 0); >> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val); >> + Val = EQ_PHASE_2_3_SET (Val, 0); >> + Val = RXEQ_REGRDLESS_SET (Val, 1); >> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val); > Same pattern again - a series of accesses to the same offset register, > writing out the offset every time instead of assigning it to a variable. > >> + >> + // Generate SPCIE capability address > What's an SPCIE? > >> + SpcieBaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_ID); >> + if (SpcieBaseAddr == 0) { >> + DEBUG (( >> + DEBUG_ERROR, >> + "PCIE%d.%d: Cannot get SPCIE capability address\n", >> + RootComplex->ID, >> + PcieIndex >> + )); >> + return; >> + } >> + >> + for (Idx=0; Idx < RootComplex->Pcie[PcieIndex].MaxWidth/2; Idx++) { > What's with the 2? > >> + // Program Preset to Gen3 EQ Lane Control >> + Val = MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4); > (Idx * 4) or (Idx * sizeof (UINT32))? > >> + Val = DSP_TX_PRESET0_SET (Val, 0x7); >> + Val = DSP_TX_PRESET1_SET (Val, 0x7); >> + MmioWrite32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4, Val); > Only two addresses to the same offset, but would still be clearer > assigned to a variable. > >> + } >> +} >> + >> +/** >> + Configure presets for GEN4 equalization >> + >> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex PCIe controller index >> +**/ >> +STATIC >> +VOID >> +ConfigurePresetGen4 ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr, SpcieBaseAddr, Pl16BaseAddr; >> + UINT32 LinkWidth, Idx; >> + UINT32 Val; >> + UINT8 Preset; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Bring to legacy mode >> + Val = MmioRead32 (CfgAddr + GEN3_RELATED_OFF); >> + Val = RATE_SHADOW_SEL_SET (Val, 1); >> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val); >> + Val = EQ_PHASE_2_3_SET (Val, 0); >> + Val = RXEQ_REGRDLESS_SET (Val, 1); >> + MmioWrite32 (CfgAddr + GEN3_RELATED_OFF, Val); > OK, last time I'm commenting on this as well - please go through and > replace Address + OFFSET with a temporary variable wherever more than > one access to the same offset register is made in sequence. > > It doesn't even need to be an additional variable unless you need to > access multiple offset registers from the same base in the same > function - you could do something like > > RegAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15) > + GEN3_RELATED_OFF; > > (although obviously not with a live-coded 15) > >> + >> + // Generate the PL16 capability address >> + Pl16BaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, PL16_CAP_ID); >> + if (Pl16BaseAddr == 0) { >> + DEBUG (( >> + DEBUG_ERROR, >> + "PCIE%d.%d: Cannot get PL16 capability address\n", >> + RootComplex->ID, >> + PcieIndex >> + )); >> + return; >> + } >> + >> + // Generate the SPCIE capability address >> + SpcieBaseAddr = PcieCheckCap (RootComplex, PcieIndex, TRUE, SPCIE_CAP_ID); >> + if (SpcieBaseAddr == 0) { >> + DEBUG (( >> + DEBUG_ERROR, >> + "PCIE%d.%d: Cannot get SPICE capability address\n", >> + RootComplex->ID, >> + PcieIndex >> + )); >> + return; >> + } >> + >> + // Configure downstream Gen4 Tx preset >> + if (RootComplex->PresetGen4[PcieIndex] == PRESET_INVALID) { >> + Preset = 0x57; // Default Gen4 preset >> + } else { >> + Preset = RootComplex->PresetGen4[PcieIndex]; >> + } >> + >> + LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth; >> + if (LinkWidth == 0x2) { >> + Val = MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF); >> + Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset); >> + Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset); >> + MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF, Val); >> + } else { >> + for (Idx = 0; Idx < LinkWidth/4; Idx++) { >> + Val = MmioRead32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4); >> + Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset); >> + Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset); >> + Val = DSP_16G_RXTX_PRESET2_SET (Val, Preset); >> + Val = DSP_16G_RXTX_PRESET3_SET (Val, Preset); >> + MmioWrite32 (Pl16BaseAddr + PL16G_CAP_OFF_20H_REG_OFF + Idx*4, Val); >> + } >> + } >> + >> + // Configure Gen3 preset >> + for (Idx = 0; Idx < LinkWidth/2; Idx++) { >> + Val = MmioRead32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4); >> + Val = DSP_TX_PRESET0_SET (Val, 0x7); >> + Val = DSP_TX_PRESET1_SET (Val, 0x7); >> + MmioWrite32 (SpcieBaseAddr + CAP_OFF_0C + Idx*4, Val); >> + } >> +} >> + >> +INT8 >> +RasdpMitigation ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr, DlinkBaseAddr, SnpsRamBase; >> + PLATFORM_INFO_HOB *PlatformHob; >> + UINT16 NextExtendedCapabilityOff; >> + UINT32 Val; >> + UINT32 VsecVal; >> + VOID *Hob; >> + >> + SnpsRamBase = RootComplex->Pcie[PcieIndex].SnpsRamBase; >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + Hob = GetFirstGuidHob (&gPlatformInfoHobGuid); >> + PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob); >> + if ((PlatformHob->ScuProductId[0] & 0xff) == 0x01 >> + && AsciiStrCmp ((CONST CHAR8 *)PlatformHob->CpuVer, "A0") == 0 >> + && (RootComplex->Type == RootComplexTypeB || PcieIndex > 0)) { >> + // Change the Read Margin dual ported RAMs >> + Val = 0x10; // Margin to 0x0 (most conservative setting) >> + MmioWrite32 (SnpsRamBase + TPSRAM_RMR, Val); >> + >> + // Generate the DLINK capability address >> + DlinkBaseAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + NextExtendedCapabilityOff = 0x100; // This is the 1st extended capability offset >> + do { >> + Val = MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff); >> + if (Val == 0xFFFFFFFF) { >> + DlinkBaseAddr = 0x0; >> + break; >> + } >> + if ((Val & 0xFFFF) == DLINK_VENDOR_CAP_ID) { >> + VsecVal = MmioRead32 (DlinkBaseAddr + NextExtendedCapabilityOff + 0x4); >> + if (VsecVal == DLINK_VSEC) { >> + DlinkBaseAddr = DlinkBaseAddr + NextExtendedCapabilityOff; >> + break; >> + } >> + } >> + NextExtendedCapabilityOff = (Val >> 20); >> + } while (NextExtendedCapabilityOff != 0); >> + >> + // Disable the scaled credit mode >> + if (DlinkBaseAddr != 0x0) { >> + Val = 1; >> + MmioWrite32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF, Val); >> + Val = MmioRead32 (DlinkBaseAddr + DATA_LINK_FEATURE_CAP_OFF); >> + if (Val != 1) { >> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Unable to disable scaled credit\n", PcieIndex)); >> + return -1; >> + } >> + } else { >> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Unable to locate data link feature cap offset\n", PcieIndex)); >> + return -1; >> + } >> + >> + // Reduce Posted Credits to 1 packet header and data credit for all >> + // impacted controllers. Also zero credit scale values for both >> + // data and packet headers. >> + Val=0x40201020; >> + MmioWrite32 (CfgAddr + PORT_LOCIG_VC0_P_RX_Q_CTRL_OFF, Val); >> + } >> + >> + return 0; >> +} >> + >> +VOID >> +ProgramHostBridge ( >> + AC01_ROOT_COMPLEX *RootComplex >> + ) >> +{ >> + UINT32 Val; >> + >> + // Program Root Complex Bifurcation >> + if (RootComplex->Active) { >> + if (RootComplex->Type == RootComplexTypeA) { >> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCAPDMR, &Val))) { >> + Val = RCAPCIDEVMAP_SET (Val, RootComplex->DevMapLow); >> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCAPDMR, Val); >> + } >> + } else { >> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCBPDMR, &Val))) { >> + Val = RCBPCIDEVMAPLO_SET (Val, RootComplex->DevMapLow); >> + Val = RCBPCIDEVMAPHI_SET (Val, RootComplex->DevMapHigh); >> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBRCBPDMR, Val); >> + } >> + } >> + } >> + >> + // Program VendorID and DeviceId >> + if (!EFI_ERROR (MailboxMsgRegisterRead (RootComplex->Socket, RootComplex->HostBridgeBase + HBPDVIDR, &Val))) { >> + Val = PCIVENDID_SET (Val, AMPERE_PCIE_VENDORID); >> + if (RootComplexTypeA == RootComplex->Type) { >> + Val = PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCA); >> + } else { >> + Val = PCIDEVID_SET (Val, AC01_HOST_BRIDGE_DEVICEID_RCB); >> + } >> + MailboxMsgRegisterWrite (RootComplex->Socket, RootComplex->HostBridgeBase + HBPDVIDR, Val); >> + } >> +} >> + >> +VOID >> +ProgramLinkCapabilities ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + UINT32 Val; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + Val = MmioRead32 (CfgAddr + PORT_LINK_CTRL_OFF); >> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) { >> + case LINK_WIDTH_X2: >> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X2); >> + break; >> + >> + case LINK_WIDTH_X4: >> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X4); >> + break; >> + >> + case LINK_WIDTH_X8: >> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X8); >> + break; >> + >> + case LINK_WIDTH_X16: >> + default: >> + Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X16); >> + break; >> + } >> + MmioWrite32 (CfgAddr + PORT_LINK_CTRL_OFF, Val); >> + Val = MmioRead32 (CfgAddr + GEN2_CTRL_OFF); >> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) { >> + case LINK_WIDTH_X2: >> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X2); >> + break; >> + >> + case LINK_WIDTH_X4: >> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X4); >> + break; >> + >> + case LINK_WIDTH_X8: >> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X8); >> + break; >> + >> + case LINK_WIDTH_X16: >> + default: >> + Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X16); >> + break; >> + } >> + MmioWrite32 (CfgAddr + GEN2_CTRL_OFF, Val); >> + Val = MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG); >> + switch (RootComplex->Pcie[PcieIndex].MaxWidth) { >> + case LINK_WIDTH_X2: >> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X2); >> + break; >> + >> + case LINK_WIDTH_X4: >> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X4); >> + break; >> + >> + case LINK_WIDTH_X8: >> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X8); >> + break; >> + >> + case LINK_WIDTH_X16: >> + default: >> + Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X16); >> + break; >> + } >> + >> + switch (RootComplex->Pcie[PcieIndex].MaxGen) { >> + case LINK_SPEED_GEN1: >> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25); >> + break; >> + >> + case LINK_SPEED_GEN2: >> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50); >> + break; >> + >> + case LINK_SPEED_GEN3: >> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80); >> + break; >> + >> + default: >> + Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160); >> + break; >> + } >> + /* Enable ASPM Capability */ >> + Val = CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET (Val, L0S_L1_SUPPORTED); >> + MmioWrite32 (CfgAddr + LINK_CAPABILITIES_REG, Val); >> + >> + Val = MmioRead32 (CfgAddr + LINK_CONTROL2_LINK_STATUS2_REG); >> + switch (RootComplex->Pcie[PcieIndex].MaxGen) { >> + case LINK_SPEED_GEN1: >> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25); >> + break; >> + >> + case LINK_SPEED_GEN2: >> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50); >> + break; >> + >> + case LINK_SPEED_GEN3: >> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80); >> + break; >> + >> + default: >> + Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160); >> + break; >> + } >> + MmioWrite32 (CfgAddr + LINK_CONTROL2_LINK_STATUS2_REG, Val); >> +} >> + >> +VOID >> +MaskCompletionTimeOut ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN UINT32 TimeOut, >> + IN BOOLEAN IsMask >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + UINT32 Val; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + Val = MmioRead32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF); >> + Val = LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, TimeOut); >> + MmioWrite32 (CfgAddr + AMBA_LINK_TIMEOUT_OFF, Val); >> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF); >> + Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0); >> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val); >> +} >> + >> +BOOLEAN >> +PollMemReady ( >> + PHYSICAL_ADDRESS CsrBase >> + ) >> +{ >> + UINT32 TimeOut; >> + UINT32 Val; >> + >> + // Poll till mem is ready > What mem? > > / > Leif > >> + TimeOut = MEMRDY_TIMEOUT; >> + do { >> + Val = MmioRead32 (CsrBase + MEMRDYR); >> + if (Val & 1) { >> + break; >> + } >> + >> + TimeOut--; >> + MicroSecondDelay (1); >> + } while (TimeOut > 0); >> + >> + if (TimeOut <= 0) { >> + return FALSE; >> + } >> + >> + return TRUE; >> +} >> + >> +BOOLEAN >> +PollPipeReady ( >> + PHYSICAL_ADDRESS CsrBase >> + ) >> +{ >> + UINT32 TimeOut; >> + UINT32 Val; >> + >> + // Poll till PIPE clock is stable >> + TimeOut = PIPE_CLOCK_TIMEOUT; >> + do { >> + Val = MmioRead32 (CsrBase + LINKSTAT); >> + if (!(Val & PHY_STATUS_MASK)) { >> + break; >> + } >> + >> + TimeOut--; >> + MicroSecondDelay (1); >> + } while (TimeOut > 0); >> + >> + if (TimeOut <= 0) { >> + return FALSE; >> + } >> + >> + return TRUE; >> +} >> + >> +/** >> + Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers >> + >> + @param RootComplex Pointer to Root Complex structure >> + @param ReInit Re-init status >> + @param ReInitPcieIndex PCIe index >> + >> + @retval RETURN_SUCCESS The Root Complex has been initialized successfully. >> + @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready. >> +**/ >> +RETURN_STATUS >> +Ac01PcieCoreSetupRC ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN BOOLEAN ReInit, >> + IN UINT8 ReInitPcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS CsrBase, CfgAddr; >> + RETURN_STATUS Status; >> + UINT32 Val; >> + UINT8 PcieIndex; >> + >> + DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex->Socket, RootComplex->ID)); >> + >> + ProgramHostBridge (RootComplex); >> + >> + if (!ReInit) { >> + // Initialize PHY >> + Status = PciePhyInit (RootComplex->SerdesBase); >> + if (RETURN_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a: Failed to initialize the PCIe PHY\n", __FUNCTION__)); >> + return RETURN_DEVICE_ERROR; >> + } >> + } >> + >> + // Setup each controller >> + for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) { >> + >> + if (ReInit) { >> + PcieIndex = ReInitPcieIndex; >> + } >> + >> + if (!RootComplex->Pcie[PcieIndex].Active) { >> + continue; >> + } >> + >> + DEBUG ((DEBUG_INFO, "Initializing Controller %d\n", PcieIndex)); >> + >> + CsrBase = RootComplex->Pcie[PcieIndex].CsrBase; >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Put Controller into reset if not in reset already >> + Val = MmioRead32 (CsrBase + RESET); >> + if (!(Val & RESET_MASK)) { >> + Val = DWCPCIE_SET (Val, 1); >> + MmioWrite32 (CsrBase + RESET, Val); >> + >> + // Delay 50ms to ensure controller finish its reset >> + MicroSecondDelay (50000); >> + } >> + >> + // Clear memory shutdown >> + Val = MmioRead32 (CsrBase + RAMSDR); >> + Val = SD_SET (Val, 0); >> + MmioWrite32 (CsrBase + RAMSDR, Val); >> + >> + if (!PollMemReady (CsrBase)) { >> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - Mem not ready\n", PcieIndex)); >> + return RETURN_DEVICE_ERROR; >> + } >> + >> + // Hold link training >> + Val = MmioRead32 (CsrBase + LINKCTRL); >> + Val = LTSSMENB_SET (Val, 0); >> + MmioWrite32 (CsrBase + LINKCTRL, Val); >> + >> + // Enable subsystem clock and release reset >> + Val = MmioRead32 (CsrBase + CLOCK); >> + Val = AXIPIPE_SET (Val, 1); >> + MmioWrite32 (CsrBase + CLOCK, Val); >> + Val = MmioRead32 (CsrBase + RESET); >> + Val = DWCPCIE_SET (Val, 0); >> + MmioWrite32 (CsrBase + RESET, Val); >> + >> + // >> + // Controller does not provide any indicator for reset released. >> + // Must wait at least 1us as per EAS. >> + // >> + MicroSecondDelay (1); >> + >> + if (!PollPipeReady (CsrBase)) { >> + DEBUG ((DEBUG_ERROR, "- Pcie[%d] - PIPE clock is not stable\n", PcieIndex)); >> + return RETURN_DEVICE_ERROR; >> + } >> + >> + // Start PERST pulse >> + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE); >> + >> + // Allow programming to config space >> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 1); >> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val); >> + >> + // In order to detect the NVMe disk for booting without disk, >> + // need to set Hot-Plug Slot Capable during port initialization. >> + // It will help PCI Linux driver to initialize its slot iomem resource, >> + // the one is used for detecting the disk when it is inserted. >> + Val = MmioRead32 (CfgAddr + SLOT_CAPABILITIES_REG); >> + Val = SLOT_HPC_SET (Val, 1); >> + // Program the power limit >> + Val = SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT); >> + MmioWrite32 (CfgAddr + SLOT_CAPABILITIES_REG, Val); >> + >> + // Apply RASDP error mitigation for all x8, x4, and x2 controllers >> + // This includes all RootComplexTypeB root ports, and every RootComplexTypeA root port controller >> + // except for index 0 (i.e. x16 controllers are exempted from this WA) >> + RasdpMitigation (RootComplex, PcieIndex); >> + >> + // Program DTI for ATS support >> + Val = MmioRead32 (CfgAddr + DTIM_CTRL0_OFF); >> + Val = DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0); >> + MmioWrite32 (CfgAddr + DTIM_CTRL0_OFF, Val); >> + >> + // >> + // Program number of lanes used >> + // - Reprogram LINK_CAPABLE of PORT_LINK_CTRL_OFF >> + // - Reprogram NUM_OF_LANES of GEN2_CTRL_OFF >> + // - Reprogram CAP_MAX_LINK_WIDTH of LINK_CAPABILITIES_REG >> + // >> + ProgramLinkCapabilities (RootComplex, PcieIndex); >> + >> + // Set Zero byte request handling >> + Val = MmioRead32 (CfgAddr + FILTER_MASK_2_OFF); >> + Val = CX_FLT_MASK_VENMSG0_DROP_SET (Val, 0); >> + Val = CX_FLT_MASK_VENMSG1_DROP_SET (Val, 0); >> + Val = CX_FLT_MASK_DABORT_4UCPL_SET (Val, 0); >> + MmioWrite32 (CfgAddr + FILTER_MASK_2_OFF, Val); >> + Val = MmioRead32 (CfgAddr + AMBA_ORDERING_CTRL_OFF); >> + Val = AX_MSTR_ZEROLREAD_FW_SET (Val, 0); >> + MmioWrite32 (CfgAddr + AMBA_ORDERING_CTRL_OFF, Val); >> + >> + // >> + // Set Completion with CRS handling for CFG Request >> + // Set Completion with CA/UR handling non-CFG Request >> + // >> + Val = MmioRead32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF); >> + Val = AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2); >> + MmioWrite32 (CfgAddr + AMBA_ERROR_RESPONSE_DEFAULT_OFF, Val); >> + >> + // Set Legacy PCIE interrupt map to INTA >> + Val = MmioRead32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG); >> + Val = INT_PIN_SET (Val, 1); >> + MmioWrite32 (CfgAddr + BRIDGE_CTRL_INT_PIN_INT_LINE_REG, Val); >> + Val = MmioRead32 (CsrBase + IRQSEL); >> + Val = INTPIN_SET (Val, 1); >> + MmioWrite32 (CsrBase + IRQSEL, Val); >> + >> + if (RootComplex->Pcie[PcieIndex].MaxGen != LINK_SPEED_GEN1) { >> + ConfigureEqualization (RootComplex, PcieIndex); >> + if (RootComplex->Pcie[PcieIndex].MaxGen == LINK_SPEED_GEN3) { >> + ConfigurePresetGen3 (RootComplex, PcieIndex); >> + } else if (RootComplex->Pcie[PcieIndex].MaxGen == LINK_SPEED_GEN4) { >> + ConfigurePresetGen4 (RootComplex, PcieIndex); >> + } >> + } >> + >> + // Mask Completion Timeout >> + MaskCompletionTimeOut (RootComplex, PcieIndex, 1, TRUE); >> + >> + // AER surprise link down error should be masked due to hotplug is enabled >> + // This event must be handled by Hotplug handler, instead of error handler >> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF); >> + Val = SDES_ERR_MASK_SET (Val, 1); >> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val); >> + >> + // Program Class Code >> + Val = MmioRead32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG); >> + Val = REVISION_ID_SET (Val, 4); >> + Val = SUBCLASS_CODE_SET (Val, 4); >> + Val = BASE_CLASS_CODE_SET (Val, 6); >> + MmioWrite32 (CfgAddr + TYPE1_CLASS_CODE_REV_ID_REG, Val); >> + >> + // Program VendorID and DeviceID >> + Val = MmioRead32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG); >> + Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDORID); >> + if (RootComplexTypeA == RootComplex->Type) { >> + Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCA + PcieIndex); >> + } else { >> + Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICEID_RCB + PcieIndex); >> + } >> + MmioWrite32 (CfgAddr + TYPE1_DEV_ID_VEND_ID_REG, Val); >> + >> + // Enable common clock for downstream >> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG); >> + Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1); >> + Val = CAP_COMMON_CLK_SET (Val, 1); >> + MmioWrite32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG, Val); >> + >> + // Match aux_clk to system >> + Val = MmioRead32 (CfgAddr + AUX_CLK_FREQ_OFF); >> + Val = AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ); >> + MmioWrite32 (CfgAddr + AUX_CLK_FREQ_OFF, Val); >> + >> + // Assert PERST low to reset endpoint >> + BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE); >> + >> + // Start link training >> + Val = MmioRead32 (CsrBase + LINKCTRL); >> + Val = LTSSMENB_SET (Val, 1); >> + MmioWrite32 (CsrBase + LINKCTRL, Val); >> + >> + // Complete the PERST pulse >> + BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE); >> + >> + // Lock programming of config space >> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 0); >> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val); >> + >> + if (ReInit) { >> + return RETURN_SUCCESS; >> + } >> + } >> + >> + return RETURN_SUCCESS; >> +} >> + >> +BOOLEAN >> +PcieLinkUpCheck ( >> + IN AC01_PCIE_CONTROLLER *Pcie >> + ) >> +{ >> + PHYSICAL_ADDRESS CsrBase; >> + UINT32 BlockEvent; >> + UINT32 LinkStat; >> + >> + CsrBase = Pcie->CsrBase; >> + >> + // Check if card present >> + // smlh_ltssm_state[13:8] = 0 >> + // phy_status[2] = 0 >> + // smlh_link_up[1] = 0 >> + // rdlh_link_up[0] = 0 >> + LinkStat = MmioRead32 (CsrBase + LINKSTAT); >> + LinkStat = LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT | >> + SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT); >> + if (LinkStat == 0x0000) { >> + return FALSE; >> + } >> + >> + BlockEvent = MmioRead32 (CsrBase + BLOCKEVENTSTAT); >> + LinkStat = MmioRead32 (CsrBase + LINKSTAT); >> + >> + if (((BlockEvent & LINKUP_MASK) != 0) >> + && (SMLH_LTSSM_STATE_GET(LinkStat) == LTSSM_STATE_L0)) >> + { >> + DEBUG ((DEBUG_INFO, "%a Linkup\n", __FUNCTION__)); >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Callback function when the Host Bridge enumeration end. >> + >> + @param RootComplex Pointer to the Root Complex structure >> +**/ >> +VOID >> +Ac01PcieCoreEndEnumeration ( >> + IN AC01_ROOT_COMPLEX *RootComplex >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + PHYSICAL_ADDRESS Reg; >> + UINT32 Val; >> + UINTN Index; >> + >> + if (RootComplex == NULL || !RootComplex->Active) { >> + return; >> + } >> + >> + // Clear uncorrectable error during enumuration phase. Mainly completion timeout. >> + for (Index = 0; Index < RootComplex->MaxPcieController; Index++) { >> + if (!RootComplex->Pcie[Index].Active) { >> + continue; >> + } >> + if (!PcieLinkUpCheck(&RootComplex->Pcie[Index])) { >> + // If link down/disabled after enumeration, disable completed time out >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[Index].DevNum << 15); >> + Val = MmioRead32 (CfgAddr + UNCORR_ERR_MASK_OFF); >> + Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, 1); >> + MmioWrite32 (CfgAddr + UNCORR_ERR_MASK_OFF, Val); >> + } >> + // Clear all errors >> + Reg = RootComplex->MmcfgBase + ((Index + 1) << 15) + UNCORR_ERR_STATUS_OFF; >> + Val = MmioRead32 (Reg); >> + if (Val != 0) { >> + // Clear error by writting >> + MmioWrite32 (Reg, Val); >> + } >> + } >> +} >> + >> +/** >> + Comparing current link status with the max capabilities of the link >> + >> + @param RootComplex Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex PCIe index >> + @param EpMaxWidth EP max link width >> + @param EpMaxGen EP max link speed >> + >> + @retval -1: Link status do not match with link max capabilities >> + 1: Link capabilites are invalid >> + 0: Link status are correct >> +**/ >> +INT32 >> +Ac01PcieCoreLinkCheck ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN UINT8 EpMaxWidth, >> + IN UINT8 EpMaxGen >> + ) >> +{ >> + PHYSICAL_ADDRESS CsrBase, CfgAddr; >> + UINT32 Val, LinkStat; >> + UINT32 MaxWidth, MaxGen; >> + >> + CsrBase = RootComplex->Pcie[PcieIndex].CsrBase; >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + Val = MmioRead32 (CfgAddr + LINK_CAPABILITIES_REG); >> + if ((CAP_MAX_LINK_WIDTH_GET (Val) == 0) || >> + (CAP_MAX_LINK_SPEED_GET (Val) == 0)) { >> + DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong RootComplex capabilities\n", RootComplex->ID, PcieIndex)); >> + return LINK_CHECK_WRONG_PARAMETER; >> + } >> + >> + if ((EpMaxWidth == 0) || (EpMaxGen == 0)) { >> + DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong EP capabilities\n", RootComplex->ID, PcieIndex)); >> + return LINK_CHECK_FAILED; >> + } >> + >> + // Compare RootComplex and EP capabilities >> + if (CAP_MAX_LINK_WIDTH_GET (Val) > EpMaxWidth) { >> + MaxWidth = EpMaxWidth; >> + } else { >> + MaxWidth = CAP_MAX_LINK_WIDTH_GET (Val); >> + } >> + >> + // Compare RootComplex and EP capabilities >> + if (CAP_MAX_LINK_SPEED_GET (Val) > EpMaxGen) { >> + MaxGen = EpMaxGen; >> + } else { >> + MaxGen = CAP_MAX_LINK_SPEED_GET (Val); >> + } >> + >> + LinkStat = MmioRead32 (CsrBase + LINKSTAT); >> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE%d.%d: Link MaxWidth %d MaxGen %d, LINKSTAT 0x%x", >> + RootComplex->ID, >> + PcieIndex, >> + MaxWidth, >> + MaxGen, >> + LinkStat >> + )); >> + >> + // Checking all conditions of the link >> + // If one of them is not sastified, return link up fail >> + if ((CAP_NEGO_LINK_WIDTH_GET (Val) != MaxWidth) || >> + (CAP_LINK_SPEED_GET (Val) != MaxGen) || >> + (RDLH_SMLH_LINKUP_STATUS_GET (LinkStat) != (SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT))) >> + { >> + DEBUG ((DEBUG_INFO, "\tLinkCheck FAILED\n")); >> + return LINK_CHECK_FAILED; >> + } >> + >> + DEBUG ((DEBUG_INFO, "\tLinkCheck SUCCESS\n")); >> + return LINK_CHECK_SUCCESS; >> +} >> + >> +INT32 >> +PFACounterRead ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN UINT64 RasDesVSecBase >> + ) >> +{ >> + INT32 Ret = LINK_CHECK_SUCCESS; >> + UINT32 Val; >> + UINT8 ErrCode, ErrGrpNum; >> + >> + UINT32 ErrCtrlCfg[MAX_NUM_ERROR_CODE] = { >> + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, // Per Lane >> + 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, >> + 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, >> + 0x300, 0x301, 0x302, 0x303, 0x304, 0x305, >> + 0x400, 0x401, // Per Lane >> + 0x500, 0x501, 0x502, 0x503, 0x504, 0x505, 0x506, 0x507, 0x508, 0x509, 0x50A, 0x50B, 0x50C, 0x50D >> + }; >> + >> + for (ErrCode = 0; ErrCode < MAX_NUM_ERROR_CODE; ErrCode++) { >> + ErrGrpNum = (ErrCtrlCfg[ErrCode] & 0xF00) >> 8; >> + // Skipping per lane group >> + // Checking common lane group because AER error are included in common group only >> + if ((ErrGrpNum != 0) && (ErrGrpNum != 4)) { >> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF); >> + if (RootComplex->Type == RootComplexTypeA) { >> + // RootComplexTypeA - 4 PCIe controller per port, 1 controller in charge of 4 lanes >> + Val = ECCR_LANE_SEL_SET (Val, PcieIndex*4); >> + } else { >> + // RootComplexTypeB - 8 PCIe controller per port, 1 controller in charge of 2 lanes >> + Val = ECCR_LANE_SEL_SET (Val, PcieIndex*2); >> + } >> + Val = ECCR_GROUP_EVENT_SEL_SET (Val, ErrCtrlCfg[ErrCode]); >> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val); >> + >> + // After setting Counter Control reg >> + // This delay just to make sure Counter Data reg is update with new value >> + MicroSecondDelay (1); >> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_DATA_REG_OFF); >> + if (Val != 0) { >> + Ret = LINK_CHECK_FAILED; >> + DEBUG (( >> + DEBUG_ERROR, >> + "\tSocket%d RootComplex%d RP%d \t%s: %d \tGROUP:%d-EVENT:%d\n", >> + RootComplex->Socket, >> + RootComplex->ID, >> + PcieIndex, >> + Val, >> + ((ErrCtrlCfg[ErrCode] & 0xF00) >> 8), // Group >> + (ErrCtrlCfg[ErrCode] & 0x0FF) // Event >> + )); >> + } >> + } >> + } >> + >> + return Ret; >> +} >> + >> +INT32 >> +Ac01PFAEnableAll ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN INTN PFAMode >> + ) >> +{ >> + PHYSICAL_ADDRESS CfgAddr; >> + PHYSICAL_ADDRESS RasDesVSecBase; >> + INT32 Ret = LINK_CHECK_SUCCESS; >> + UINT32 Val; >> + >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Allow programming to config space >> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 1); >> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val); >> + >> + // Generate the RAS DES capability address >> + // RAS_DES_CAP_ID = 0xB >> + RasDesVSecBase = PcieCheckCap (RootComplex, PcieIndex, TRUE, RAS_DES_CAP_ID); >> + if (RasDesVSecBase == 0) { >> + DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\n", RootComplex->ID, PcieIndex)); >> + return LINK_CHECK_WRONG_PARAMETER; >> + } >> + >> + if (PFAMode == PFA_REG_ENABLE) { >> + // PFA Counters Enable >> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF); >> + Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0x7); >> + Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0); >> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val); >> + } else if (PFAMode == PFA_REG_CLEAR) { >> + // PFA Counters Clear >> + Val = MmioRead32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF); >> + Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, 0); >> + Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, 0x3); >> + MmioWrite32 (RasDesVSecBase + EVENT_COUNTER_CONTROL_REG_OFF, Val); >> + } else { >> + // PFA Counters Read >> + Ret = PFACounterRead (RootComplex, PcieIndex, RasDesVSecBase); >> + } >> + >> + // Disable programming to config space >> + Val = MmioRead32 (CfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 0); >> + MmioWrite32 (CfgAddr + MISC_CONTROL_1_OFF, Val); >> + >> + return Ret; >> +} >> + >> +UINT32 >> +CheckEndpointCfg ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + PHYSICAL_ADDRESS EpCfgAddr; >> + UINT32 TimeOut; >> + UINT32 Val; >> + >> + EpCfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 20); /* Bus 1, dev 0, func 0 */ >> + >> + // Loop read EpCfgAddr value until got valid value or >> + // reach to timeout EP_LINKUP_TIMEOUT (or more depend on card) >> + TimeOut = EP_LINKUP_TIMEOUT; >> + do { >> + Val = MmioRead32 (EpCfgAddr); >> + if (Val != 0xFFFF0001 && Val != 0xFFFFFFFF) { >> + break; >> + } >> + MicroSecondDelay (LINK_WAIT_INTERVAL_US); >> + TimeOut -= LINK_WAIT_INTERVAL_US; >> + } while (TimeOut > 0); >> + >> + return MmioRead32 (EpCfgAddr); >> +} >> + >> +VOID >> +GetEndpointInfo ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + OUT UINT8 *EpMaxWidth, >> + OUT UINT8 *EpMaxGen >> + ) >> +{ >> + PHYSICAL_ADDRESS PcieCapBaseAddr; >> + UINT32 Val; >> + >> + Val = CheckEndpointCfg (RootComplex, PcieIndex); >> + if (Val == 0xFFFFFFFF) { >> + *EpMaxWidth = 0; // Invalid Width >> + *EpMaxGen = 0; // Invalid Speed >> + DEBUG ((DEBUG_ERROR, "PCIE%d.%d Cannot access EP config space!\n", RootComplex->ID, PcieIndex)); >> + } else { >> + PcieCapBaseAddr = PcieCheckCap (RootComplex, PcieIndex, FALSE, CAP_ID); >> + if (PcieCapBaseAddr == 0) { >> + *EpMaxWidth = 0; // Invalid Width >> + *EpMaxGen = 0; // Invalid Speed >> + DEBUG (( >> + DEBUG_ERROR, >> + "PCIE%d.%d Cannot get PCIe capability extended address!\n", >> + RootComplex->ID, >> + PcieIndex >> + )); >> + } else { >> + Val = MmioRead32 (PcieCapBaseAddr + LINK_CAPABILITIES_REG_OFF); >> + *EpMaxWidth = (Val >> 4) & 0x3F; >> + *EpMaxGen = Val & 0xF; >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE%d.%d EP MaxWidth %d EP MaxGen %d \n", RootComplex->ID, >> + PcieIndex, >> + *EpMaxWidth, >> + *EpMaxGen >> + )); >> + >> + // From EP, enabling common clock for upstream >> + Val = MmioRead32 (PcieCapBaseAddr + LINK_CONTROL_LINK_STATUS_OFF); >> + Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1); >> + Val = CAP_COMMON_CLK_SET (Val, 1); >> + MmioWrite32 (PcieCapBaseAddr + LINK_CONTROL_LINK_STATUS_OFF, Val); >> + } >> + } >> +} >> + >> +/** >> + Get link capabilities link width and speed of endpoint >> + >> + @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex[in] PCIe controller index >> + @param EpMaxWidth[out] EP max link width >> + @param EpMaxGen[out] EP max link speed >> +**/ >> +VOID >> +Ac01PcieCoreGetEndpointInfo ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + OUT UINT8 *EpMaxWidth, >> + OUT UINT8 *EpMaxGen >> + ) >> +{ >> + PHYSICAL_ADDRESS RcCfgAddr; >> + UINT32 Val, RestoreVal; >> + >> + RcCfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + // Allow programming to config space >> + Val = MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 1); >> + MmioWrite32 (RcCfgAddr + MISC_CONTROL_1_OFF, Val); >> + >> + Val = MmioRead32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG); >> + RestoreVal = Val; >> + Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS); /* Set DEFAULT_SUB_BUS to Subordinate bus */ >> + Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum); /* Set RootComplex->Pcie[PcieIndex].DevNum to Secondary bus */ >> + Val = PRIM_BUS_SET (Val, 0x0); /* Set 0x0 to Primary bus */ >> + MmioWrite32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, Val); >> + >> + GetEndpointInfo (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen); >> + >> + // Restore value in order to not affect enumeration process >> + MmioWrite32 (RcCfgAddr + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, RestoreVal); >> + >> + // Disable programming to config space >> + Val = MmioRead32 (RcCfgAddr + MISC_CONTROL_1_OFF); >> + Val = DBI_RO_WR_EN_SET (Val, 0); >> + MmioWrite32 (RcCfgAddr + MISC_CONTROL_1_OFF, Val); >> +} >> + >> +VOID >> +PollLinkUp ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + UINT32 TimeOut; >> + >> + // Poll until link up >> + // This checking for linkup status and >> + // give LTSSM state the time to transit from DECTECT state to L0 state >> + // Total delay are 100ms, smaller number of delay cannot always make sure >> + // the state transition is completed >> + TimeOut = LTSSM_TRANSITION_TIMEOUT; >> + do { >> + if (PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex])) { >> + DEBUG (( >> + DEBUG_INFO, >> + "\tPCIE%d.%d LinkStat is correct after soft reset, transition time: %d\n", >> + RootComplex->ID, >> + PcieIndex, >> + TimeOut >> + )); >> + RootComplex->Pcie[PcieIndex].LinkUp = TRUE; >> + break; >> + } >> + >> + MicroSecondDelay (100); >> + TimeOut -= 100; >> + } while (TimeOut > 0); >> + >> + if (TimeOut <= 0) { >> + DEBUG ((DEBUG_ERROR, "\tPCIE%d.%d LinkStat TIMEOUT after re-init\n", RootComplex->ID, PcieIndex)); >> + } else { >> + DEBUG ((DEBUG_INFO, "PCIE%d.%d Link re-initialization passed!\n", RootComplex->ID, PcieIndex)); >> + } >> +} >> + >> +/** >> + Check active PCIe controllers of RootComplex, retrain or soft reset if needed >> + >> + @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure >> + @param PcieIndex[in] PCIe controller index >> + >> + @retval -1: Link recovery had failed >> + 1: Link width and speed are not correct >> + 0: Link recovery succeed >> +**/ >> +INT32 >> +Ac01PcieCoreQoSLinkCheckRecovery ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex >> + ) >> +{ >> + INT32 NumberOfReset = MAX_REINIT; // Number of soft reset retry >> + UINT8 EpMaxWidth, EpMaxGen; >> + INT32 LinkStatusCheck, RasdesChecking; >> + >> + // PCIe controller is not active or Link is not up >> + // Nothing to be done >> + if ((!RootComplex->Pcie[PcieIndex].Active) || (!RootComplex->Pcie[PcieIndex].LinkUp)) { >> + return LINK_CHECK_WRONG_PARAMETER; >> + } >> + >> + do { >> + >> + if (RootComplex->Pcie[PcieIndex].LinkUp) { >> + // Enable all of RASDES register to detect any training error >> + Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_ENABLE); >> + >> + // Accessing Endpoint and checking current link capabilities >> + Ac01PcieCoreGetEndpointInfo (RootComplex, PcieIndex, &EpMaxWidth, &EpMaxGen); >> + LinkStatusCheck = Ac01PcieCoreLinkCheck (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen); >> + >> + // Delay to allow the link to perform internal operation and generate >> + // any error status update. This allows detection of any error observed >> + // during initial link training. Possible evaluation time can be >> + // between 100ms to 200ms. >> + MicroSecondDelay (100000); >> + >> + // Check for error >> + RasdesChecking = Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_READ); >> + >> + // Clear error counter >> + Ac01PFAEnableAll (RootComplex, PcieIndex, PFA_REG_CLEAR); >> + >> + // If link check functions return passed, then breaking out >> + // else go to soft reset >> + if (LinkStatusCheck != LINK_CHECK_FAILED && >> + RasdesChecking != LINK_CHECK_FAILED && >> + PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex])) >> + { >> + return LINK_CHECK_SUCCESS; >> + } >> + >> + RootComplex->Pcie[PcieIndex].LinkUp = FALSE; >> + } >> + >> + // Trigger controller soft reset >> + DEBUG ((DEBUG_INFO, "PCIE%d.%d Start link re-initialization..\n", RootComplex->ID, PcieIndex)); >> + Ac01PcieCoreSetupRC (RootComplex, TRUE, PcieIndex); >> + >> + PollLinkUp (RootComplex, PcieIndex); >> + >> + NumberOfReset--; >> + } while (NumberOfReset > 0); >> + >> + return LINK_CHECK_SUCCESS; >> +} >> + >> +VOID >> +Ac01PcieCoreUpdateLink ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + OUT BOOLEAN *IsNextRoundNeeded, >> + OUT INT8 *FailedPciePtr, >> + OUT INT8 *FailedPcieCount >> + ) >> +{ >> + AC01_PCIE_CONTROLLER *Pcie; >> + PHYSICAL_ADDRESS CfgAddr; >> + UINT8 PcieIndex; >> + UINT32 Index; >> + UINT32 Val; >> + >> + *IsNextRoundNeeded = FALSE; >> + *FailedPcieCount = 0; >> + for (Index = 0; Index < MaxPcieControllerB; Index++) { >> + FailedPciePtr[Index] = -1; >> + } >> + >> + if (!RootComplex->Active) { >> + return; >> + } >> + >> + // Loop for all controllers >> + for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) { >> + Pcie = &RootComplex->Pcie[PcieIndex]; >> + CfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << 15); >> + >> + if (Pcie->Active && !Pcie->LinkUp) { >> + if (PcieLinkUpCheck (Pcie)) { >> + Pcie->LinkUp = TRUE; >> + Val = MmioRead32 (CfgAddr + LINK_CONTROL_LINK_STATUS_REG); >> + DEBUG (( >> + DEBUG_INFO, >> + "%a Socket%d RootComplex%d RP%d NEGO_LINK_WIDTH: 0x%x LINK_SPEED: 0x%x\n", >> + __FUNCTION__, >> + RootComplex->Socket, >> + RootComplex->ID, >> + PcieIndex, >> + CAP_NEGO_LINK_WIDTH_GET (Val), >> + CAP_LINK_SPEED_GET (Val) >> + )); >> + >> + // Doing link checking and recovery if needed >> + Ac01PcieCoreQoSLinkCheckRecovery (RootComplex, PcieIndex); >> + >> + // Un-mask Completion Timeout >> + MaskCompletionTimeOut (RootComplex, PcieIndex, 32, FALSE); >> + >> + } else { >> + *IsNextRoundNeeded = FALSE; >> + FailedPciePtr[*FailedPcieCount] = PcieIndex; >> + *FailedPcieCount += 1; >> + } >> + } >> + } >> +} >> + >> +/** >> + Verify the link status and retry to initialize the Root Complex if there's any issue. >> + >> + @param RootComplexList Pointer to the Root Complex list >> +**/ >> +VOID >> +Ac01PcieCorePostSetupRC ( >> + IN AC01_ROOT_COMPLEX *RootComplexList >> + ) >> +{ >> + UINT8 RCIndex, Idx; >> + BOOLEAN IsNextRoundNeeded = FALSE, NextRoundNeeded; >> + UINT64 PrevTick, CurrTick, ElapsedCycle; >> + UINT64 TimerTicks64; >> + UINT8 ReInit; >> + INT8 FailedPciePtr[MaxPcieControllerB]; >> + INT8 FailedPcieCount; >> + >> + ReInit = 0; >> + >> +_link_polling: >> + NextRoundNeeded = 0; >> + // >> + // It is not guaranteed the timer service is ready prior to PCI Dxe. >> + // Calculate system ticks for link training. >> + // >> + TimerTicks64 = ArmGenericTimerGetTimerFreq (); /* 1 Second */ >> + PrevTick = ArmGenericTimerGetSystemCount (); >> + ElapsedCycle = 0; >> + >> + do { >> + CurrTick = ArmGenericTimerGetSystemCount (); >> + if (CurrTick < PrevTick) { >> + ElapsedCycle += (UINT64)(~0x0ULL) - PrevTick; >> + PrevTick = 0; >> + } >> + ElapsedCycle += (CurrTick - PrevTick); >> + PrevTick = CurrTick; >> + } while (ElapsedCycle < TimerTicks64); >> + >> + for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) { >> + Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount); >> + if (IsNextRoundNeeded) { >> + NextRoundNeeded = 1; >> + } >> + } >> + >> + if (NextRoundNeeded && ReInit < MAX_REINIT) { >> + // >> + // Timer is up. Give another chance to re-program controller >> + // >> + ReInit++; >> + for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) { >> + Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount); >> + if (IsNextRoundNeeded) { >> + for (Idx = 0; Idx < FailedPcieCount; Idx++) { >> + if (FailedPciePtr[Idx] == -1) { >> + continue; >> + } >> + >> + // >> + // Some controller still observes link-down. Re-init controller >> + // >> + Ac01PcieCoreSetupRC (&RootComplexList[RCIndex], TRUE, FailedPciePtr[Idx]); >> + } >> + } >> + } >> + >> + goto _link_polling; >> + } >> +} >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c >> new file mode 100644 >> index 000000000000..0916adb77539 >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c >> @@ -0,0 +1,47 @@ >> +/** @file >> + >> + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include >> + >> +/** >> + Assert PERST of input PCIe controller >> + >> + @param[in] RootComplex RootComplex instance. >> + @param[in] PcieIndex PCIe controller index of input Root Complex. >> + @param[in] Bifurcation Bifurcation mode of input Root Complex. >> + @param[in] IsPullToHigh Target status for the PERST. >> + >> + @retval RETURN_SUCCESS The operation is successful. >> + @retval Others An error occurred. >> +**/ >> +RETURN_STATUS >> +EFIAPI >> +BoardPcieAssertPerst ( >> + IN AC01_ROOT_COMPLEX *RootComplex, >> + IN UINT8 PcieIndex, >> + IN BOOLEAN IsPullToHigh >> + ) >> +{ >> + return RETURN_SUCCESS; >> +} >> + >> +/** >> + Override the segment number for a root complex with a board specific number. >> + >> + @param[in] RootComplex Root Complex instance with properties. >> + >> + @retval Segment number corresponding to the input root complex. >> + Default segment number is 0x0F. >> +**/ >> +UINT16 >> +BoardPcieGetSegmentNumber ( >> + IN AC01_ROOT_COMPLEX *RootComplex >> + ) >> +{ >> + return 0x0F; >> +} >> -- >> 2.17.1 >>