From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com [40.107.220.102]) by mx.groups.io with SMTP id smtpd.web09.9821.1637167818891394120 for ; Wed, 17 Nov 2021 08:50:19 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=rQ4YAhmZ; spf=pass (domain: os.amperecomputing.com, ip: 40.107.220.102, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=DTjKTu0tidbjaH064P4lC0whkSH6NKAsWP696fnX+KWMuvjL+VMHSQ2n6vnTxBm1sCIUzWNU+ehThEOgXiujKz29vv2fQBwjtVIRCx536o0AcTTcl3dLxDaCbwPUrkkSPo9iHLzE5aDfuNeKW9A0aRcAZ1vPJocpsZpvlx2zbRjUDzVLSdI7NoevjnI3sh+7wVyLyeijfLwGLrcgwDGTBdhW0RxjtxSOQy9Q3pTTT4mYdy64SV7ERLNlSHlujypNHZSPclFZdDZVIC4tT69cklGxO/C8g8r2AiLcjzWxWAMKCoLVvQ6TrlN+pckJXYtWLZfG3P3qzbb4U4hG4aV2Zg== 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=xK5s+wsUUfr4kKLfa8F3OW3bztzjtGKXLKS0Y1976Xs=; b=jBYPOsDfu9AEo5GSUOmtWcpxw3VPMx9rKwxnn1iYr8CF1Ki6+iWj6USDFGHy9kLKnwwf2RWYvsMdo1+c0VvcNOFmC36PSuJjERLLRAuVtpLQQTF36+MIDNPc+gNwdaTo5whE5TADAoUPeFmMtPR78le7Tn3CXiISmbObED+BJmhbhKOo9aUlAfyRQcNywYSjcTttIS7v+PsgQxhf63WDsPaZnZH5FG1ZfMmTDRk7j8RNSFv6gOxpp3CnFDFd1Aw3BULu/RUAdRFYmMlk35uihdBDwQYv20D0VjdB+mC+9pf5F7W4lhTEptSkfKp26suK1CtBOabSyHFlrkpB7A3D7w== 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=xK5s+wsUUfr4kKLfa8F3OW3bztzjtGKXLKS0Y1976Xs=; b=rQ4YAhmZFfE3i84r2acoY87zdPTTfAHHBHhOX9Tap2yTZuQB8tDEiVTfd1gNR26hF+hxFl2ngW3mGUbcJ3NM8+hyMSrhz8hD2HkXzLkuJEMnNekMJGnTYHmyIskQpTrVQJ7/RU37IyonWSSmZnX80poxLE+15xmQSkuh/VD1rbM= 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 PH0PR01MB6454.prod.exchangelabs.com (2603:10b6:510:1b::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.20; Wed, 17 Nov 2021 16:50:17 +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; Wed, 17 Nov 2021 16:50:17 +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 v5 13/30] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Date: Wed, 17 Nov 2021 23:47:10 +0700 Message-ID: <20211117164727.10922-14-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211117164727.10922-1-nhi@os.amperecomputing.com> References: <20211117164727.10922-1-nhi@os.amperecomputing.com> X-ClientProxiedBy: HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) 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 HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.21 via Frontend Transport; Wed, 17 Nov 2021 16:50:14 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 149ccf71-1f42-4dca-b9cd-08d9a9ea5565 X-MS-TrafficTypeDiagnostic: PH0PR01MB6454: 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: oYXaGhmYCY+xkPEasHWd+iguYhuPhEo8iH6Bc6psETQqFPYjMgqCFXqWLN/9ciOkt1j1KCA+c7Jl7X2VviCoNU8O2urOrJFV9O6S/JeNUTgJmu6r9+DzApwZZDLrvu5typFQJhXLwjjRFAJkOtHJlJkj4Ovp1w2xf+X3k/4q/5OnwdEZFLWcCrLPw/HMWK0eonSvb1/PhbaOW/k2VLtwN4gih4fIAeM+ODQfxuO7Z2EW5+a+PkJsIEoq+ZqV6whehJ73QyRYAsweeiJzgcfhlx2UK7x9HKmQx2R2S0+5G3OQ/DzgmF6NKi2qaT/0bjf6UV3CwnN6TlAprRk8QNTP7uV6j+yqoGg7/dVscT7fyKfsSYOOdZZhsTTl6RXCwW+XCl+srDEsv4HMYZaqzVtaz0YY+ZDytQ4CBTSrYtECuW/h2Uz1ZBy4mgtup+2WANUhbn1wPl6J85FykfauLIyRzEMk6li5aTiWB9Q0BwIhq+NE6EBiyrmB5bKe7+2a+rVILcB4wHUe3jH1j8KTyPgXqst9WULPuNXz6+Uhr1Hs/A7VoPRKKHwbI09apeu/BeFqknkscb6Z5xHTQJgfRAXXl8izPe7GgJQIdG5SJLwFHP98EdbllKhOF8V7hG08iQTsnnDCxuYCYHk5/kVJRcwiP7PZNxawSycbo/YQjuX9fQ3LRjsTyKP2CIZtkRi+YwIi/YGakXtP9bayOK49zRSKHg== 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)(8936002)(66476007)(52116002)(186003)(86362001)(2906002)(1076003)(83380400001)(54906003)(4326008)(66556008)(26005)(38100700002)(38350700002)(19627235002)(30864003)(6506007)(6916009)(6486002)(2616005)(956004)(5660300002)(6512007)(316002)(8676002)(66946007)(508600001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?MyfBh7dFMehz+bdik2xLaS5nbDTyIyovINmJ/+FlEYreqgStgqQKTXUeKbIM?= =?us-ascii?Q?zKQv4s34M3+/yFv95ampNKi6GxwktI6XsHB6rrNsrHIf5rRKvjn/JnzOyvR0?= =?us-ascii?Q?9XbiNSu3L9FYgSZn5U4vFgVLBRF7ecftVHUWZjorNowO8BhZudGJzCN0MjJ1?= =?us-ascii?Q?GbDd9H7nPTq7IBPgewfBDakK4sCZOj1FM9/Eg6IYV3ZRi+xUp/pI+sC07XQB?= =?us-ascii?Q?cJ8ZEif5R+KJ1j7CUyyVUY60fHlUa5z6C4YqMwhVJSELu2O2TjK1a1YgmcCq?= =?us-ascii?Q?gSSt+5Eax4rqXaSvJrTHQVvnNEhQAe7pLZBAENdV76DbiBbCBIQlnv3BQUbK?= =?us-ascii?Q?ruIP8Dk8eDbInhTMiVsjXsogWSJESe9PWQSlDN20MfFKJ+clHYzB6pfP4O1N?= =?us-ascii?Q?L6Ly6n6g5owXDfiRQaspHJGZMdFVj3at7a6LnpJWwnL3XVnYzSQ9cWfpBsdW?= =?us-ascii?Q?W45o1vieXGc0IzikmyRSTZZRtmOMz5Pjs4JUv8lQ5I3kUoBdvoL0hxNWAD7l?= =?us-ascii?Q?sgcAKZJAawZUh2dbbGNEkP1lrtlfObGZc2HWg8AOtsEubOecYGAv2CUhdXtp?= =?us-ascii?Q?AIrBeyKCfhI0myEx5Hd6n4X6poGA9WeworBHiPYasYcbD8JPJa7VVJSeP444?= =?us-ascii?Q?ETbs9HKVm0IttIbqICkydWWIvfm2GDarLVgYEEpCArDIW7Io2+AJewcGrTWn?= =?us-ascii?Q?WKA23/byHGzdqd2FcqAjn7ajaZ9ZtyXrbum1Dy45PLBm1QjTwYM9ISMOvm4y?= =?us-ascii?Q?BXDgwTe0TP8lc2sot8ZiaxOp/akVrAqMJwnphkUnlmzLXyf34t+7LQjxs6WA?= =?us-ascii?Q?N70QAAnIxtnGVoxU1DVvOkdU3S7cFeJbz6Ha93630kDoT/ww/pFpHe5eEsKu?= =?us-ascii?Q?cQaca84tsYuiTySuiJ9znBi2HQRFZfnWsyzrgsH8R3wU7d97vXz3Jiwr6hPe?= =?us-ascii?Q?nLj6upjfI2ELKhzAFQA9L7+l/USuU2e3oUi+Nkqa0kdRJDil55fx1kz/moRe?= =?us-ascii?Q?6lI8W6NgxoL/iDwQNFvtal2YXW+YnkhcJBAzYO/IsBIXT3KDcCXiHetG9r7q?= =?us-ascii?Q?00TjDyp4pFiATPorCl7b+qLuw3pQmQDuFN8PSe4JcmjdxZq6ZdBitr3zXJGM?= =?us-ascii?Q?aLpmrOwhQiU+WeoxyDJbDHkKxVAshkkJ4udXoIGi9L0VSpIReUMi0l2NKB7r?= =?us-ascii?Q?tTr6VH8RcdPuHOEdnpwXmAhU8075BSlR9/zzk55mupDM0pnWt694HRHR8NRd?= =?us-ascii?Q?b/u3tICWsfo/E0lPRwXYAT/5YAZDIFYx7WB6QLTgDSen4as0WrZv3B+kl2Tz?= =?us-ascii?Q?2lmLGyQBoKXvJk4TMm/euDKomh+ZsJ7jh105MxDok8rx4n0/vOQE5zBk68lb?= =?us-ascii?Q?v+mBL5SOIisblO7/zAhm2o2sHq1KWp3ENZ77L/9cs9ZAcFqSpEWOBAfw5TMK?= =?us-ascii?Q?nABtnqSGg/pqcl5kiRrSo4gVToKFNA4eEfojVe86Lu5q3LQjz228dTjtJMZ5?= =?us-ascii?Q?y54DQqD4FnqhL1xDUdKaLF2Iu2NlPNymNt+bAzrWW0tTJjGh+n+HfhT8miaU?= =?us-ascii?Q?CxD8UwebdOlpRzMzWc4KEPj7xFN08GA6gE+TOUSi+WSlOnxBryjiNtZ1iDPm?= =?us-ascii?Q?5SjnNfaZc4NpAs/IcFHgOcZzwxTibllg7j40ghDrUNEloae5m9JBTjiZhY4b?= =?us-ascii?Q?2WMvJG7mW4+Awz1qwGqECOJs080=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 149ccf71-1f42-4dca-b9cd-08d9a9ea5565 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Nov 2021 16:50:17.2863 (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: cT6OVjzCvfRuZykZA9uq+xQedsBLUNNnIVDOxqS3TxhkGdQfZToLUxJRZqe/ZaGv96NxCkAReeZZV1EdTE4dtHJMOkFHNJlRv7GYlBYM/ic= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6454 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Vu Nguyen This driver takes responsibility for: - Parsing platform settings to build the Root Complex info HOB - Initializing each Root Complex 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 Reviewed-by: Leif Lindholm --- Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | = 1 + Platform/Ampere/JadePkg/Jade.fdf | = 1 + Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf | = 40 ++ Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.h | = 28 ++ Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h | = 45 ++ Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c | 1= 57 ++++++ Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.c | 5= 14 ++++++++++++++++++++ 7 files changed, 786 insertions(+) diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon= /Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc index 5b767ecb024f..b08bdd82177e 100644 --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc @@ -534,6 +534,7 @@ [Components.common] Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf + Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf ArmPkg/Drivers/CpuPei/CpuPei.inf UefiCpuPkg/CpuIoPei/CpuIoPei.inf MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jad= e.fdf index 078b63c867d6..2fef96deb767 100644 --- a/Platform/Ampere/JadePkg/Jade.fdf +++ b/Platform/Ampere/JadePkg/Jade.fdf @@ -162,6 +162,7 @@ [FV.FVMAIN_COMPACT] INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRo= uterPei.inf INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.in= f + INF Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf =20 # # Print platform information before passing control into the Driver Exec= ution Environment (DXE) phase diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.= inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf new file mode 100644 index 000000000000..17ac1672dac8 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf @@ -0,0 +1,40 @@ +## @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 PcieInitPei + FILE_GUID =3D CD3F92A7-9AE4-42F9-B2CC-B47A8615B85B + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PcieInitEntry + +[Sources] + PcieInitPei.c + RootComplexNVParam.c + RootComplexNVParam.h + +[Packages] + MdePkg/MdePkg.dec + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec + +[LibraryClasses] + Ac01PcieLib + AmpereCpuLib + BaseMemoryLib + BoardPcieLib + DebugLib + HobLib + PeimEntryPoint + +[Guids] + gRootComplexInfoHobGuid + gPlatformInfoHobGuid + +[Depex] + TRUE diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexN= VParam.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVP= aram.h new file mode 100644 index 000000000000..008a8db69f2c --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.= h @@ -0,0 +1,28 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef GET_ROOT_COMPLEX_INFO_ +#define GET_ROOT_COMPLEX_INFO_ + +#define BITS_PER_BYTE 8 +#define BYTE_MASK 0xFF +#define PCIE_ERRATA_SPEED1 0x0001 // Limited speed errata + +#ifndef BIT +#define BIT(nr) (1 << (nr)) +#endif + +#define PCIE_GET_MAX_WIDTH(Pcie, Max) \ + !((Pcie).MaxWidth) ? (Max) : MIN ((Pcie).MaxWidth, (Max)) + +VOID +ParseRootComplexNVParamData ( + AC01_ROOT_COMPLEX *RootComplex + ); + +#endif /* GET_ROOT_COMPLEX_INFO_ */ diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h b/Silico= n/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h index 2310e4e1ce98..f3e6b4041737 100644 --- a/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h @@ -229,4 +229,49 @@ // #define PLATFORM_CPM_UID_BIT_OFFSET 8 =20 +// +// Max number for AC01 PCIE Root Complexes +// +#define AC01_PCIE_MAX_ROOT_COMPLEX 16 + +// +// Max number for AC01 PCIE Root Complexes per socket +// +#define AC01_PCIE_MAX_RCS_PER_SOCKET 8 + +// +// The base address of {TCU, CSR, MMCONFIG} Registers +// +#define AC01_PCIE_CSR_BASE_LIST 0x33FFE0000000, 0x37FFE0000000, 0= x3BFFE0000000, 0x3FFFE0000000, 0x23FFE0000000, 0x27FFE0000000, 0x2BFFE00000= 00, 0x2FFFE0000000, 0x73FFE0000000, 0x77FFE0000000, 0x7BFFE0000000, 0x7FFFE= 0000000, 0x63FFE0000000, 0x67FFE0000000, 0x6BFFE0000000, 0x6FFFE0000000 + +// +// The base address of MMIO Registers +// +#define AC01_PCIE_MMIO_BASE_LIST 0x300000000000, 0x340000000000, 0= x380000000000, 0x3C0000000000, 0x200000000000, 0x240000000000, 0x2800000000= 00, 0x2C0000000000, 0x700000000000, 0x740000000000, 0x780000000000, 0x7C000= 0000000, 0x600000000000, 0x640000000000, 0x680000000000, 0x6C0000000000 + +// +// The size of MMIO space +// +#define AC01_PCIE_MMIO_SIZE_LIST 0x3FFE0000000, 0x3FFE0000000, 0x3= FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3= FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3= FFE0000000, 0x3FFE0000000, 0x3FFE0000000, 0x3FFE0000000 + +// +// The base address of MMIO32 Registers +// +#define AC01_PCIE_MMIO32_BASE_LIST 0x000020000000, 0x000028000000, 0= x000030000000, 0x000038000000, 0x000004000000, 0x000008000000, 0x0000100000= 00, 0x000018000000, 0x000060000000, 0x000068000000, 0x000070000000, 0x00007= 8000000, 0x000040000000, 0x000048000000, 0x000050000000, 0x000058000000 + +// +// The size of MMIO32 space +// +#define AC01_PCIE_MMIO32_SIZE_LIST 0x8000000, 0x8000000, 0x8000000, = 0x8000000, 0x4000000, 0x8000000, 0x8000000, 0x8000000, 0x8000000, 0x8000000= , 0x8000000, 0x8000000, 0x8000000, 0x8000000, 0x8000000, 0x8000000 + +// +// The base address of MMIO32 Registers +// +#define AC01_PCIE_MMIO32_BASE_1P_LIST 0x000040000000, 0x000050000000, 0= x000060000000, 0x000070000000, 0x000008000000, 0x000010000000, 0x0000200000= 00, 0x000030000000, 0, 0, 0, 0, 0, 0, 0, 0 + +// +// The size of MMIO32 1P space +// +#define AC01_PCIE_MMIO32_SIZE_1P_LIST 0x10000000, 0x10000000, 0x1000000= 0, 0x10000000, 0x8000000, 0x10000000, 0x10000000, 0x10000000, 0, 0, 0, 0, 0= , 0, 0, 0 + #endif /* PLATFORM_AC01_H_ */ diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.= c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c new file mode 100644 index 000000000000..cdd907d378e8 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c @@ -0,0 +1,157 @@ +/** @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 "RootComplexNVParam.h" + +#define TCU_OFFSET 0 +#define SNPSRAM_OFFSET 0x9000 +#define HB_CSR_OFFSET 0x01000000 +#define PCIE0_CSR_OFFSET 0x01010000 +#define SERDES_CSR_OFFSET 0x01200000 +#define MMCONFIG_OFFSET 0x10000000 + +#define PCIE_CSR_SIZE 0x10000 + +STATIC AC01_ROOT_COMPLEX mRootComplexList[AC01_PCIE_MAX_ROOT_COMPLE= X]; +STATIC UINT64 mCsrBase[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_CSR_BASE_LIST }; +STATIC UINT64 mMmio32Base[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO32_BASE_LIST }; +STATIC UINT64 mMmio32Base1P[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO32_BASE_1P_LIST }; +STATIC UINT64 mMmio32Size[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO32_SIZE_LIST }; +STATIC UINT64 mMmio32Size1P[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO32_SIZE_1P_LIST }; +STATIC UINT64 mMmioBase[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO_BASE_LIST }; +STATIC UINT64 mMmioSize[AC01_PCIE_MAX_ROOT_COMPLEX] = =3D { AC01_PCIE_MMIO_SIZE_LIST }; + +VOID +BuildRootComplexData ( + VOID + ) +{ + AC01_ROOT_COMPLEX *RootComplex; + UINT8 RCIndex; + UINT8 PcieIndex; + + ZeroMem (&mRootComplexList, sizeof (AC01_ROOT_COMPLEX) * AC01_PCIE_MAX_R= OOT_COMPLEX); + + // + // Adjust Root Complex MMIO32 base address in 1P or 2P configuration + // + if (!IsSlaveSocketAvailable ()) { + CopyMem ((VOID *)&mMmio32Base, (VOID *)&mMmio32Base1P, sizeof (mMmio32= Base1P)); + CopyMem ((VOID *)&mMmio32Size, (VOID *)&mMmio32Size1P, sizeof (mMmio32= Size1P)); + } + + for (RCIndex =3D 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) { + RootComplex =3D &mRootComplexList[RCIndex]; + RootComplex->Active =3D TRUE; + RootComplex->DevMapLow =3D 0; + RootComplex->DevMapHigh =3D 0; + RootComplex->Socket =3D RCIndex / AC01_PCIE_MAX_RCS_PER_SOCKET; + RootComplex->ID =3D RCIndex % AC01_PCIE_MAX_RCS_PER_SOCKET; + RootComplex->CsrBase =3D mCsrBase[RCIndex]; + RootComplex->TcuBase =3D RootComplex->CsrBase + TCU_OFFSET; + RootComplex->HostBridgeBase =3D RootComplex->CsrBase + HB_CSR_OFFSET; + RootComplex->SerdesBase =3D RootComplex->CsrBase + SERDES_CSR_OFFSET; + RootComplex->MmcfgBase =3D RootComplex->CsrBase + MMCONFIG_OFFSET; + RootComplex->MmioBase =3D mMmioBase[RCIndex]; + RootComplex->MmioSize =3D mMmioSize[RCIndex]; + RootComplex->Mmio32Base =3D mMmio32Base[RCIndex]; + RootComplex->Mmio32Size =3D mMmio32Size[RCIndex]; + RootComplex->Type =3D (RootComplex->ID < MaxRootComplexA) ? RootComple= xTypeA : RootComplexTypeB; + RootComplex->MaxPcieController =3D (RootComplex->Type =3D=3D RootCompl= exTypeB) + ? MaxPcieControllerOfRootComplexB : M= axPcieControllerOfRootComplexA; + RootComplex->Logical =3D BoardPcieGetSegmentNumber (RootComplex); + + for (PcieIndex =3D 0; PcieIndex < RootComplex->MaxPcieController; Pcie= Index++) { + RootComplex->Pcie[PcieIndex].ID =3D PcieIndex; + RootComplex->Pcie[PcieIndex].CsrBase =3D RootComplex->CsrBase + PCIE= 0_CSR_OFFSET + PcieIndex * PCIE_CSR_SIZE; + RootComplex->Pcie[PcieIndex].SnpsRamBase =3D RootComplex->Pcie[PcieI= ndex].CsrBase + SNPSRAM_OFFSET; + RootComplex->Pcie[PcieIndex].DevNum =3D PcieIndex + 1; + } + + ParseRootComplexNVParamData (RootComplex); + + DEBUG (( + DEBUG_INFO, + " + S%d - RootComplex%a%d, MMCfgBase:0x%lx, MmioBase:0x%lx, Mmio32Ba= se:0x%lx, Enabled:%a\n", + RootComplex->Socket, + (RootComplex->Type =3D=3D RootComplexTypeA) ? "A" : "B", + RootComplex->ID, + RootComplex->MmcfgBase, + RootComplex->MmioBase, + RootComplex->Mmio32Base, + (RootComplex->Active) ? "Y" : "N" + )); + + DEBUG ((DEBUG_INFO, " + DevMapLo/Hi: 0x%x/0x%x\n", RootComplex->DevM= apLow, RootComplex->DevMapHigh)); + for (PcieIndex =3D 0; PcieIndex < RootComplex->MaxPcieController; Pcie= Index++) { + DEBUG (( + DEBUG_INFO, + " + PCIE%d:0x%lx - Enabled:%a - DevNum:0x%x\n", + PcieIndex, + RootComplex->Pcie[PcieIndex].CsrBase, + (RootComplex->Pcie[PcieIndex].Active) ? "Y" : "N", + RootComplex->Pcie[PcieIndex].DevNum + )); + } + } +} + +EFI_STATUS +EFIAPI +PcieInitEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + AC01_ROOT_COMPLEX *RootComplex; + EFI_STATUS Status; + UINT8 Index; + + BuildRootComplexData (); + + // + // Initialize Root Complex and underneath controllers + // + for (Index =3D 0; Index < AC01_PCIE_MAX_ROOT_COMPLEX; Index++) { + RootComplex =3D &mRootComplexList[Index]; + if (!RootComplex->Active) { + continue; + } + + Status =3D Ac01PcieCoreSetupRC (RootComplex, FALSE, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "RootComplex[%d]: Init Failed\n", Index)); + RootComplex->Active =3D FALSE; + continue; + } + } + + Ac01PcieCorePostSetupRC (mRootComplexList); + + // + // Build Root Complex info Hob + // + BuildGuidDataHob ( + &gRootComplexInfoHobGuid, + (VOID *)&mRootComplexList, + sizeof (mRootComplexList) + ); + + return EFI_SUCCESS; +} diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexN= VParam.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVP= aram.c new file mode 100644 index 000000000000..aa34a90b44c6 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.= c @@ -0,0 +1,514 @@ +/** @file + Parsing NVPARAM board settings for bifurcation programming. + + NVPARAM board settings is spec-ed within Firmware Interface Requirement. + Bifurcation devmap is programmed before at SCP following the rule + + Root Complex Type-A devmap settings (RP =3D=3D Root Port) + ----------------------------------------- + | RP0 | RP1 | RP2 | RP3 | Devmap | + | (x16) | (x4) | (x8) | (x4) | (output) | + ------------------------------------------- + | Y | N | N | N | 0 | + | Y | N | Y | N | 1 | + | Y | N | Y | Y | 2 | + | Y | Y | Y | Y | 3 | + ----------------------------------------- + + Root Complex Type-B LOW (aka RCBxA) devmap settings (RP =3D=3D Root Port= ) + ---------------------------------------- + | RP0 | RP1 | RP2 | RP3 | Devmap | + | (x8) | (x2) | (x4) | (x3) | (output) | + ---------------------------------------- + | Y | N | N | N | 0 | + | Y | N | Y | N | 1 | + | Y | N | Y | Y | 2 | + | Y | Y | Y | Y | 3 | + ---------------------------------------- + + Root Complex Type-B HIGH (aka RCBxB) devmap settings (RP =3D=3D Root Por= t) + ---------------------------------------- + | RP4 | RP5 | RP6 | RP7 | Devmap | + | (x8) | (x2) | (x4) | (x3) | (output) | + ---------------------------------------- + | Y | N | N | N | 0 | + | Y | N | Y | N | 1 | + | Y | N | Y | Y | 2 | + | Y | Y | Y | Y | 3 | + ---------------------------------------- + + 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 "RootComplexNVParam.h" + +STATIC +BOOLEAN +IsEmptyRC ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + UINT8 Idx; + + for (Idx =3D PcieController0; Idx < MaxPcieController; Idx++) { + if (RootComplex->Pcie[Idx].Active) { + return FALSE; + } + } + + return TRUE; +} + +VOID +SetRootComplexBifurcation ( + IN AC01_ROOT_COMPLEX *RootComplex, + IN UINT8 RPStart, + IN DEV_MAP_MODE DevMap + ) +{ + UINT8 MaxWidth; + + if (RPStart !=3D PcieController0 && RPStart !=3D PcieController4) { + return; + } + + if (RootComplex->Type !=3D RootComplexTypeB && RPStart =3D=3D PcieContro= ller4) { + return; + } + + if (RootComplex->Type =3D=3D RootComplexTypeA && RootComplex->Pcie[RPSta= rt].MaxWidth =3D=3D LINK_WIDTH_X16) { + RootComplex->Pcie[RPStart + 1].MaxWidth =3D LINK_WIDTH_X4; + RootComplex->Pcie[RPStart + 2].MaxWidth =3D LINK_WIDTH_X8; + RootComplex->Pcie[RPStart + 3].MaxWidth =3D LINK_WIDTH_X4; + } + + if (RootComplex->Type =3D=3D RootComplexTypeB && RootComplex->Pcie[RPSta= rt].MaxWidth =3D=3D LINK_WIDTH_X8) { + RootComplex->Pcie[RPStart + 1].MaxWidth =3D LINK_WIDTH_X2; + RootComplex->Pcie[RPStart + 2].MaxWidth =3D LINK_WIDTH_X4; + RootComplex->Pcie[RPStart + 3].MaxWidth =3D LINK_WIDTH_X2; + } + + switch (DevMap) { + case DevMapMode2: + MaxWidth =3D (RootComplex->Type =3D=3D RootComplexTypeA) ? LINK_WIDTH_= X8 : LINK_WIDTH_X4; + RootComplex->Pcie[RPStart].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootComple= x->Pcie[RPStart], MaxWidth); + RootComplex->Pcie[RPStart + 1].Active =3D FALSE; + RootComplex->Pcie[RPStart + 2].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 2], MaxWidth); + RootComplex->Pcie[RPStart + 2].Active =3D TRUE; + RootComplex->Pcie[RPStart + 3].Active =3D FALSE; + break; + + case DevMapMode3: + MaxWidth =3D (RootComplex->Type =3D=3D RootComplexTypeA) ? LINK_WIDTH_= X8 : LINK_WIDTH_X4; + RootComplex->Pcie[RPStart].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootComple= x->Pcie[RPStart], MaxWidth); + RootComplex->Pcie[RPStart + 1].Active =3D FALSE; + MaxWidth =3D (RootComplex->Type =3D=3D RootComplexTypeA) ? LINK_WIDTH_= X4 : LINK_WIDTH_X2; + RootComplex->Pcie[RPStart + 2].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 2], MaxWidth); + RootComplex->Pcie[RPStart + 2].Active =3D TRUE; + RootComplex->Pcie[RPStart + 3].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 3], MaxWidth); + RootComplex->Pcie[RPStart + 3].Active =3D TRUE; + break; + + case DevMapMode4: + MaxWidth =3D (RootComplex->Type =3D=3D RootComplexTypeA) ? LINK_WIDTH_= X4 : LINK_WIDTH_X2; + RootComplex->Pcie[RPStart].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootComple= x->Pcie[RPStart], MaxWidth); + RootComplex->Pcie[RPStart + 1].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 1], MaxWidth); + RootComplex->Pcie[RPStart + 1].Active =3D TRUE; + RootComplex->Pcie[RPStart + 2].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 2], MaxWidth); + RootComplex->Pcie[RPStart + 2].Active =3D TRUE; + RootComplex->Pcie[RPStart + 3].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootCo= mplex->Pcie[RPStart + 3], MaxWidth); + RootComplex->Pcie[RPStart + 3].Active =3D TRUE; + break; + + case DevMapMode1: + default: + MaxWidth =3D (RootComplex->Type =3D=3D RootComplexTypeA) ? LINK_WIDTH_= X16 : LINK_WIDTH_X8; + RootComplex->Pcie[RPStart].MaxWidth =3D PCIE_GET_MAX_WIDTH (RootComple= x->Pcie[RPStart], MaxWidth); + RootComplex->Pcie[RPStart + 1].Active =3D FALSE; + RootComplex->Pcie[RPStart + 2].Active =3D FALSE; + RootComplex->Pcie[RPStart + 3].Active =3D FALSE; + break; + } +} + +VOID +GetDefaultDevMap ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + if (RootComplex->Pcie[PcieController0].Active + && RootComplex->Pcie[PcieController1].Active + && RootComplex->Pcie[PcieController2].Active + && RootComplex->Pcie[PcieController3].Active) { + RootComplex->DefaultDevMapLow =3D DevMapMode4; + } else if (RootComplex->Pcie[PcieController0].Active + && RootComplex->Pcie[PcieController2].Active + && RootComplex->Pcie[PcieController3].Active) { + RootComplex->DefaultDevMapLow =3D DevMapMode3; + } else if (RootComplex->Pcie[PcieController0].Active + && RootComplex->Pcie[PcieController2].Active) { + RootComplex->DefaultDevMapLow =3D DevMapMode2; + } else { + RootComplex->DefaultDevMapLow =3D DevMapMode1; + } + + if (RootComplex->Pcie[PcieController4].Active + && RootComplex->Pcie[PcieController5].Active + && RootComplex->Pcie[PcieController6].Active + && RootComplex->Pcie[PcieController7].Active) { + RootComplex->DefaultDevMapHigh =3D DevMapMode4; + } else if (RootComplex->Pcie[PcieController4].Active + && RootComplex->Pcie[PcieController6].Active + && RootComplex->Pcie[PcieController7].Active) { + RootComplex->DefaultDevMapHigh =3D DevMapMode3; + } else if (RootComplex->Pcie[PcieController4].Active + && RootComplex->Pcie[PcieController6].Active) { + RootComplex->DefaultDevMapHigh =3D DevMapMode2; + } else { + RootComplex->DefaultDevMapHigh =3D DevMapMode1; + } + + if (RootComplex->DevMapLow =3D=3D 0) { + RootComplex->DevMapLow =3D RootComplex->DefaultDevMapLow; + } + + if (RootComplex->Type =3D=3D RootComplexTypeB && RootComplex->DevMapHigh= =3D=3D 0) { + RootComplex->DevMapHigh =3D RootComplex->DefaultDevMapHigh; + } + + SetRootComplexBifurcation (RootComplex, PcieController0, RootComplex->De= vMapLow); + if (RootComplex->Type =3D=3D RootComplexTypeB) { + SetRootComplexBifurcation (RootComplex, PcieController4, RootComplex->= DevMapHigh); + } +} + +VOID +GetLaneAllocation ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + EFI_STATUS Status; + INTN RPIndex; + NVPARAM NvParamOffset; + UINT32 Value, Width; + + // Retrieve lane allocation and capabilities for each controller + if (RootComplex->Type =3D=3D RootComplexTypeA) { + NvParamOffset =3D (RootComplex->Socket =3D=3D 0) ? NV_SI_RO_BOARD_S0_R= CA0_CFG : NV_SI_RO_BOARD_S1_RCA0_CFG; + NvParamOffset +=3D RootComplex->ID * NV_PARAM_ENTRYSIZE; + } else { + // + // There're two NVParam entries per RootComplexTypeB + // + NvParamOffset =3D (RootComplex->Socket =3D=3D 0) ? NV_SI_RO_BOARD_S0_R= CB0_LO_CFG : NV_SI_RO_BOARD_S1_RCB0_LO_CFG; + NvParamOffset +=3D (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENT= RYSIZE * 2); + } + + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (EFI_ERROR (Status)) { + Value =3D 0; + } + + for (RPIndex =3D 0; RPIndex < MaxPcieControllerOfRootComplexA; RPIndex++= ) { + Width =3D (Value >> (RPIndex * BITS_PER_BYTE)) & BYTE_MASK; + switch (Width) { + case 1: + case 2: + case 3: + case 4: + RootComplex->Pcie[RPIndex].MaxWidth =3D 1 << Width; + RootComplex->Pcie[RPIndex].MaxGen =3D LINK_SPEED_GEN3; + RootComplex->Pcie[RPIndex].Active =3D TRUE; + break; + + case 0: + default: + RootComplex->Pcie[RPIndex].MaxWidth =3D LINK_WIDTH_NONE; + RootComplex->Pcie[RPIndex].MaxGen =3D LINK_SPEED_NONE; + RootComplex->Pcie[RPIndex].Active =3D FALSE; + break; + } + } + + if (RootComplex->Type =3D=3D RootComplexTypeB) { + NvParamOffset +=3D NV_PARAM_ENTRYSIZE; + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (EFI_ERROR (Status)) { + Value =3D 0; + } + + for (RPIndex =3D MaxPcieControllerOfRootComplexA; RPIndex < MaxPcieCon= troller; RPIndex++) { + Width =3D (Value >> ((RPIndex - MaxPcieControllerOfRootComplexA) * B= ITS_PER_BYTE)) & BYTE_MASK; + switch (Width) { + case 1: + case 2: + case 3: + case 4: + RootComplex->Pcie[RPIndex].MaxWidth =3D 1 << Width; + RootComplex->Pcie[RPIndex].MaxGen =3D LINK_SPEED_GEN3; + RootComplex->Pcie[RPIndex].Active =3D TRUE; + break; + + case 0: + default: + RootComplex->Pcie[RPIndex].MaxWidth =3D LINK_WIDTH_NONE; + RootComplex->Pcie[RPIndex].MaxGen =3D LINK_SPEED_NONE; + RootComplex->Pcie[RPIndex].Active =3D FALSE; + break; + } + } + } + + // Do not proceed if no Root Port enabled + if (IsEmptyRC (RootComplex)) { + RootComplex->Active =3D FALSE; + } +} + +NVPARAM +GetGen3PresetNvParamOffset ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + NVPARAM NvParamOffset; + + if (RootComplex->Socket =3D=3D 0) { + if (RootComplex->Type =3D=3D RootComplexTypeA) { + if (RootComplex->ID < MaxRootComplexA) { + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCA0_TXRX_G3PRESET + RootCompl= ex->ID * NV_PARAM_ENTRYSIZE; + } else { + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCA4_TXRX_G3PRESET + (RootComp= lex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE; + } + } else { + // + // There're two NVParam entries per RootComplexTypeB + // + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCB0A_TXRX_G3PRESET + (RootCompl= ex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2); + } + } else if (RootComplex->Type =3D=3D RootComplexTypeA) { + if (RootComplex->ID < MaxRootComplexA) { + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCA2_TXRX_G3PRESET + (RootComple= x->ID - 2) * NV_PARAM_ENTRYSIZE; + } else { + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCA4_TXRX_G3PRESET + (RootComple= x->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE; + } + } else { + // + // There're two NVParam entries per RootComplexTypeB + // + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCB0A_TXRX_G3PRESET + (RootComplex= ->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2); + } + + return NvParamOffset; +} + +NVPARAM +GetGen4PresetNvParamOffset ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + NVPARAM NvParamOffset; + + if (RootComplex->Socket =3D=3D 0) { + if (RootComplex->Type =3D=3D RootComplexTypeA) { + if (RootComplex->ID < MaxRootComplexA) { + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCA0_TXRX_G4PRESET + RootCompl= ex->ID * NV_PARAM_ENTRYSIZE; + } else { + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCA4_TXRX_G4PRESET + (RootComp= lex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE; + } + } else { + // + // There're two NVParam entries per RootComplexTypeB + // + NvParamOffset =3D NV_SI_RO_BOARD_S0_RCB0A_TXRX_G4PRESET + (RootCompl= ex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2); + } + } else if (RootComplex->Type =3D=3D RootComplexTypeA) { + if (RootComplex->ID < MaxRootComplexA) { + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCA2_TXRX_G4PRESET + (RootComple= x->ID - 2) * NV_PARAM_ENTRYSIZE; + } else { + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCA4_TXRX_G4PRESET + (RootComple= x->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE; + } + } else { + // + // There're two NVParam entries per RootComplexTypeB + // + NvParamOffset =3D NV_SI_RO_BOARD_S1_RCB0A_TXRX_G4PRESET + (RootComplex= ->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2); + } + + return NvParamOffset; +} + +VOID +GetPresetSetting ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + EFI_STATUS Status; + INTN Index; + NVPARAM NvParamOffset; + UINT32 Value; + + // Load default value + for (Index =3D 0; Index < MaxPcieControllerOfRootComplexB; Index++) { + RootComplex->PresetGen3[Index] =3D PRESET_INVALID; + RootComplex->PresetGen4[Index] =3D PRESET_INVALID; + } + + NvParamOffset =3D GetGen3PresetNvParamOffset (RootComplex); + + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (!EFI_ERROR (Status)) { + for (Index =3D 0; Index < MaxPcieControllerOfRootComplexA; Index++) { + RootComplex->PresetGen3[Index] =3D (Value >> (Index * BITS_PER_BYTE)= ) & BYTE_MASK; + } + } + + if (RootComplex->Type =3D=3D RootComplexTypeB) { + NvParamOffset +=3D NV_PARAM_ENTRYSIZE; + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (!EFI_ERROR (Status)) { + for (Index =3D MaxPcieControllerOfRootComplexA; Index < MaxPcieContr= oller; Index++) { + RootComplex->PresetGen3[Index] =3D (Value >> ((Index - MaxPcieCont= rollerOfRootComplexA) * BITS_PER_BYTE)) & BYTE_MASK; + } + } + } + + NvParamOffset =3D GetGen4PresetNvParamOffset (RootComplex); + + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (!EFI_ERROR (Status)) { + for (Index =3D 0; Index < MaxPcieControllerOfRootComplexA; Index++) { + RootComplex->PresetGen4[Index] =3D (Value >> (Index * BITS_PER_BYTE)= ) & BYTE_MASK; + } + } + + if (RootComplex->Type =3D=3D RootComplexTypeB) { + NvParamOffset +=3D NV_PARAM_ENTRYSIZE; + Status =3D NVParamGet (NvParamOffset, NV_PERM_ALL, &Value); + if (!EFI_ERROR (Status)) { + for (Index =3D MaxPcieControllerOfRootComplexA; Index < MaxPcieContr= oller; Index++) { + RootComplex->PresetGen4[Index] =3D (Value >> ((Index - MaxPcieCont= rollerOfRootComplexA) * BITS_PER_BYTE)) & BYTE_MASK; + } + } + } +} + +VOID +GetMaxSpeedGen ( + AC01_ROOT_COMPLEX *RootComplex + ) +{ + UINT8 MaxSpeedGen[MaxPcieControllerOfRootComplexA] =3D { LINK_SPEED_GEN4= , LINK_SPEED_GEN4, LINK_SPEED_GEN4, LINK_SPEED_GEN4 }; // Bifurcati= on 0: RootComplexTypeA x16 / RootComplexTypeB x8 + UINT8 ErrataSpeedDevMap3[MaxPcieControllerOfRootComplexA] =3D { LINK_SPE= ED_GEN4, LINK_SPEED_GEN4, LINK_SPEED_GEN1, LINK_SPEED_GEN1 }; // Bifurcati= on 2: x8 x4 x4 (PCIE_ERRATA_SPEED1) + UINT8 ErrataSpeedDevMap4[MaxPcieControllerOfRootComplexA] =3D { LINK_SPE= ED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1 }; // Bifurcati= on 3: x4 x4 x4 x4 (PCIE_ERRATA_SPEED1) + UINT8 ErrataSpeedRcb[MaxPcieControllerOfRootComplexA] =3D { LINK_SPEED_G= EN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1 }; // RootCompl= exTypeB PCIE_ERRATA_SPEED1 + UINT8 Idx; + UINT8 *MaxGen; + + ASSERT (MaxPcieControllerOfRootComplexA =3D=3D 4); + ASSERT (MaxPcieController =3D=3D 8); + + // + // Due to hardware errata, for A0/A1* + // RootComplexTypeB is limited to Gen1 speed. + // RootComplexTypeA x16, x8 port supports up to Gen4, + // RootComplexTypeA x4 port only supports Gen1. + // + MaxGen =3D MaxSpeedGen; + if (RootComplex->Type =3D=3D RootComplexTypeB) { + if (RootComplex->Flags & PCIE_ERRATA_SPEED1) { + MaxGen =3D ErrataSpeedRcb; + } + } else { + switch (RootComplex->DevMapLow) { + case DevMapMode3: /* x8 x4 x4 */ + if (RootComplex->Flags & PCIE_ERRATA_SPEED1) { + MaxGen =3D ErrataSpeedDevMap3; + } + break; + + case DevMapMode4: /* x4 x4 x4 x4 */ + if (RootComplex->Flags & PCIE_ERRATA_SPEED1) { + MaxGen =3D ErrataSpeedDevMap4; + } + break; + + case DevMapMode2: /* x8 x8 */ + case DevMapMode1: /* x16 */ + default: + break; + } + } + + for (Idx =3D 0; Idx < MaxPcieControllerOfRootComplexA; Idx++) { + RootComplex->Pcie[Idx].MaxGen =3D RootComplex->Pcie[Idx].Active ? MaxG= en[Idx] : LINK_SPEED_NONE; + } + + if (RootComplex->Type =3D=3D RootComplexTypeB) { + for (Idx =3D MaxPcieControllerOfRootComplexA; Idx < MaxPcieController;= Idx++) { + RootComplex->Pcie[Idx].MaxGen =3D RootComplex->Pcie[Idx].Active ? + MaxGen[Idx - MaxPcieControllerOfRoot= ComplexA] : LINK_SPEED_NONE; + } + } +} + +VOID +ParseRootComplexNVParamData ( + IN OUT AC01_ROOT_COMPLEX *RootComplex + ) +{ + PLATFORM_INFO_HOB *PlatformHob; + UINT32 EFuse; + UINT8 RootComplexID; + VOID *Hob; + + EFuse =3D 0; + Hob =3D GetFirstGuidHob (&gPlatformInfoHobGuid); + if (Hob !=3D NULL) { + PlatformHob =3D (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob); + EFuse =3D PlatformHob->RcDisableMask[0] | (PlatformHob->RcDisableMask[= 1] << AC01_PCIE_MAX_RCS_PER_SOCKET); + DEBUG (( + DEBUG_INFO, + "RcDisableMask[0]: 0x%x [1]: 0x%x\n", + PlatformHob->RcDisableMask[0], + PlatformHob->RcDisableMask[1] + )); + + // Update errata flags for Ampere Altra + if ((PlatformHob->ScuProductId[0] & 0xff) =3D=3D 0x01) { + if (PlatformHob->AHBCId[0] =3D=3D 0x20100 + || PlatformHob->AHBCId[0] =3D=3D 0x21100 + || (IsSlaveSocketActive () + && (PlatformHob->AHBCId[1] =3D=3D 0x20100 + || PlatformHob->AHBCId[1] =3D=3D 0x21100))) + { + RootComplex->Flags |=3D PCIE_ERRATA_SPEED1; + DEBUG ((DEBUG_INFO, "RootComplex[%d]: Flags 0x%x\n", RootComplex->= ID, RootComplex->Flags)); + } + } + } + + RootComplexID =3D RootComplex->Socket * AC01_PCIE_MAX_RCS_PER_SOCKET + R= ootComplex->ID; + RootComplex->DefaultActive =3D !(EFuse & BIT (RootComplexID)) ? TRUE : F= ALSE; + if (!IsSlaveSocketActive () && RootComplex->Socket =3D=3D 1) { + RootComplex->DefaultActive =3D FALSE; + } + RootComplex->Active =3D RootComplex->Active && RootComplex->DefaultActiv= e; + + GetPresetSetting (RootComplex); + GetLaneAllocation (RootComplex); + GetDefaultDevMap (RootComplex); + GetMaxSpeedGen (RootComplex); +} --=20 2.17.1