From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.100, mailfrom: nathaniel.l.desimone@intel.com) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by groups.io with SMTP; Fri, 16 Aug 2019 17:52:41 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Aug 2019 17:52:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,395,1559545200"; d="scan'208";a="261263907" Received: from orsmsx102.amr.corp.intel.com ([10.22.225.129]) by orsmga001.jf.intel.com with ESMTP; 16 Aug 2019 17:52:39 -0700 Received: from orsmsx162.amr.corp.intel.com (10.22.240.85) by ORSMSX102.amr.corp.intel.com (10.22.225.129) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 16 Aug 2019 17:52:39 -0700 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.96]) by ORSMSX162.amr.corp.intel.com ([169.254.3.73]) with mapi id 14.03.0439.000; Fri, 16 Aug 2019 17:52:39 -0700 From: "Nate DeSimone" To: "Kubacki, Michael A" , "devel@edk2.groups.io" CC: "Chaganty, Rangasai V" , "Chiu, Chasel" , "Gao, Liming" , "Kinney, Michael D" , "Sinha, Ankit" Subject: Re: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances Thread-Topic: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances Thread-Index: AQHVVJEXmEMGfjYXoECoDZmZNIdLe6b+gviw Date: Sat, 17 Aug 2019 00:52:38 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE129AE@ORSMSX114.amr.corp.intel.com> References: <20190817001603.30632-1-michael.a.kubacki@intel.com> <20190817001603.30632-20-michael.a.kubacki@intel.com> In-Reply-To: <20190817001603.30632-20-michael.a.kubacki@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZTE3NjZmNGEtMGZhMS00MDI3LThmMzUtOTUxNDA3M2FmNjM0IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiWWE4MXZ4UTlhT0YxS3ZqZFdJMmI1K0NTV2Q1bjZlWk85SE5IcFhvWlwva0poTHdCcTQ4am9BeUZqZ1djQUcxVjMifQ== x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.139] MIME-Version: 1.0 Return-Path: nathaniel.l.desimone@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone -----Original Message----- From: Kubacki, Michael A=20 Sent: Friday, August 16, 2019 5:16 PM To: devel@edk2.groups.io Cc: Chaganty, Rangasai V ; Chiu, Chasel ; Desimone, Nathaniel L = ; Gao, Liming ; Kinney, Michael D ; Sinha, Ankit Subject: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI= library instances REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D2082 Adds PCH PEI library class instances. These libraries may also be compatible in other boot phases as indicated by the library type. * PeiDxeSmmBiosLockLib * PeiDxeSmmGpioLib * PeiDxeSmmPchCycleDecodingLib * PeiDxeSmmPchDmiWithS3Lib * PeiDxeSmmPchEspiLib * PeiDxeSmmPchGbeLib * PeiDxeSmmPchHsioLib * PeiDxeSmmPchInfoLib * PeiDxeSmmPchPcieRpLib * PeiDxeSmmPchPcrLib * PeiDxeSmmPchPmcLib * PeiDxeSmmPchSbiAccessLib * PeiDxeSmmPchSerialIoLib * PeiDxeSmmPchSerialIoUartLib * PeiDxeSmmPchWdtCommonLib * PeiDxeSmmPmcLib * PeiDxeSmmSataLib * PeiOcWdtLib * PeiOcWdtLibNull * PeiPchPolicyLib * PeiPchResetLib * PeiResetSystemLib * PeiSpiLib Cc: Sai Chaganty Cc: Chasel Chiu Cc: Nate DeSimone Cc: Liming Gao Cc: Michael D Kinney Cc: Ankit Sinha Signed-off-by: Michael Kubacki --- Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/PeiDxe= SmmBiosLockLib.inf | 40 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmG= pioLib.inf | 48 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLi= b/PeiDxeSmmPchCycleDecodingLib.inf | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiDxeS= mmPchEspiLib.inf | 38 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSm= mPchGbeLib.inf | 38 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeS= mmPchHsioLib.inf | 37 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeS= mmPchInfoLibCnl.inf | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDx= eSmmPchPcieRpLib.inf | 37 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSm= mPchPcrLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSm= mPchPmcLib.inf | 36 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/Pe= iDxeSmmPchSbiAccessLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pei= DxeSmmPchSerialIoLibCnl.inf | 39 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib= /PeiDxeSmmPchSerialIoUartLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/Pe= iDxeSmmPchWdtCommonLib.inf | 31 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeSmmPm= cLib.inf | 43 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeSmmS= ataLibCnl.inf | 32 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf= | 39 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLib= Null.inf | 24 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic= yLibCnl.inf | 86 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetL= ib.inf | 41 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetS= ystemLib.inf | 49 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf = | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrar= y.h | 117 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo= LibPrivate.h | 45 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch= SerialIoLibInternal.h | 16 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic= yLibrary.h | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/BiosLo= ckLib.c | 98 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c= | 553 ++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c = | 2710 ++++++++++++++++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNames.= c | 87 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNative= Lib.c | 234 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLi= b/PchCycleDecodingLib.c | 1136 ++++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEspi= Lib.c | 505 ++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLi= b.c | 82 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsio= Lib.c | 127 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo= Lib.c | 272 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo= LibClient.c | 87 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo= LibCnl.c | 386 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPc= ieRpLib.c | 183 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLi= b.c | 279 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLi= b.c | 101 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/Pc= hSbiAccessLib.c | 270 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch= SerialIoLib.c | 516 ++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch= SerialIoLibCnl.c | 181 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib= /PeiDxeSmmPchSerialIoUartLib.c | 372 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/Wd= tCommon.c | 242 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib.c = | 330 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.c = | 41 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCdf= .c | 101 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCnl= .c | 88 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c = | 130 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLib= Null.c | 23 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPr= intPolicy.c | 307 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPol= icy.c | 778 ++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic= yLib.c | 739 ++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic= yLibCnl.c | 169 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMe= mPolicyLib.c | 318 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c = | 109 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetS= ystemLib.c | 257 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c = | 217 ++ 60 files changed, 13130 insertions(+) diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLo= ckLib/PeiDxeSmmBiosLockLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Lib= rary/PeiDxeSmmBiosLockLib/PeiDxeSmmBiosLockLib.inf new file mode 100644 index 0000000000..6db81f6cf3 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/P= eiDxeSmmBiosLockLib.inf @@ -0,0 +1,40 @@ +## @file +# BIOS LOCK library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmBiosLockLib +FILE_GUID =3D 64EBA6B1-CC36-4C2E-A0F5-D90199432E6C +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D BiosLockLib + + +[LibraryClasses] +BaseLib +DebugLib +PcdLib +PciSegmentLib +S3BootScriptLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +BiosLockLib.c + + +[Pcd] +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/PeiDxeSmmGpioLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pei= DxeSmmGpioLib/PeiDxeSmmGpioLib.inf new file mode 100644 index 0000000000..00d06591fc --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDx= eSmmGpioLib.inf @@ -0,0 +1,48 @@ +## @file +# Component description file for the PeiDxeSmmGpioLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmGpioLib +FILE_GUID =3D 16EC5CA8-8195-4847-B6CB-662BD7B763F2 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D GpioLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# + + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PrintLib +PchCycleDecodingLib +PchSbiAccessLib +PmcPrivateLib +GpioPrivateLib +SataLib +GpioHelpersLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +GpioLib.c +GpioLibrary.h +GpioNativeLib.c +GpioInit.c +GpioNames.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCyc= leDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/CoffeelakeSi= liconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecoding= Lib.inf new file mode 100644 index 0000000000..2a53f42004 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecod= ingLib/PeiDxeSmmPchCycleDecodingLib.inf @@ -0,0 +1,42 @@ +## @file +# PCH cycle decoding Lib. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchCycleDecodingLib +FILE_GUID =3D 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchCycleDecodingLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib +PchInfoLib +PchPcrLib +PchDmiLib +PchEspiLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec +PcAtChipsetPkg/PcAtChipsetPkg.dec + +[Sources] +PchCycleDecodingLib.c + +[Pcd] +gSiPkgTokenSpaceGuid.PcdSiHpetBaseAddress ## CONSUMES +gPcAtChipsetPkgTokenSpaceGuid.PcdIoApicBaseAddress ## CONSUMES diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEsp= iLib/PeiDxeSmmPchEspiLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Libra= ry/PeiDxeSmmPchEspiLib/PeiDxeSmmPchEspiLib.inf new file mode 100644 index 0000000000..a775210984 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/Pe= iDxeSmmPchEspiLib.inf @@ -0,0 +1,38 @@ +## @file +# Component description file for the PeiDxeSmmPchEspiLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchEspiLib +FILE_GUID =3D 7F25F990-7989-4413-B414-1EDE557E9389 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchEspiLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# + + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PchPcrLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchEspiLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbe= Lib/PeiDxeSmmPchGbeLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library= /PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf new file mode 100644 index 0000000000..a685104249 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/Pei= DxeSmmPchGbeLib.inf @@ -0,0 +1,38 @@ +## @file +# PCH Gbe Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchGbeLib +FILE_GUID =3D FC022ED0-6EB3-43E1-A740-0BA27CBBD010 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchGbeLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib +PchInfoLib +PchPcrLib +PchCycleDecodingLib +PmcPrivateLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchGbeLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsi= oLib/PeiDxeSmmPchHsioLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Libra= ry/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf new file mode 100644 index 0000000000..7c67e0fa20 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/Pe= iDxeSmmPchHsioLib.inf @@ -0,0 +1,37 @@ +## @file +# PCH HSIO Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchHsioLib +FILE_GUID =3D 6B2D3D0D-9A04-4E7C-AE84-1C2EF2E00E2E +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchHsioLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +MmPciLib +PchInfoLib +PchPcrLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchHsioLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInf= oLib/PeiDxeSmmPchInfoLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Li= brary/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibCnl.inf new file mode 100644 index 0000000000..b9781de810 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/Pe= iDxeSmmPchInfoLibCnl.inf @@ -0,0 +1,42 @@ +## @file +# PCH information library for PCH. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchInfoLibCnl +FILE_GUID =3D 455CD363-0E78-46B7-8DD3-634003F1614F +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchInfoLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PrintLib +PciSegmentLib +PchPcrLib +PmcPrivateLib +PcdLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchInfoLib.c +PchInfoLibClient.c +PchInfoLibCnl.c + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPci= eRpLib/PeiDxeSmmPchPcieRpLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/L= ibrary/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf new file mode 100644 index 0000000000..b1ee095423 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/= PeiDxeSmmPchPcieRpLib.inf @@ -0,0 +1,37 @@ +## @file +# PCH PCIE root port Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchPcieRpLib +FILE_GUID =3D B4129C2C-E0C5-4E04-A82A-C61D4F0B2C75 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchPcieRpLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib +PchInfoLib +PchPcrLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchPcieRpLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcr= Lib/PeiDxeSmmPchPcrLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library= /PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf new file mode 100644 index 0000000000..0244e1c0c8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/Pei= DxeSmmPchPcrLib.inf @@ -0,0 +1,35 @@ +## @file +# PCH PCR Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchPcrLib +FILE_GUID =3D 117C8D19-445B-46BF-B624-109F63709375 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchPcrLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PchInfoLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchPcrLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmc= Lib/PeiDxeSmmPchPmcLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library= /PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf new file mode 100644 index 0000000000..3b1f1e467b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/Pei= DxeSmmPchPmcLib.inf @@ -0,0 +1,36 @@ +## @file +# PEI/DXE/SMM PCH PMC Lib. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchPmcLib +FILE_GUID =3D 9D60C364-5086-41E3-BC9D-C62AB7233DBF +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchPmcLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +MmPciLib +PchCycleDecodingLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchPmcLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbi= AccessLib/PeiDxeSmmPchSbiAccessLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg= /Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf new file mode 100644 index 0000000000..ceb109168b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessL= ib/PeiDxeSmmPchSbiAccessLib.inf @@ -0,0 +1,35 @@ +## @file +# PCH SBI access library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchSbiAccessLib +FILE_GUID =3D 96ECB0FB-A975-4DC8-B88A-D90C3378CE87 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchSbiAccessLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchSbiAccessLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoLib/PeiDxeSmmPchSerialIoLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPk= g/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLibCnl.inf new file mode 100644 index 0000000000..3bfada0b22 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLi= b/PeiDxeSmmPchSerialIoLibCnl.inf @@ -0,0 +1,39 @@ +## @file +# Component description file for PEI/DXE/SMM PCH Serial IO Lib. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchSerialIoLibCnl +FILE_GUID =3D 613A22A2-5736-40f8-909B-DF10EA389C72 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchSerialIoLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PcdLib +PciSegmentLib +GpioPrivateLib +PchPcrLib +PchSerialIoUartLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchSerialIoLib.c +PchSerialIoLibCnl.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf b/Silicon/Intel/CoffeelakeSili= conPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.= inf new file mode 100644 index 0000000000..1becfc7a96 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUa= rtLib/PeiDxeSmmPchSerialIoUartLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for PCH Serial IO UART Lib. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchSerialIoUartLib +FILE_GUID =3D 55463A54-FD0D-4e8e-8D57-D54FAAEFDC2F +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchSerialIoUartLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PchSerialIoLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PeiDxeSmmPchSerialIoUartLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdt= CommonLib/PeiDxeSmmPchWdtCommonLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg= /Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf new file mode 100644 index 0000000000..8a01a749bf --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonL= ib/PeiDxeSmmPchWdtCommonLib.inf @@ -0,0 +1,31 @@ +## @file +# Component description file for the PchWdtCommonLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PeiDxeSmmPchWdtCommonLib + FILE_GUID =3D 171F78D2-0A52-4692-8830-AB693791EA23 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PchWdtCommonLib + +[Sources] + WdtCommon.c + +[Packages] + MdePkg/MdePkg.dec + CoffeelakeSiliconPkg/SiPkg.dec + +[LibraryClasses] + IoLib + DebugLib + PmcLib + +[Pcd] + gSiPkgTokenSpaceGuid.PcdOcEnableWdtforDebug ## CONSUMES diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib= /PeiDxeSmmPmcLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDx= eSmmPmcLib/PeiDxeSmmPmcLib.inf new file mode 100644 index 0000000000..78e212eeb0 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxe= SmmPmcLib.inf @@ -0,0 +1,43 @@ +## @file +# PEI/DXE/SMM PCH PMC Lib. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPmcLib +FILE_GUID =3D 9D60C364-5086-41E3-BC9D-C62AB7233DBF +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PmcLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib +PchCycleDecodingLib +PchPcrLib +PchInfoLib +PmcPrivateLib +BaseMemoryLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Pcd] +gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress + + +[Sources] +PmcLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLi= b/PeiDxeSmmSataLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/= PeiDxeSmmSataLib/PeiDxeSmmSataLibCnl.inf new file mode 100644 index 0000000000..128b348b3d --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDx= eSmmSataLibCnl.inf @@ -0,0 +1,32 @@ +## @file +# PEI/DXE/SMM PCH SATA library for Cannon Lake PCH. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchSataLibCnl +FILE_GUID =3D 5163ECE3-5372-47E1-B057-2282E753DD55 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D SataLib + +[LibraryClasses] +BaseLib +PciSegmentLib +PchInfoLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + +[Sources] +SataLib.c +SataLibCnl.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/Pei= OcWdtLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/P= eiOcWdtLib.inf new file mode 100644 index 0000000000..37d0c80ea4 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLi= b.inf @@ -0,0 +1,39 @@ +## @file +# Component Description File for OcWdt Support. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiOcWdtLib +FILE_GUID =3D D5207C23-3632-4078-A671-3B5C364B2BDB +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D OcWdtLib + + +[LibraryClasses] +IoLib +DebugLib +PeiServicesLib +PchWdtCommonLib +PmcLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PeiOcWdtLib.c + + +[Ppis] +gWdtPpiGuid ## PRODUCES + +[Pcd] +gSiPkgTokenSpaceGuid.PcdOcEnableWdtforDebug ## CONSUMES diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull= /PeiOcWdtLibNull.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOc= WdtLibNull/PeiOcWdtLibNull.inf new file mode 100644 index 0000000000..68ff41ef7f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcW= dtLibNull.inf @@ -0,0 +1,24 @@ +## @file +# Component Description File for OcWdt Support. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiOcWdtLib +FILE_GUID =3D DB65B36B-E276-4A2b-AB20-61764889E483 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D OcWdtLib + + +[Packages] +MdePkg/MdePkg.dec + + +[Sources] +PeiOcWdtLibNull.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PeiPchPolicyLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pe= iPchPolicyLib/PeiPchPolicyLibCnl.inf new file mode 100644 index 0000000000..49e63cfc51 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPch= PolicyLibCnl.inf @@ -0,0 +1,86 @@ +## @file +# Component description file for the PeiPchPolicy libbrary. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiPchPolicyLibCnl +FILE_GUID =3D BB1AC992-B2CA-4744-84B7-915C185576C5 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D PchPolicyLib + + +[LibraryClasses] +DebugLib +IoLib +PcdLib +PeiServicesLib +BaseMemoryLib +MemoryAllocationLib +PchInfoLib +ConfigBlockLib +SiConfigBlockLib +SataLib +PchPcieRpLib +CpuPlatformLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Pcd] +gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress +gSiPkgTokenSpaceGuid.PcdSerialIoUartDebugEnable +gSiPkgTokenSpaceGuid.PcdSerialIoUartNumber + + +[Sources] +PeiPchPolicyLib.c +PeiPchPolicyLibCnl.c +PeiPchPolicyLibrary.h +PeiPchPreMemPolicyLib.c +PchPrintPolicy.c +PchPreMemPrintPolicy.c + +[Guids] +gPchGeneralConfigGuid ## CONSUMES +gPcieRpConfigGuid ## CONSUMES +gSataConfigGuid ## CONSUMES +gIoApicConfigGuid ## CONSUMES +gDmiConfigGuid ## CONSUMES +gFlashProtectionConfigGuid ## CONSUMES +gHdAudioConfigGuid ## CONSUMES +gInterruptConfigGuid ## CONSUMES +gIshConfigGuid ## CONSUMES +gLanConfigGuid ## CONSUMES +gLockDownConfigGuid ## CONSUMES +gP2sbConfigGuid ## CONSUMES +gPmConfigGuid ## CONSUMES +gScsConfigGuid ## CONSUMES +gSerialIoConfigGuid ## CONSUMES +gSerialIrqConfigGuid ## CONSUMES +gThermalConfigGuid ## CONSUMES +gUsbConfigGuid ## CONSUMES +gEspiConfigGuid ## CONSUMES +gCnviConfigGuid ## CONSUMES +gHsioConfigGuid ## CONSUMES +gPchGeneralPreMemConfigGuid ## COMSUMES +gDciPreMemConfigGuid ## CONSUMES +gWatchDogPreMemConfigGuid ## CONSUMES +gPchTraceHubPreMemConfigGuid ## CONSUMES +gSmbusPreMemConfigGuid ## CONSUMES +gLpcPreMemConfigGuid ## CONSUMES +gHsioPciePreMemConfigGuid ## CONSUMES +gHsioSataPreMemConfigGuid ## CONSUMES +gPcieRpPreMemConfigGuid ## CONSUMES +gHdAudioPreMemConfigGuid ## CONSUMES +gIshPreMemConfigGuid ## CONSUMES + +[Ppis] diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/= PeiPchResetLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchR= esetLib/PeiPchResetLib.inf new file mode 100644 index 0000000000..41e339a2e8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchR= esetLib.inf @@ -0,0 +1,41 @@ +## @file +# Component description file for PCH Reset Lib Pei Phase +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiPchResetLib +FILE_GUID =3D DB91FFF0-5B99-4A88-9EC8-183A2106DCA2 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D PchResetLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] +DebugLib +PeiServicesLib +PeiServicesTablePointerLib +MemoryAllocationLib +ResetSystemLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchReset.c + +[Ppis] +gEfiPeiReset2PpiGuid ## PRODUCES + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemL= ib/PeiResetSystemLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/P= eiResetSystemLib/PeiResetSystemLib.inf new file mode 100644 index 0000000000..f8f8bf1b66 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiR= esetSystemLib.inf @@ -0,0 +1,49 @@ +## @file +# Component description file for Intel Ich7 Reset System Library. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiResetSystemLib +FILE_GUID =3D D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +UEFI_SPECIFICATION_VERSION =3D 2.00 +LIBRARY_CLASS =3D ResetSystemLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] +IoLib +DebugLib +BaseMemoryLib +PeiServicesLib +PmcLib +PmcPrivateLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PeiResetSystemLib.c + + +[Ppis] +gMeDidSentPpiGuid ## CONSUMES +gPchResetCallbackPpiGuid ## CONSUMES + + +[Guids] +gPchGlobalResetGuid + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSp= iLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiL= ib.inf new file mode 100644 index 0000000000..fb2fad78d3 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.in= f @@ -0,0 +1,42 @@ +## @file +# Component description file for PCH Reset Lib Pei Phase +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiSpiLib +FILE_GUID =3D 4998447D-7948-448F-AB75-96E24E18FF23 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D SpiLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] +DebugLib +PeiServicesLib +PeiServicesTablePointerLib +MemoryAllocationLib +PciSegmentLib +PchSpiCommonLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchSpi.c + + +[Ppis] +gPchSpiPpiGuid ## PRODUCES + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/GpioLibrary.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmG= pioLib/GpioLibrary.h new file mode 100644 index 0000000000..7a480b6cad --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioL= ibrary.h @@ -0,0 +1,117 @@ +/** @file + Header file for GPIO Lib implementation. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _GPIO_LIBRARY_H_ +#define _GPIO_LIBRARY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// BIT15-0 - pad number +// BIT31-16 - group info +// BIT23- 16 - group index +// BIT31- 24 - chipset ID +#define PAD_INFO_MASK 0x0000FFFF +#define GROUP_INFO_POSITION 16 +#define GROUP_INFO_MASK 0xFFFF0000 +#define GROUP_INDEX_MASK 0x00FF0000 +#define UNIQUE_ID_MASK 0xFF000000 +#define UNIQUE_ID_POSITION 24 + +#define GPIO_PAD_DEF(Group,Pad) (UINT32)(((Group) << 16) + (= Pad)) +#define GPIO_GROUP_DEF(Index,ChipsetId) ((Index) | ((ChipsetId) << 8= )) +#define GPIO_GET_GROUP_INDEX(Group) ((Group) & 0xFF) +#define GPIO_GET_GROUP_FROM_PAD(Pad) ((Pad) >> 16) +#define GPIO_GET_GROUP_INDEX_FROM_PAD(Pad) GPIO_GET_GROUP_INDEX (((Pad)= >> 16)) +#define GPIO_GET_PAD_NUMBER(Pad) ((Pad) & 0xFFFF) +#define GPIO_GET_CHIPSET_ID(Pad) ((Pad) >> 24) + +#define GPIO_GET_PAD_POSITION(PadNumber) ((PadNumber) % 32) +#define GPIO_GET_DW_NUM(PadNumber) ((PadNumber) / 32u) + +// +// Number of PADCFG_DW registers +// +#define GPIO_PADCFG_DW_REG_NUMBER 4 + +/** + This internal procedure will calculate GPIO_RESET_CONFIG value (new typ= e) + based on provided PadRstCfg for a specific GPIO Pad. + + @param[in] GpioPad GPIO Pad + @param[in] PadRstCfg GPIO PadRstCfg value + + @retval GpioResetConfig GPIO Reset configuration (new type) +**/ +GPIO_RESET_CONFIG +GpioResetConfigFromPadRstCfg ( + IN GPIO_PAD GpioPad, + IN UINT32 PadRstCfg + ); + +/** + This internal procedure will calculate PadRstCfg register value based + on provided GPIO Reset configuration for a certain pad. + + @param[in] GpioPad GPIO Pad + @param[in] GpioResetConfig GPIO Reset configuration + @param[out] PadRstCfg GPIO PadRstCfg value + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid configuration +**/ +EFI_STATUS +GpioPadRstCfgFromResetConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_RESET_CONFIG GpioResetConfig, + OUT UINT32 *PadRstCfg + ); + +/** + This procedure will calculate PADCFG register value based on GpioConfig = data + + @param[in] GpioPad GPIO Pad + @param[in] GpioConfig GPIO Configuration data + @param[out] PadCfgDwReg PADCFG DWx register value + @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits= to be modified +**/ +VOID +GpioPadCfgRegValueFromGpioConfig ( + IN GPIO_PAD GpioPad, + IN CONST GPIO_CONFIG *GpioConfig, + OUT UINT32 *PadCfgDwReg, + OUT UINT32 *PadCfgDwRegMask + ); + +/** + Generates GPIO group name from GroupIndex + + @param[in] GroupIndex Gpio GroupIndex + + @retval CHAR8* Pointer to the GPIO group name +**/ +CONST +CHAR8* +GpioGetGroupName ( + IN UINT32 GroupIndex + ); + +#endif // _GPIO_LIBRARY_H_ diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInf= oLib/PchInfoLibPrivate.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/P= eiDxeSmmPchInfoLib/PchInfoLibPrivate.h new file mode 100644 index 0000000000..79e03fef44 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/Pc= hInfoLibPrivate.h @@ -0,0 +1,45 @@ +/** @file + Private header for PCH Info Lib. + + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +/** + Structure for PCH SKU string mapping +**/ +struct PCH_SKU_STRING { + UINT16 Id; + CHAR8 *String; +}; + +extern struct PCH_SKU_STRING mSkuStrs[]; + +/** + Determine Pch Series based on Device Id + + @param[in] LpcDeviceId Lpc Device Id + + @retval PCH_SERIES Pch Series +**/ +PCH_SERIES +PchSeriesFromLpcDid ( + IN UINT16 LpcDeviceId + ); + +/** +Determine Pch Generation based on Device Id + +@param[in] LpcDeviceId Lpc Device Id + +@retval PCH_GENERATION Pch Generation +**/ +PCH_GENERATION +PchGenerationFromDid ( + IN UINT16 LpcDeviceId + ); + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoLib/PchSerialIoLibInternal.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/= Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLibInternal.h new file mode 100644 index 0000000000..17e4bb863a --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLi= b/PchSerialIoLibInternal.h @@ -0,0 +1,16 @@ +/** @file + Header file for PchSerialIoLibInternal. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PCH_SERIAL_IO_LIB_INTERNAL_H_ +#define _PCH_SERIAL_IO_LIB_INTERNAL_H_ + +typedef struct { + UINT8 DevNum; + UINT8 FuncNum; +} SERIAL_IO_BDF_NUMBERS; +#endif diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PeiPchPolicyLibrary.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pei= PchPolicyLib/PeiPchPolicyLibrary.h new file mode 100644 index 0000000000..abd7e63365 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPch= PolicyLibrary.h @@ -0,0 +1,35 @@ +/** @file + Header file for the PeiPchPolicy library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PEI_PCH_POLICY_LIBRARY_H_ +#define _PEI_PCH_POLICY_LIBRARY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Adds interrupt configuration for device + + @param[in/out] InterruptConfig Pointer to interrupt config +**/ +VOID +LoadDeviceInterruptConfig ( + IN OUT PCH_INTERRUPT_CONFIG *InterruptConfig + ); + +#endif // _PEI_PCH_POLICY_LIBRARY_H_ diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLo= ckLib/BiosLockLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxe= SmmBiosLockLib/BiosLockLib.c new file mode 100644 index 0000000000..20c024e893 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/B= iosLockLib.c @@ -0,0 +1,98 @@ +/** @file + Bios Lock library. + + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Enable BIOS lock. This will set the LE (Lock Enable) and EISS (Enable In= SMM.STS). + When this is set, attempts to write the WPD (Write Protect Disable) bit = in PCH + will cause a SMI which will allow the BIOS to verify that the write is f= rom a valid source. + + Bios should always enable LockDownConfig.BiosLock policy to set Bios Loc= k bit in FRC. + If capsule udpate is enabled, it's expected to not do BiosLock by settin= g BiosLock policy disable + so it can udpate BIOS region. + After flash update, it should utilize this lib to do BiosLock for securi= ty. +**/ +VOID +BiosLockEnable ( + VOID + ) +{ + UINT64 LpcBaseAddress; + UINT64 SpiBaseAddress; + + LpcBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + SpiBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + + /// + /// PCH BIOS Spec Flash Security Recommendation + /// + /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH b= y setting + /// SPI/eSPI/LPC PCI offset DCh[1] =3D 1b. + /// When this bit is set, attempts to write the Write Protect Disable (W= PD) bit + /// in PCH will cause a SMI which will allow the BIOS to verify that the= write is + /// from a valid source. + /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] =3D 0= b to enable + /// BIOS region protection before exiting the SMI handler. + /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = =3D 1b) to keep + /// BLE feature enabled after booting to the OS. + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the= PCH to + /// ensure SMM protection of flash. + /// RC installs a default SMI handler that clears WPD. + /// There could be additional SMI handler to log such attempt if desired= . + /// + /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the P= CH by setting + /// SPI PCI offset DCh[5] =3D 1b for SPI or setting eSPI PCI offset DCh[= 5] =3D 1b for eSPI. + /// When this bit is set, the BIOS region is not writable until SMM sets= the InSMM.STS bit, + /// to ensure BIOS can only be modified from SMM. Please refer to CPU BW= G for more details + /// on InSMM.STS bit. + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the= PCH to ensure + /// SMM protection of flash. + /// SPI PCI offset DCh[1] =3D 1b for SPI or setting eSPI PCI offset DCh[= 1] =3D 1b for eSPI. + /// When this bit is set, EISS is locked down. + /// + PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, B_SPI_CFG_BC_EISS | B_SPI_= CFG_BC_LE); + S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint8, + PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC, + 1, + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress= + R_SPI_CFG_BC) + ); + PciSegmentOr8 (LpcBaseAddress + R_LPC_CFG_BC, B_LPC_CFG_BC_EISS | B_LPC_= CFG_BC_LE); + S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint8, + PcdGet64 (PcdPciExpressBaseAddress) + LpcBaseAddress + R_LPC_CFG_BC, + 1, + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + LpcBaseAddress= + R_LPC_CFG_BC) + ); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/GpioInit.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpio= Lib/GpioInit.c new file mode 100644 index 0000000000..76eb3a9b81 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioI= nit.c @@ -0,0 +1,553 @@ +/** @file + This file contains routines for GPIO initialization + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "GpioLibrary.h" +#include + +// +// GPIO_GROUP_DW_DATA structure is used by GpioConfigurePch function +// to cache values which will be programmed into respective GPIO registers +// after all GpioPads are processed. This way MMIO accesses are decreased +// and instead of doing one programming for one GpioPad there is only +// one access for whole register. +// +typedef struct { + UINT32 HostSoftOwnReg; + UINT32 HostSoftOwnRegMask; + UINT32 GpiGpeEnReg; + UINT32 GpiGpeEnRegMask; + UINT32 GpiNmiEnReg; + UINT32 GpiNmiEnRegMask; + UINT32 GpiSmiEnReg; + UINT32 GpiSmiEnRegMask; + UINT32 ConfigUnlockMask; + UINT32 OutputUnlockMask; +} GPIO_GROUP_DW_DATA; + +// +// GPIO_GROUP_DW_NUMBER contains number of DWords required to +// store Pad data for all groups. Each pad uses one bit. +// +// For Cannonlake only vGPIO group has >32 pads but those pads +// will not be accessed by this function so GPIO_GROUP_DW_NUMBER can be 1 +// +#define GPIO_GROUP_DW_NUMBER 1 + +/** + Get GPIO DW Register values (HOSTSW_OWN, GPE_EN, NMI_EN, Lock). + + @param[in] PadNumber GPIO pad number + @param[in] GpioConfig GPIO Config data + @param[in out] DwRegsValues Values for GPIO DW Registers + + @retval None +**/ +STATIC +VOID +GpioDwRegValueFromGpioConfig ( + IN UINT32 PadNumber, + IN CONST GPIO_CONFIG *GpioConfig, + IN OUT GPIO_GROUP_DW_DATA *GroupDwData + ) +{ + UINT32 PadBitPosition; + UINT32 DwNum; + + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + + if (DwNum >=3D GPIO_GROUP_DW_NUMBER) { + ASSERT (FALSE); + return; + } + // + // Update value to be programmed in HOSTSW_OWN register + // + GroupDwData[DwNum].HostSoftOwnRegMask |=3D (GpioConfig->HostSoftPadOwn &= 0x1) << PadBitPosition; + GroupDwData[DwNum].HostSoftOwnReg |=3D (GpioConfig->HostSoftPadOwn >> 0x= 1) << PadBitPosition; + + // + // Update value to be programmed in GPI_GPE_EN register + // + GroupDwData[DwNum].GpiGpeEnRegMask |=3D (GpioConfig->InterruptConfig & 0= x1) << PadBitPosition; + GroupDwData[DwNum].GpiGpeEnReg |=3D ((GpioConfig->InterruptConfig & Gpio= IntSci) >> 3) << PadBitPosition; + + // + // Update value to be programmed in GPI_NMI_EN register + // + GroupDwData[DwNum].GpiNmiEnRegMask |=3D (GpioConfig->InterruptConfig & 0= x1) << PadBitPosition; + GroupDwData[DwNum].GpiNmiEnReg |=3D ((GpioConfig->InterruptConfig & Gpio= IntNmi) >> 1) << PadBitPosition; + + // + // Update value to be programmed in GPI_SMI_EN register + GroupDwData[DwNum].GpiSmiEnRegMask |=3D (GpioConfig->InterruptConfig & 0= x1) << PadBitPosition; + GroupDwData[DwNum].GpiSmiEnReg |=3D ((GpioConfig->InterruptConfig & Gpio= IntSmi) >> 2) << PadBitPosition; + if ((GpioConfig->InterruptConfig & GpioIntSmi) =3D=3D GpioIntSmi) { + GroupDwData[DwNum].HostSoftOwnRegMask |=3D 1 << PadBitPosition; + GroupDwData[DwNum].HostSoftOwnReg |=3D 1 << PadBitPosition; + } + + // + // Update information on Pad Configuration Lock + // + GroupDwData[DwNum].ConfigUnlockMask |=3D ((GpioConfig->LockConfig >> 1) = & 0x1) << PadBitPosition; + + // + // Update information on Pad Configuration Lock Tx + // + GroupDwData[DwNum].OutputUnlockMask |=3D ((GpioConfig->LockConfig >> 3) = & 0x1) << PadBitPosition; + + // + // if pad in GpioMode is an output default action should be to leave out= put unlocked + // + if ((GpioConfig->PadMode =3D=3D GpioPadModeGpio) && + (GpioConfig->Direction =3D=3D GpioDirOut) && + ((GpioConfig->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) =3D= =3D GpioLockDefault)) { + GroupDwData[DwNum].OutputUnlockMask |=3D 0x1 << PadBitPosition; + } +} + +/** + This internal procedure will scan GPIO initialization table and unlock + all pads present in it + + @param[in] NumberOfItem Number of GPIO pad records in tabl= e + @param[in] GpioInitTableAddress GPIO initialization table + @param[in] Index Index of GPIO Initialization table= record + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +STATIC +EFI_STATUS +GpioUnlockPadsForAGroup ( + IN UINT32 NumberOfItems, + IN GPIO_INIT_CONFIG *GpioInitTableAddress, + IN UINT32 Index + ) +{ + UINT32 PadsToUnlock[GPIO_GROUP_DW_NUMBER]; + UINT32 DwNum; + UINT32 PadBitPosition; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + CONST GPIO_INIT_CONFIG *GpioData; + GPIO_GROUP Group; + UINT32 GroupIndex; + UINT32 PadNumber; + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GpioData =3D &GpioInitTableAddress[Index]; + Group =3D GpioGetGroupFromGpioPad (GpioData->GpioPad); + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioData->GpioPad); + + ZeroMem (PadsToUnlock, sizeof (PadsToUnlock)); + // + // Loop through pads for one group. If pad belongs to a different group = then + // break and move to register programming. + // + while (Index < NumberOfItems) { + + GpioData =3D &GpioInitTableAddress[Index]; + if (GroupIndex !=3D GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) = { + //if next pad is from different group then break loop + break; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioData->GpioPad); + // + // Check if legal pin number + // + if (PadNumber >=3D GpioGroupInfo[GroupIndex].PadPerGroup) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible r= ange for group %d\n", PadNumber, GroupIndex)); + return EFI_INVALID_PARAMETER; + } + + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + + if (DwNum >=3D GPIO_GROUP_DW_NUMBER) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + // + // Update pads which need to be unlocked + // + PadsToUnlock[DwNum] |=3D 0x1 << PadBitPosition; + + //Move to next item + Index++; + } + + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].= PadPerGroup); DwNum++) { + // + // Unlock pads + // + if (PadsToUnlock[DwNum] !=3D 0) { + GpioUnlockPadCfgForGroupDw (Group, DwNum, PadsToUnlock[DwNum]); + GpioUnlockPadCfgTxForGroupDw (Group, DwNum, PadsToUnlock[DwNum]); + } + } + + return EFI_SUCCESS; +} + +/** + This procedure will initialize multiple PCH GPIO pins + + @param[in] NumberofItem Number of GPIO pads to be updated + @param[in] GpioInitTableAddress GPIO initialization table + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +STATIC +EFI_STATUS +GpioConfigurePch ( + IN UINT32 NumberOfItems, + IN GPIO_INIT_CONFIG *GpioInitTableAddress + ) +{ + UINT32 Index; + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER]; + UINT32 PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER]; + UINT32 PadCfgReg; + GPIO_GROUP_DW_DATA GroupDwData[GPIO_GROUP_DW_NUMBER]; + UINT32 DwNum; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + GPIO_PAD_OWN PadOwnVal; + CONST GPIO_INIT_CONFIG *GpioData; + UINT32 GroupIndex; + UINT32 PadNumber; + PCH_SBI_PID GpioCom; + + PadOwnVal =3D GpioPadOwnHost; + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + Index =3D 0; + while (Index < NumberOfItems) { + + GpioData =3D &GpioInitTableAddress[Index]; + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioData->GpioPad); + GpioCom =3D GpioGroupInfo[GroupIndex].Community; + + DEBUG_CODE_BEGIN(); + if (!GpioIsCorrectPadForThisChipset (GpioData->GpioPad)) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad (0x%08x) used on= this chipset!\n", GpioData->GpioPad)); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + DEBUG_CODE_END (); + + // + // Unlock pads for a given group which are going to be reconfigured + // + // + // Because PADCFGLOCK/LOCKTX register reset domain is Powergood, lock = settings + // will get back to default only after G3 or DeepSx transition. On the= other hand GpioPads + // configuration is controlled by a configurable type of reset - PadRs= tCfg. This means that if + // PadRstCfg !=3D Powergood GpioPad will have its configuration locked= despite it being not the + // one desired by BIOS. Before reconfiguring all pads they will get un= locked. + // + GpioUnlockPadsForAGroup (NumberOfItems, GpioInitTableAddress, Index); + + ZeroMem (GroupDwData, sizeof (GroupDwData)); + // + // Loop through pads for one group. If pad belongs to a different grou= p then + // break and move to register programming. + // + while (Index < NumberOfItems) { + + GpioData =3D &GpioInitTableAddress[Index]; + if (GroupIndex !=3D GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)= ) { + //if next pad is from different group then break loop + break; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioData->GpioPad); + + DEBUG_CODE_BEGIN (); + // + // Check if legal pin number + // + if (PadNumber >=3D GpioGroupInfo[GroupIndex].PadPerGroup) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible= range for group %d\n", PadNumber, GroupIndex)); + return EFI_INVALID_PARAMETER; + } + + // + // Check if selected GPIO Pad is not owned by CSME/ISH + // + GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal); + + if (PadOwnVal !=3D GpioPadOwnHost) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host = (Group=3D%d, Pad=3D%d)!\n", GroupIndex, PadNumber)); + DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync b= etween CSME and BIOS configuration. \n")); + DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not = do any configuration by BIOS.\n")); + //Move to next item + Index++; + continue; + } + + // + // Check if Pad enabled for SCI is to be in unlocked state + // + if (((GpioData->GpioConfig.InterruptConfig & GpioIntSci) =3D=3D Gpio= IntSci) && + ((GpioData->GpioConfig.LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_= LOCK_MASK) !=3D GpioPadConfigUnlock)){ + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a used for SCI is not unlocked!= \n", GpioName (GpioData->GpioPad))); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + DEBUG_CODE_END (); + + ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg)); + ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask)); + // + // Get GPIO PADCFG register value from GPIO config data + // + GpioPadCfgRegValueFromGpioConfig ( + GpioData->GpioPad, + &GpioData->GpioConfig, + PadCfgDwReg, + PadCfgDwRegMask + ); + + // + // Create PADCFG register offset using group and pad number + // + PadCfgReg =3D S_GPIO_PCR_PADCFG * PadNumber + GpioGroupInfo[GroupInd= ex].PadCfgOffset; + + // + // Write PADCFG DW0 register + // + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, PadCfgReg), + ~PadCfgDwRegMask[0], + PadCfgDwReg[0] + ); + + // + // Write PADCFG DW1 register + // + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x4), + ~PadCfgDwRegMask[1], + PadCfgDwReg[1] + ); + + // + // Write PADCFG DW2 register + // + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x8), + ~PadCfgDwRegMask[2], + PadCfgDwReg[2] + ); + + // + // Get GPIO DW register values from GPIO config data + // + GpioDwRegValueFromGpioConfig ( + PadNumber, + &GpioData->GpioConfig, + GroupDwData + ); + + //Move to next item + Index++; + } + + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex= ].PadPerGroup); DwNum++) { + // + // Write HOSTSW_OWN registers + // + if (GpioGroupInfo[GroupIndex].HostOwnOffset !=3D NO_REGISTER_FOR_PRO= PERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].HostOwnOffse= t + DwNum * 0x4), + ~GroupDwData[DwNum].HostSoftOwnRegMask, + GroupDwData[DwNum].HostSoftOwnReg + ); + } + + // + // Write GPI_GPE_EN registers + // + if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset !=3D NO_REGISTER_FOR_PR= OPERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].GpiGpeEnOffs= et + DwNum * 0x4), + ~GroupDwData[DwNum].GpiGpeEnRegMask, + GroupDwData[DwNum].GpiGpeEnReg + ); + } + + // + // Write GPI_NMI_EN registers + // + if (GpioGroupInfo[GroupIndex].NmiEnOffset !=3D NO_REGISTER_FOR_PROPE= RTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].NmiEnOffset = + DwNum * 0x4), + ~GroupDwData[DwNum].GpiNmiEnRegMask, + GroupDwData[DwNum].GpiNmiEnReg + ); + } else if (GroupDwData[DwNum].GpiNmiEnReg !=3D 0x0) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting = NMI\n", GroupIndex)); + ASSERT_EFI_ERROR (EFI_UNSUPPORTED); + } + + // + // Write GPI_SMI_EN registers + // + if (GpioGroupInfo[GroupIndex].SmiEnOffset !=3D NO_REGISTER_FOR_PROPE= RTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].SmiEnOffset = + DwNum * 0x4), + ~GroupDwData[DwNum].GpiSmiEnRegMask, + GroupDwData[DwNum].GpiSmiEnReg + ); + } else if (GroupDwData[DwNum].GpiSmiEnReg !=3D 0x0) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting = SMI\n", GroupIndex)); + ASSERT_EFI_ERROR (EFI_UNSUPPORTED); + } + + // + // Update Pad Configuration unlock data + // + if (GroupDwData[DwNum].ConfigUnlockMask) { + GpioStoreGroupDwUnlockPadConfigData (GroupIndex, DwNum, GroupDwDat= a[DwNum].ConfigUnlockMask); + } + + // + // Update Pad Output unlock data + // + if (GroupDwData[DwNum].OutputUnlockMask) { + GpioStoreGroupDwUnlockOutputData (GroupIndex, DwNum, GroupDwData[D= wNum].OutputUnlockMask); + } + } + } + + return EFI_SUCCESS; +} + +/** + This procedure will clear all status bits of any GPIO interrupts. +**/ +STATIC +VOID +GpioClearAllGpioInterrupts ( + VOID + ) +{ + GPIO_GROUP Group; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + GPIO_GROUP GpioGroupLowest; + GPIO_GROUP GpioGroupHighest; + UINT32 GroupIndex; + UINT32 GpioGroupInfoLength; + UINT32 DwNum; + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GpioGroupLowest =3D GpioGetLowestGroup (); + GpioGroupHighest =3D GpioGetHighestGroup (); + + for (Group =3D GpioGroupLowest; Group <=3D GpioGroupHighest; Group++) { + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + // + // Check if group has GPI IS register + // + if (GpioGroupInfo[GroupIndex].GpiIsOffset !=3D NO_REGISTER_FOR_PROPERT= Y) { + // + // Clear all GPI_IS Status bits by writing '1' + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupInd= ex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupI= nfo[GroupIndex].GpiIsOffset + DwNum * 0x4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has GPI_GPE_STS register + // + if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset !=3D NO_REGISTER_FOR_PRO= PERTY) { + // + // Clear all GPI_GPE_STS Status bits by writing '1' + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupInd= ex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupI= nfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has SMI_STS register + // + if (GpioGroupInfo[GroupIndex].SmiStsOffset !=3D NO_REGISTER_FOR_PROPER= TY) { + // + // Clear all SMI_STS Status bits by writing '1' + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupInd= ex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupI= nfo[GroupIndex].SmiStsOffset + DwNum * 4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has NMI_STS register + // + if (GpioGroupInfo[GroupIndex].NmiStsOffset !=3D NO_REGISTER_FOR_PROPER= TY) { + // + // Clear all NMI_STS Status bits by writing '1' + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGroupInfo[GroupInd= ex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupI= nfo[GroupIndex].NmiStsOffset + DwNum * 4), + 0xFFFFFFFF + ); + } + } + + } +} + +/** + This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG = structure. + Structure contains fields that can be used to configure each pad. + Pad not configured using GPIO_INIT_CONFIG will be left with hardware def= ault values. + Separate fields could be set to hardware default if it does not matter, = except + GpioPad and PadMode. + Function will work in most efficient way if pads which belong to the sam= e group are + placed in adjacent records of the table. + Although function can enable pads for Native mode, such programming is d= one + by reference code when enabling related silicon feature. + + @param[in] NumberofItem Number of GPIO pads to be updated + @param[in] GpioInitTableAddress GPIO initialization table + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioConfigurePads ( + IN UINT32 NumberOfItems, + IN GPIO_INIT_CONFIG *GpioInitTableAddress + ) +{ + EFI_STATUS Status; + Status =3D GpioConfigurePch (NumberOfItems, GpioInitTableAddress); + GpioClearAllGpioInterrupts (); + return Status; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/GpioLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioL= ib/GpioLib.c new file mode 100644 index 0000000000..0be50f75df --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioL= ib.c @@ -0,0 +1,2710 @@ +/** @file + This file contains routines for GPIO + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "GpioLibrary.h" +#include + +/** + This procedure will check if GpioGroup argument is correct and + supplied DW reg number can be used for this group to access DW registers= . + Function will check below conditions: + - Valid GpioGroup + - DwNum is has valid value for this group + + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (parameter app= licable in accessing whole register). + For group which has less then 32 pads per group = DwNum must be 0. + + @retval TRUE DW Reg number and GpioGroup is valid + @retval FALSE DW Reg number and GpioGroup is invalid +**/ +STATIC +BOOLEAN +GpioIsGroupAndDwNumValid ( + IN GPIO_GROUP Group, + IN UINT32 DwNum + ) +{ + UINT32 GroupIndex; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ()) = || (GroupIndex >=3D GpioGroupInfoLength)) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within ra= nge of possible groups for this PCH\n", GroupIndex)); + goto Error; + } + + // + // Check if DwNum argument does not exceed number of DWord registers + // resulting from available pads for certain group + // + if (DwNum > GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup - 1))= { + goto Error; + } + + return TRUE; +Error: + ASSERT (FALSE); + return FALSE; +} + +// +// Possible registers to be accessed using GpioReadReg()/GpioWriteReg() fu= nctions +// +typedef enum { + GpioHostOwnershipRegister =3D 0, + GpioGpeEnableRegister, + GpioGpeStatusRegister, + GpioSmiEnableRegister, + GpioSmiStatusRegister, + GpioNmiEnableRegister, + GpioPadConfigLockRegister, + GpioPadLockOutputRegister +} GPIO_REG; + +/** + This procedure will read GPIO register + + @param[in] RegType GPIO register type + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (param= eter applicable in accessing whole register). + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[out] ReadVal Read data +**/ +STATIC +VOID +GpioReadReg ( + IN GPIO_REG RegType, + IN GPIO_GROUP Group, + IN UINT32 DwNum, + OUT UINT32 *ReadVal + ) +{ + UINT32 RegOffset; + UINT32 GroupIndex; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + + RegOffset =3D NO_REGISTER_FOR_PROPERTY; + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioHostOwnershipRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].HostOwnOffset; + break; + case GpioGpeEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].GpiGpeEnOffset; + break; + case GpioGpeStatusRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].GpiGpeStsOffset; + break; + case GpioSmiEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].SmiEnOffset; + break; + case GpioSmiStatusRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].SmiStsOffset; + break; + case GpioNmiEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].NmiEnOffset; + break; + case GpioPadConfigLockRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].PadCfgLockOffset; + break; + case GpioPadLockOutputRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].PadCfgLockTxOffset; + break; + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset =3D=3D NO_REGISTER_FOR_PROPERTY) { + *ReadVal =3D 0; + ASSERT (FALSE); + return; + } + + // + // If there are more then 32 pads per group then certain + // group information would be split into more then one DWord register. + // + if ((RegType =3D=3D GpioPadConfigLockRegister) || (RegType =3D=3D GpioPa= dLockOutputRegister)) { + // + // PadConfigLock and OutputLock registers when used for group containi= ng more than 32 pads + // are not placed in a continuous way, e.g: + // 0x0 - PadConfigLock_DW0 + // 0x4 - OutputLock_DW0 + // 0x8 - PadConfigLock_DW1 + // 0xC - OutputLock_DW1 + // + RegOffset +=3D DwNum * 0x8; + } else { + RegOffset +=3D DwNum * 0x4; + } + + *ReadVal =3D MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Comm= unity, RegOffset)); +} + +/** + This function determines if the group is SMI capable. + + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (param= eter applicable in accessing whole register). + For group which has less then 32 pads pe= r group DwNum must be 0. + @retval TRUE The function completed successfully + @retval FALSE Setting SMI for a group is not supported +**/ +STATIC +BOOLEAN +GpioIsSmiSupportedByGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 Dw + ) +{ + UINT32 RegOffset; + UINT32 GroupIndex; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + RegOffset =3D GpioGroupInfo[GroupIndex].SmiStsOffset; + + // + // Check if selected register exists + // + if (RegOffset =3D=3D NO_REGISTER_FOR_PROPERTY) { + return FALSE; + } + + return TRUE; +} + +/** + This function determines if the group is NMI capable. + + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (param= eter applicable in accessing whole register). + For group which has less then 32 pads pe= r group DwNum must be 0. + @retval TRUE The function completed successfully + @retval FALSE Setting NMI for a group is not supported +**/ +STATIC +BOOLEAN +GpioIsNmiSupportedByGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 Dw + ) +{ + UINT32 RegOffset; + UINT32 GroupIndex; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + RegOffset =3D GpioGroupInfo[GroupIndex].NmiEnOffset; + + // + // Check if selected register exists + // + if (RegOffset =3D=3D NO_REGISTER_FOR_PROPERTY) { + return FALSE; + } + + return TRUE; +} + +/** + This procedure will write GPIO register + + @param[in] RegType GPIO register type + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (param= eter applicable in accessing whole register). + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] RegAndMask Mask which will be AND'ed with register = value + @param[in] RegOrMask Mask which will be OR'ed with register v= alue +**/ +STATIC +VOID +GpioWriteReg ( + IN GPIO_REG RegType, + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 RegAndMask, + IN UINT32 RegOrMask + ) +{ + UINT32 RegOffset; + UINT32 GroupIndex; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + UINT32 PadCfgLock; + BOOLEAN Lockable; + EFI_STATUS Status; + + Lockable =3D FALSE; + PadCfgLock =3D 0; + RegOffset =3D NO_REGISTER_FOR_PROPERTY; + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioHostOwnershipRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].HostOwnOffset; + break; + case GpioGpeEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].GpiGpeEnOffset; + Lockable =3D TRUE; + break; + case GpioGpeStatusRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].GpiGpeStsOffset; + break; + case GpioSmiEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].SmiEnOffset; + Lockable =3D TRUE; + break; + case GpioSmiStatusRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].SmiStsOffset; + break; + case GpioNmiEnableRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].NmiEnOffset; + Lockable =3D TRUE; + break; + case GpioPadConfigLockRegister: + case GpioPadLockOutputRegister: + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset =3D=3D NO_REGISTER_FOR_PROPERTY) { + return; + } + + if (Lockable) { + GpioGetPadCfgLockForGroupDw (Group, DwNum, &PadCfgLock); + if (PadCfgLock) { + // + // Check if for pads which are going to be reconfigured lock is set. + // + if ((~RegAndMask | RegOrMask) & PadCfgLock) { + // + // Unlock all pads for this Group DW reg for simplicity + // even if not all of those pads will have their settings reprogra= mmed + // + Status =3D GpioUnlockPadCfgForGroupDw (Group, DwNum, PadCfgLock); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return; + } + } else { + // + // No need to perform an unlock as pads which are going to be reco= nfigured + // are not in locked state + // + PadCfgLock =3D 0; + } + } + } + + // + // If there are more then 32 pads per group then certain + // group information would be split into more then one DWord register. + // + RegOffset +=3D DwNum * 0x4; + + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset), + RegAndMask, + RegOrMask + ); + + if (Lockable && PadCfgLock) { + // + // Lock previously unlocked pads + // + Status =3D GpioLockPadCfgForGroupDw (Group, DwNum, PadCfgLock); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return; + } + } +} + +/** + This procedure will write GPIO Lock/LockTx register using SBI. + + @param[in] RegType GPIO register (Lock or LockTx) + @param[in] Group GPIO group number + @param[in] DwNum Register number for current group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] LockRegAndMask Mask which will be AND'ed with Lock regi= ster value + @param[in] LockRegOrMask Mask which will be Or'ed with Lock regis= ter value + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_UNSUPPORTED Feature is not supported for this group = or pad +**/ +STATIC +EFI_STATUS +GpioWriteLockReg ( + IN GPIO_REG RegType, + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 LockRegAndMask, + IN UINT32 LockRegOrMask + ) +{ + UINT8 Response; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + UINT32 RegOffset; + UINT32 OldLockVal; + UINT32 NewLockVal; + UINT32 GroupIndex; + EFI_STATUS Status; + + OldLockVal =3D 0; + NewLockVal =3D 0; + + RegOffset =3D NO_REGISTER_FOR_PROPERTY; + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioPadConfigLockRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].PadCfgLockOffset; + GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldLockVal); + break; + case GpioPadLockOutputRegister: + RegOffset =3D GpioGroupInfo[GroupIndex].PadCfgLockTxOffset; + GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldLockVal); + break; + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset =3D=3D NO_REGISTER_FOR_PROPERTY) { + return EFI_UNSUPPORTED; + } + + // + // If there are more then 32 pads per group then certain + // group information would be split into more then one DWord register. + // PadConfigLock and OutputLock registers when used for group containing= more than 32 pads + // are not placed in a continuous way, e.g: + // 0x0 - PadConfigLock_DW0 + // 0x4 - OutputLock_DW0 + // 0x8 - PadConfigLock_DW1 + // 0xC - OutputLock_DW1 + // + RegOffset +=3D DwNum *0x8; + + NewLockVal =3D (OldLockVal & LockRegAndMask) | LockRegOrMask; + + Status =3D PchSbiExecutionEx ( + GpioGroupInfo[GroupIndex].Community, + RegOffset, + GpioLockUnlock, + FALSE, + 0x000F, + 0x0000, + 0x0000, + &NewLockVal, + &Response + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + This internal procedure will calculate GPIO_RESET_CONFIG value (new typ= e) + based on provided PadRstCfg for a specific GPIO Pad. + + @param[in] GpioPad GPIO Pad + @param[in] PadRstCfg GPIO PadRstCfg value + + @retval GpioResetConfig GPIO Reset configuration (new type) +**/ +GPIO_RESET_CONFIG +GpioResetConfigFromPadRstCfg ( + IN GPIO_PAD GpioPad, + IN UINT32 PadRstCfg + ) +{ + GPIO_GROUP Group; + + static GPIO_RESET_CONFIG GppPadRstCfgToGpioResetConfigMap[] =3D { + GpioResumeReset, + GpioHostDeepReset, + GpioPlatformReset}; + static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] =3D { + GpioDswReset, + GpioHostDeepReset, + GpioPlatformReset, + GpioResumeReset}; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + + if (GpioIsDswGroup (Group) && PadRstCfg < 4) { + return GpdPadRstCfgToGpioResetConfigMap[PadRstCfg]; + } else if (PadRstCfg < 3) { + return GppPadRstCfgToGpioResetConfigMap[PadRstCfg]; + } else { + ASSERT (FALSE); + return GpioResetDefault; + } +} + +/** + This internal procedure will calculate PadRstCfg register value based + on provided GPIO Reset configuration for a certain pad. + + @param[in] GpioPad GPIO Pad + @param[in] GpioResetConfig GPIO Reset configuration + @param[out] PadRstCfg GPIO PadRstCfg value + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid configuration +**/ +EFI_STATUS +GpioPadRstCfgFromResetConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_RESET_CONFIG GpioResetConfig, + OUT UINT32 *PadRstCfg + ) +{ + GPIO_GROUP Group; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + + switch (GpioResetConfig) { + case GpioResetDefault: + *PadRstCfg =3D 0x0; + break; + case GpioHostDeepReset: + *PadRstCfg =3D V_GPIO_PCR_RST_CONF_DEEP_RST; + break; + case GpioPlatformReset: + *PadRstCfg =3D V_GPIO_PCR_RST_CONF_GPIO_RST; + break; + case GpioResumeReset: + if (GpioIsDswGroup (Group)) { + *PadRstCfg =3D V_GPIO_PCR_RST_CONF_RESUME_RST; + } else { + *PadRstCfg =3D V_GPIO_PCR_RST_CONF_POW_GOOD; + } + break; + case GpioDswReset: + if (GpioIsDswGroup (Group)) { + *PadRstCfg =3D V_GPIO_PCR_RST_CONF_POW_GOOD; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use Gpio= DswReset: %a\n", GpioName (GpioPad))); + goto Error; + } + break; + default: + goto Error; + } + + return EFI_SUCCESS; +Error: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; +} + +/** + This internal procedure will get GPIO_CONFIG data from PADCFG registers = value + + @param[in] GpioPad GPIO Pad + @param[in] PadCfgDwReg PADCFG DWx register values + @param[out] GpioData GPIO Configuration data + + @retval Status +**/ +STATIC +VOID +GpioConfigFromPadCfgRegValue ( + IN GPIO_PAD GpioPad, + IN CONST UINT32 *PadCfgDwReg, + OUT GPIO_CONFIG *GpioConfig + ) +{ + UINT32 PadRstCfg; + + // + // Get Reset Type (PadRstCfg) + // + PadRstCfg =3D (PadCfgDwReg[0] & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_C= ONF; + + GpioConfig->PowerConfig =3D GpioResetConfigFromPadRstCfg ( + GpioPad, + PadRstCfg + ); + + // + // Get how interrupt is triggered (RxEvCfg) + // + GpioConfig->InterruptConfig =3D ((PadCfgDwReg[0] & B_GPIO_PCR_RX_LVL_EDG= ) >> (N_GPIO_PCR_RX_LVL_EDG - (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | = (0x1 << N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS); + + // + // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI) + // + GpioConfig->InterruptConfig |=3D ((PadCfgDwReg[0] & (B_GPIO_PCR_RX_NMI_R= OUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_AP= IC_ROUTE)) >> (N_GPIO_PCR_RX_NMI_ROUTE - (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_= POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS); + + // + // Get GPIO direction (GPIORxDis and GPIOTxDis) + // + GpioConfig->Direction =3D ((PadCfgDwReg[0] & (B_GPIO_PCR_RXDIS | B_GPIO_= PCR_TXDIS)) >> (N_GPIO_PCR_TXDIS - (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (= 0x1 << N_GPIO_DIRECTION_DIR_BIT_POS); + + // + // Get GPIO input inversion (RXINV) + // (Only meaningful if input enabled) + // + if((PadCfgDwReg[0] & B_GPIO_PCR_RXDIS) =3D=3D 0) { + GpioConfig->Direction |=3D ((PadCfgDwReg[0] & B_GPIO_PCR_RXINV) >> (N_= GPIO_PCR_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRE= CTION_INV_BIT_POS); + } + + // + // Get GPIO output state (GPIOTxState) + // + GpioConfig->OutputState =3D ((PadCfgDwReg[0] & B_GPIO_PCR_TX_STATE) << (= N_GPIO_PCR_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 << N_GPIO_OUTPUT= _BIT_POS); + + // + // Configure GPIO RX raw override to '1' (RXRAW1) + // + GpioConfig->OtherSettings =3D ((PadCfgDwReg[0] & B_GPIO_PCR_RX_RAW1) >> = (N_GPIO_PCR_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1))) | (0x1 << N= _GPIO_OTHER_CONFIG_RXRAW_BIT_POS); + + // + // Get GPIO Pad Mode (PMode) + // + GpioConfig->PadMode =3D ((PadCfgDwReg[0] & B_GPIO_PCR_PAD_MODE) >> (N_GP= IO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE= _BIT_POS); + + // + // Get GPIO termination (Term) + // + GpioConfig->ElectricalConfig =3D ((PadCfgDwReg[1] & B_GPIO_PCR_TERM) >> = (N_GPIO_PCR_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1))) | (= 0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS); +} + +/** + This procedure will read multiple GPIO settings + + @param[in] GpioPad GPIO Pad + @param[out] GpioData GPIO data structure + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioGetPadConfig ( + IN GPIO_PAD GpioPad, + OUT GPIO_CONFIG *GpioData + ) +{ + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER]; + UINT32 RegVal; + GPIO_GROUP Group; + UINT32 PadNumber; + UINT32 PadBitPosition; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + // + // Read PADCFG DW0 register + // + PadCfgDwReg[0] =3D GpioReadPadCfgReg (GpioPad, 0); + + // + // Read PADCFG DW1 register + // + PadCfgDwReg[1] =3D GpioReadPadCfgReg (GpioPad, 1); + + // + // Read PADCFG DW2 register + // + PadCfgDwReg[2] =3D GpioReadPadCfgReg (GpioPad, 2); + + GpioConfigFromPadCfgRegValue ( + GpioPad, + PadCfgDwReg, + GpioData + ); + + // + // Read HOSTSW_OWN registers + // + GpioReadReg ( + GpioHostOwnershipRegister, + Group, + GPIO_GET_DW_NUM (PadNumber), + &RegVal + ); + + // + // Get Host Software Ownership + // + GpioData->HostSoftPadOwn =3D (((RegVal >> PadBitPosition) & 0x1) << (N_G= PIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 << N_GPIO_HOSTSW_OWN_BIT_POS); + + // + // Read PADCFGLOCK register + // + GpioReadReg ( + GpioPadConfigLockRegister, + Group, + GPIO_GET_DW_NUM (PadNumber), + &RegVal + ); + + // + // Get Pad Configuration Lock state + // + GpioData->LockConfig =3D ((!((RegVal >> PadBitPosition) & 0x1)) << 1) | = 0x1; + + // + // Read PADCFGLOCKTX register + // + GpioReadReg ( + GpioPadLockOutputRegister, + Group, + GPIO_GET_DW_NUM (PadNumber), + &RegVal + ); + + // + // Get Pad Configuration Lock Tx state + // + GpioData->LockConfig |=3D ((!((RegVal >> PadBitPosition) & 0x1)) << 2) |= 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure will calculate PADCFG register value based on GpioConfig = data + + @param[in] GpioPad GPIO Pad + @param[in] GpioConfig GPIO Configuration data + @param[out] PadCfgDwReg PADCFG DWx register value + @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits= to be modified +**/ +VOID +GpioPadCfgRegValueFromGpioConfig ( + IN GPIO_PAD GpioPad, + IN CONST GPIO_CONFIG *GpioConfig, + OUT UINT32 *PadCfgDwReg, + OUT UINT32 *PadCfgDwRegMask + ) +{ + UINT32 PadRstCfg; + EFI_STATUS Status; + + // + // Configure Reset Type (PadRstCfg) + // Reset configuration depends on group type. + // This field requires support for new and deprecated settings. + // + Status =3D GpioPadRstCfgFromResetConfig ( + GpioPad, + GpioConfig->PowerConfig, + &PadRstCfg + ); + if (EFI_ERROR (Status)) { + return; + } + + PadCfgDwRegMask[0] |=3D ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFI= G_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) =3D=3D GpioHardwareDefa= ult) ? 0x0 : B_GPIO_PCR_RST_CONF); + PadCfgDwReg[0] |=3D PadRstCfg << N_GPIO_PCR_RST_CONF; + + // + // Configure how interrupt is triggered (RxEvCfg) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->InterruptConfig & B_GPIO_INT_CON= FIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) =3D=3D GpioHardwa= reDefault) ? 0x0 : B_GPIO_PCR_RX_LVL_EDG); + PadCfgDwReg[0] |=3D (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_I= NT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX= _LVL_EDG); + + // + // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->InterruptConfig & B_GPIO_INT_CON= FIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) =3D=3D GpioHa= rdwareDefault) ? 0x0 : (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE = | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE)); + PadCfgDwReg[0] |=3D (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_I= NT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_GPIO_PC= R_RX_NMI_ROUTE); + + // + // Configure GPIO direction (GPIORxDis and GPIOTxDis) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->Direction & B_GPIO_DIRECTION_DIR= _MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) =3D=3D GpioHardwareDefault) ? 0x0 := (B_GPIO_PCR_RXDIS | B_GPIO_PCR_TXDIS)); + PadCfgDwReg[0] |=3D (((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK= ) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) << N_GPIO_PCR_TXDIS); + + // + // Configure GPIO input inversion (RXINV) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV= _MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) =3D=3D GpioHardwareDefault) ? 0x0 = : B_GPIO_PCR_RXINV); + PadCfgDwReg[0] |=3D (((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK= ) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) << N_GPIO_PCR_RXINV); + + // + // Configure GPIO output state (GPIOTxState) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK= ) >> N_GPIO_OUTPUT_BIT_POS) =3D=3D GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_= TX_STATE); + PadCfgDwReg[0] |=3D (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> = (N_GPIO_OUTPUT_BIT_POS + 1)) << N_GPIO_PCR_TX_STATE); + + // + // Configure GPIO RX raw override to '1' (RXRAW1) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->OtherSettings & B_GPIO_OTHER_CON= FIG_RXRAW_MASK) >> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) =3D=3D GpioHardwareDe= fault) ? 0x0 : B_GPIO_PCR_RX_RAW1); + PadCfgDwReg[0] |=3D (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_R= XRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_GPIO_PCR_RX_RAW= 1); + + // + // Configure GPIO Pad Mode (PMode) + // + PadCfgDwRegMask[0] |=3D ((((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) = >> N_GPIO_PAD_MODE_BIT_POS) =3D=3D GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_= PAD_MODE); + PadCfgDwReg[0] |=3D (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> (N= _GPIO_PAD_MODE_BIT_POS + 1)) << N_GPIO_PCR_PAD_MODE); + + // + // Configure GPIO termination (Term) + // + PadCfgDwRegMask[1] |=3D ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTR= ICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_P= OS) =3D=3D GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TERM); + PadCfgDwReg[1] |=3D (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_= CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS += 1)) << N_GPIO_PCR_TERM); +} + +/** + This procedure will configure multiple GPIO settings + + @param[in] GpioPad GPIO Pad + @param[in] GpioData GPIO data structure + + @retval EFI_SUCCESS The function completed successfull= y + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioSetPadConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_CONFIG *GpioData + ) +{ + EFI_STATUS Status; + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER]; + UINT32 PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER]; + UINT32 HostSoftOwnReg; + UINT32 HostSoftOwnRegMask; + UINT32 GpiGpeEnReg; + UINT32 GpiGpeEnRegMask; + UINT32 GpiNmiEnReg; + UINT32 GpiNmiEnRegMask; + UINT32 GpiSmiEnReg; + UINT32 GpiSmiEnRegMask; + GPIO_GROUP Group; + UINT32 GroupIndex; + UINT32 PadNumber; + UINT32 PadBitPosition; + UINT32 DwNum; + GPIO_LOCK_CONFIG LockConfig; + + Status =3D EFI_SUCCESS; + ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg)); + ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask)); + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + // + // Check if Pad enabled for SCI is to be in unlocked state + // + if (((GpioData->InterruptConfig & GpioIntSci) =3D=3D GpioIntSci) && + ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) !=3D= GpioPadConfigUnlock)){ + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a for SCI is not unlocked!\n", Gpio= Name (GpioPad))); + return EFI_INVALID_PARAMETER; + } + + // + // Get GPIO PADCFG register value from GPIO config data + // + GpioPadCfgRegValueFromGpioConfig ( + GpioPad, + GpioData, + PadCfgDwReg, + PadCfgDwRegMask + ); + + // + // Write PADCFG DW0 register + // + GpioWritePadCfgReg ( + GpioPad, + 0, + ~PadCfgDwRegMask[0], + PadCfgDwReg[0] + ); + + // + // Write PADCFG DW1 register + // + GpioWritePadCfgReg ( + GpioPad, + 1, + ~PadCfgDwRegMask[1], + PadCfgDwReg[1] + ); + + // + // Write PADCFG DW2 register + // + GpioWritePadCfgReg ( + GpioPad, + 2, + ~PadCfgDwRegMask[2], + PadCfgDwReg[2] + ); + + // + // Update value to be programmed in HOSTSW_OWN register + // + if ((GpioData->InterruptConfig & GpioIntSmi) =3D=3D GpioIntSmi) { + HostSoftOwnRegMask =3D 1 << PadBitPosition; + HostSoftOwnReg =3D 1 << PadBitPosition; + } else { + HostSoftOwnRegMask =3D (GpioData->HostSoftPadOwn & 0x1) << PadBitPosit= ion; + HostSoftOwnReg =3D (GpioData->HostSoftPadOwn >> 0x1) << PadBitPosition= ; + } + + // + // Write HOSTSW_OWN registers + // + GpioWriteReg ( + GpioHostOwnershipRegister, + Group, + DwNum, + ~HostSoftOwnRegMask, + HostSoftOwnReg + ); + + // + // Update value to be programmed in GPI_GPE_EN register + // + GpiGpeEnRegMask =3D (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiGpeEnReg =3D ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBi= tPosition; + + // + // Write GPI_GPE_EN registers + // + GpioWriteReg ( + GpioGpeEnableRegister, + Group, + DwNum, + ~GpiGpeEnRegMask, + GpiGpeEnReg + ); + + // + // Update value to be programmed in GPI_NMI_EN register + // + GpiNmiEnRegMask =3D (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiNmiEnReg =3D ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBi= tPosition; + + if (GpioIsNmiSupportedByGroupDw (Group, DwNum)) { + GpioWriteReg ( + GpioNmiEnableRegister, + Group, + DwNum, + ~GpiNmiEnRegMask, + GpiNmiEnReg + ); + } else { + if (GpiNmiEnReg =3D=3D 0) { + // + // Not all GPIO have NMI capabilities. Since we always try to progra= m this register, + // even when not enabling NMI for a pad so do not report such access= as an error + // + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting NM= I\n", GpioGetGroupName (GroupIndex))); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } + + // + // Update value to be programmed in GPI_SMI_EN register + // + GpiSmiEnRegMask =3D (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiSmiEnReg =3D ((GpioData->InterruptConfig & GpioIntSmi) >> 2) << PadBi= tPosition; + + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) { + GpioWriteReg ( + GpioSmiEnableRegister, + Group, + DwNum, + ~GpiSmiEnRegMask, + GpiSmiEnReg + ); + } else { + if (GpiSmiEnReg =3D=3D 0) { + // + // Not all GPIO have SMI capabilities. Since we always try to progra= m this register, + // even when not enabling SMI for a pad so do not report such access= as an error + // + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting SM= I\n", GpioGetGroupName (GroupIndex))); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } + + // + // Store unlock data + // + if (GpioData->LockConfig !=3D GpioLockDefault) { + LockConfig =3D GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK= _MASK; + // + // If pad in GpioMode is an output default action should be to leave o= utput unlocked + // + if ((GpioData->PadMode =3D=3D GpioPadModeGpio) && + (GpioData->Direction =3D=3D GpioDirOut) && + ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) =3D=3D= GpioLockDefault)) { + LockConfig |=3D GpioOutputStateUnlock; + } else { + LockConfig |=3D GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOC= K_MASK; + } + Status =3D GpioStoreUnlockData (GpioPad, LockConfig); + } + + return Status; +} + +/** + This procedure will set GPIO output level + + @param[in] GpioPad GPIO pad + @param[in] Value Output value + 0: OutputLow, 1: OutputHigh + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetOutputValue ( + IN GPIO_PAD GpioPad, + IN UINT32 Value + ) +{ + if (Value > 1) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + GpioWritePadCfgReg ( + GpioPad, + 0, + (UINT32)~B_GPIO_PCR_TX_STATE, + Value << N_GPIO_PCR_TX_STATE + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO output level + + @param[in] GpioPad GPIO pad + @param[out] OutputVal GPIO Output value + 0: OutputLow, 1: OutputHigh + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetOutputValue ( + IN GPIO_PAD GpioPad, + OUT UINT32 *OutputVal + ) +{ + UINT32 PadCfgReg; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + PadCfgReg =3D GpioReadPadCfgReg (GpioPad, 0); + + *OutputVal =3D (PadCfgReg & B_GPIO_PCR_TX_STATE) >> N_GPIO_PCR_TX_STATE; + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO input level + + @param[in] GpioPad GPIO pad + @param[out] InputVal GPIO Input value + 0: InputLow, 1: InpuHigh + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetInputValue ( + IN GPIO_PAD GpioPad, + OUT UINT32 *InputVal + ) +{ + UINT32 PadCfgReg; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + PadCfgReg =3D GpioReadPadCfgReg (GpioPad, 0); + + *InputVal =3D (PadCfgReg & B_GPIO_PCR_RX_STATE) >> N_GPIO_PCR_RX_STATE; + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO IOxAPIC interrupt number + + @param[in] GpioPad GPIO pad + @param[out] IrqNum IRQ number + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetPadIoApicIrqNumber ( + IN GPIO_PAD GpioPad, + OUT UINT32 *IrqNum + ) +{ + UINT32 PadCfgReg; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + PadCfgReg =3D GpioReadPadCfgReg (GpioPad, 1); + + *IrqNum =3D (PadCfgReg & B_GPIO_PCR_INTSEL) >> N_GPIO_PCR_INTSEL; + + return EFI_SUCCESS; +} + +/** + This procedure will configure GPIO input inversion + + @param[in] GpioPad GPIO pad + @param[in] Value Value for GPIO input inversion + 0: No input inversion, 1: Invert input + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetInputInversion ( + IN GPIO_PAD GpioPad, + IN UINT32 Value + ) +{ + if (Value > 1) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + GpioWritePadCfgReg ( + GpioPad, + 0, + (UINT32)~B_GPIO_PCR_RXINV, + Value << N_GPIO_PCR_RXINV + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO pad input inversion value + + @param[in] GpioPad GPIO pad + @param[out] InvertState GPIO inversion state + 0: No input inversion, 1: Inverted input + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetInputInversion ( + IN GPIO_PAD GpioPad, + OUT UINT32 *InvertState + ) +{ + UINT32 PadCfgReg; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + PadCfgReg =3D GpioReadPadCfgReg (GpioPad, 0); + + *InvertState =3D (PadCfgReg & B_GPIO_PCR_RXINV) >> N_GPIO_PCR_RXINV; + return EFI_SUCCESS; +} + +/** + This procedure will set GPIO interrupt settings + + @param[in] GpioPad GPIO pad + @param[in] Value Value of Level/Edge + use GPIO_INT_CONFIG as argument + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetPadInterruptConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_INT_CONFIG Value + ) +{ + EFI_STATUS Status; + BOOLEAN IsNmiSupported; + UINT32 RxLvlEdgeValue; + UINT32 IntRouteValue; + UINT32 PadNumber; + UINT32 GpeEnable; + UINT32 NmiEnable; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + Status =3D EFI_SUCCESS; + + if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_= TYPE_BIT_POS) !=3D GpioHardwareDefault) { + RxLvlEdgeValue =3D ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GP= IO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX_LVL_EDG; + + GpioWritePadCfgReg ( + GpioPad, + 0, + (UINT32)~B_GPIO_PCR_RX_LVL_EDG, + RxLvlEdgeValue + ); + } + + if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_IN= T_SOURCE_BIT_POS) !=3D GpioHardwareDefault) { + + IntRouteValue =3D ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_G= PIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_GPIO_PCR_RX_NMI_ROUTE; + + GpioWritePadCfgReg ( + GpioPad, + 0, + (UINT32)~(B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO= _PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE), + IntRouteValue + ); + + if ((Value & GpioIntSci) =3D=3D GpioIntSci) { + GpeEnable =3D 0x1; + } else { + GpeEnable =3D 0x0; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioWriteReg ( + GpioGpeEnableRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + ~(1 << GPIO_GET_PAD_POSITION (PadNumber)), + GpeEnable << GPIO_GET_PAD_POSITION (PadNumber) + ); + + if ((Value & GpioIntNmi) =3D=3D GpioIntNmi) { + NmiEnable =3D 0x1; + } else { + NmiEnable =3D 0x0; + } + + IsNmiSupported =3D GpioIsNmiSupportedByGroupDw ( + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber) + ); + if (IsNmiSupported) { + GpioWriteReg ( + GpioNmiEnableRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + ~(1 << GPIO_GET_PAD_POSITION (PadNumber)), + NmiEnable << GPIO_GET_PAD_POSITION (PadNumber) + ); + } else { + if (NmiEnable =3D=3D 0) { + // + // Not all GPIO have NMI capabilities. Since we always try to prog= ram this register, + // even when not enabling NMI for a pad so do not report such acce= ss as an error + // + return EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting = NMI\n", GpioGetGroupName (GpioGetGroupIndexFromGpioPad (GpioPad)))); + ASSERT (FALSE); + } + } + } + + return Status; +} + +/** + This procedure will set GPIO electrical settings + + @param[in] GpioPad GPIO pad + @param[in] Value Value of termination + use GPIO_ELECTRICAL_CONFIG as argument + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetPadElectricalConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_ELECTRICAL_CONFIG Value + ) +{ + UINT32 TermValue; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECT= RICAL_CONFIG_TERMINATION_BIT_POS) !=3D GpioHardwareDefault) { + TermValue =3D ((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> = (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_GPIO_PCR_TERM; + + GpioWritePadCfgReg ( + GpioPad, + 1, + (UINT32)~B_GPIO_PCR_TERM, + TermValue + ); + } + + return EFI_SUCCESS; +} + +/** + This procedure will set GPIO Reset settings + + @param[in] GpioPad GPIO pad + @param[in] Value Value for Pad Reset Configuration + use GPIO_RESET_CONFIG as argument + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetPadResetConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_RESET_CONFIG Value + ) +{ + UINT32 PadRstCfg; + EFI_STATUS Status; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RES= ET_BIT_POS) !=3D GpioHardwareDefault) { + + // + // Reset configuration depends on group type. + // This field requires support for new and deprecated settings. + // + Status =3D GpioPadRstCfgFromResetConfig ( + GpioPad, + Value, + &PadRstCfg + ); + if (EFI_ERROR (Status)) { + return Status; + } + GpioWritePadCfgReg ( + GpioPad, + 0, + (UINT32)~B_GPIO_PCR_RST_CONF, + PadRstCfg << N_GPIO_PCR_RST_CONF + ); + } + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO Reset settings + + @param[in] GpioPad GPIO pad + @param[in] Value Value of Pad Reset Configuration + based on GPIO_RESET_CONFIG + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetPadResetConfig ( + IN GPIO_PAD GpioPad, + IN GPIO_RESET_CONFIG *Value + ) +{ + UINT32 PadRstCfg; + UINT32 PadCfgDw0Reg; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + PadCfgDw0Reg =3D GpioReadPadCfgReg (GpioPad, 0); + + // + // Get Reset Type (PadRstCfg) + // + PadRstCfg =3D (PadCfgDw0Reg & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_CON= F; + + *Value =3D GpioResetConfigFromPadRstCfg ( + GpioPad, + PadRstCfg + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO Host Software Pad Ownership for certain gro= up + + @param[in] Group GPIO group + @param[in] DwNum Host Ownership register number for curre= nt group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[out] HostSwRegVal Value of Host Software Pad Ownership reg= ister + Bit position - PadNumber + Bit value - 0: ACPI Mode, 1: GPIO Driver= mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioGetHostSwOwnershipForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + OUT UINT32 *HostSwRegVal + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + GpioReadReg ( + GpioHostOwnershipRegister, + Group, + DwNum, + HostSwRegVal + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO Host Software Pad Ownership for certain gro= up + + @param[in] Group GPIO group + @param[in] DwNum Host Ownership register number for curre= nt group + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] HostSwRegVal Value of Host Software Pad Ownership reg= ister + Bit position - PadNumber + Bit value - 0: ACPI Mode, 1: GPIO Driver= mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioSetHostSwOwnershipForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 HostSwRegVal + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + GpioWriteReg ( + GpioHostOwnershipRegister, + Group, + DwNum, + 0, + HostSwRegVal + ); + return EFI_SUCCESS; +} + +/** + This procedure will get Gpio Pad Host Software Ownership + + @param[in] GpioPad GPIO pad + @param[out] PadHostSwOwn Value of Host Software Pad Owner + 0: ACPI Mode, 1: GPIO Driver mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetHostSwOwnershipForPad ( + IN GPIO_PAD GpioPad, + OUT UINT32 *PadHostSwOwn + ) +{ + UINT32 PadNumber; + UINT32 HostSwRegVal; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioHostOwnershipRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &HostSwRegVal + ); + + *PadHostSwOwn =3D (HostSwRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & = 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure will set Gpio Pad Host Software Ownership + + @param[in] GpioPad GPIO pad + @param[in] PadHostSwOwn Pad Host Software Owner + 0: ACPI Mode, 1: GPIO Driver mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioSetHostSwOwnershipForPad ( + IN GPIO_PAD GpioPad, + IN UINT32 PadHostSwOwn + ) +{ + UINT32 PadNumber; + + if (!GpioIsPadValid (GpioPad) || (PadHostSwOwn > 1)) { + return EFI_INVALID_PARAMETER; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioWriteReg ( + GpioHostOwnershipRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + (UINT32)~(1 << GPIO_GET_PAD_POSITION (PadNumber)), + PadHostSwOwn << GPIO_GET_PAD_POSITION (PadNumber) + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get Gpio Pad Ownership + + @param[in] GpioPad GPIO pad + @param[out] PadOwnVal Value of Pad Ownership + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioGetPadOwnership ( + IN GPIO_PAD GpioPad, + OUT GPIO_PAD_OWN *PadOwnVal + ) +{ + UINT32 Mask; + UINT32 RegOffset; + UINT32 GroupIndex; + UINT32 PadNumber; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + UINT32 PadOwnRegValue; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Calculate RegOffset using Pad Ownership offset and GPIO Pad number. + // One DWord register contains information for 8 pads. + // + RegOffset =3D GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) = * 0x4; + + // + // Calculate pad bit position within DWord register + // + PadNumber %=3D 8; + Mask =3D (BIT1 | BIT0) << (PadNumber * 4); + + PadOwnRegValue =3D MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex= ].Community, RegOffset)); + + *PadOwnVal =3D (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4= )); + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Lock for pads within one g= roup + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLock register number for current g= roup. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[out] PadCfgLockRegVal Value of PadCfgLock register + Bit position - PadNumber + Bit value - 0: NotLocked, 1: Locked + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioGetPadCfgLockForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + OUT UINT32 *PadCfgLockRegVal + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + GpioReadReg ( + GpioPadConfigLockRegister, + Group, + DwNum, + PadCfgLockRegVal + ); + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Lock for selected pad + + @param[in] GpioPad GPIO pad + @param[out] PadCfgLock PadCfgLock for selected pad + 0: NotLocked, 1: Locked + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetPadCfgLock ( + IN GPIO_PAD GpioPad, + OUT UINT32 *PadCfgLock + ) +{ + UINT32 PadNumber; + UINT32 PadCfgLockRegVal; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioPadConfigLockRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &PadCfgLockRegVal + ); + + *PadCfgLock =3D (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) = & 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Tx Lock for pads within on= e group + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLockTx register number for current= group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register + Bit position - PadNumber + Bit value - 0: NotLockedTx, 1: LockedTx + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioGetPadCfgLockTxForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + OUT UINT32 *PadCfgLockTxRegVal + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + GpioReadReg ( + GpioPadLockOutputRegister, + Group, + DwNum, + PadCfgLockTxRegVal + ); + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Tx Lock for selected pad + + @param[in] GpioPad GPIO pad + @param[out] PadCfgLock PadCfgLockTx for selected pad + 0: NotLockedTx, 1: LockedTx + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetPadCfgLockTx ( + IN GPIO_PAD GpioPad, + OUT UINT32 *PadCfgLockTx + ) +{ + UINT32 PadNumber; + UINT32 PadCfgLockTxRegVal; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioPadLockOutputRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &PadCfgLockTxRegVal + ); + + *PadCfgLockTx =3D (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumbe= r)) & 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure will clear PadCfgLock for selected pads within one group. + This function should be used only inside SMI. + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLock register number for current g= roup. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] PadsToUnlock Bitmask for pads which are going to be u= nlocked, + Bit position - PadNumber + Bit value - 0: DoNotUnlock, 1: Unlock + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioUnlockPadCfgForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 PadsToUnlock + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + return GpioWriteLockReg ( + GpioPadConfigLockRegister, + Group, + DwNum, + ~PadsToUnlock, + 0 + ); +} + +/** + This procedure will clear PadCfgLock for selected pad. + This function should be used only inside SMI. + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioUnlockPadCfg ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + return GpioUnlockPadCfgForGroupDw ( + Group, + GPIO_GET_DW_NUM (PadNumber), + 1 << GPIO_GET_PAD_POSITION (PadNumber) + ); +} + +/** + This procedure will set PadCfgLock for selected pads within one group + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLock register number for current g= roup. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] PadsToLock Bitmask for pads which are going to be l= ocked + Bit position - PadNumber + Bit value - 0: DoNotLock, 1: Lock + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioLockPadCfgForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 PadsToLock + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + return GpioWriteLockReg ( + GpioPadConfigLockRegister, + Group, + DwNum, + ~0u, + PadsToLock + ); +} + +/** + This procedure will set PadCfgLock for selected pad + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioLockPadCfg ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + return GpioLockPadCfgForGroupDw ( + Group, + GPIO_GET_DW_NUM (PadNumber), + 1 << GPIO_GET_PAD_POSITION (PadNumber) + ); +} + +/** + This procedure will clear PadCfgLockTx for selected pads within one grou= p. + This function should be used only inside SMI. + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLockTx register number for current= group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] PadsToUnlockTx Bitmask for pads which are going to be u= nlocked, + Bit position - PadNumber + Bit value - 0: DoNotUnLockTx, 1: LockTx + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioUnlockPadCfgTxForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 PadsToUnlockTx + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + return GpioWriteLockReg ( + GpioPadLockOutputRegister, + Group, + DwNum, + ~PadsToUnlockTx, + 0 + ); +} + +/** + This procedure will clear PadCfgLockTx for selected pad. + This function should be used only inside SMI. + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioUnlockPadCfgTx ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + return GpioUnlockPadCfgTxForGroupDw ( + Group, + GPIO_GET_DW_NUM (PadNumber), + 1 << GPIO_GET_PAD_POSITION (PadNumber) + ); +} + +/** + This procedure will set PadCfgLockTx for selected pads within one group + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLock register number for current g= roup. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] PadsToLockTx Bitmask for pads which are going to be l= ocked, + Bit position - PadNumber + Bit value - 0: DoNotLockTx, 1: LockTx + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number +**/ +EFI_STATUS +GpioLockPadCfgTxForGroupDw ( + IN GPIO_GROUP Group, + IN UINT32 DwNum, + IN UINT32 PadsToLockTx + ) +{ + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) { + return EFI_INVALID_PARAMETER; + } + + return GpioWriteLockReg ( + GpioPadLockOutputRegister, + Group, + DwNum, + ~0u, + PadsToLockTx + ); +} + +/** + This procedure will set PadCfgLockTx for selected pad + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioLockPadCfgTx ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + return GpioLockPadCfgTxForGroupDw ( + Group, + GPIO_GET_DW_NUM (PadNumber), + 1 << GPIO_GET_PAD_POSITION (PadNumber) + ); +} + +/** + This procedure will get Group to GPE mapping. + It will assume that only first 32 pads can be mapped to GPE. + To handle cases where groups have more than 32 pads and higher part of g= roup + can be mapped please refer to GpioGetGroupDwToGpeDwX() + + @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0 + @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1 + @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2 + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioGetGroupToGpeDwX ( + IN GPIO_GROUP *GroupToGpeDw0, + IN GPIO_GROUP *GroupToGpeDw1, + IN GPIO_GROUP *GroupToGpeDw2 + ) +{ + UINT32 GroupDw[3]; + UINT32 Index; + EFI_STATUS Status; + + Status =3D GpioGetGroupDwToGpeDwX ( + GroupToGpeDw0, + &GroupDw[0], + GroupToGpeDw1, + &GroupDw[1], + GroupToGpeDw2, + &GroupDw[2] + ); + + for (Index =3D 0; Index < ARRAY_SIZE (GroupDw); Index++) { + if (GroupDw[Index] !=3D 0) { + Status =3D EFI_UNSUPPORTED; + ASSERT (FALSE); + } + } + return Status; +} + + +/** + This procedure will get Group to GPE mapping. If group has more than 32 = bits + it is possible to map only single DW of pins (e.g. 0-31, 32-63) because + ACPI GPE_DWx register is 32 bits large. + + @param[out] GroupToGpeDw0 GPIO group mapped to GPE_DW0 + @param[out] GroupDwForGpeDw0 DW of pins mapped to GPE_DW0 + @param[out] GroupToGpeDw1 GPIO group mapped to GPE_DW1 + @param[out] GroupDwForGpeDw1 DW of pins mapped to GPE_DW1 + @param[out] GroupToGpeDw2 GPIO group mapped to GPE_DW2 + @param[out] GroupDwForGpeDw2 DW of pins mapped to GPE_DW2 + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioGetGroupDwToGpeDwX ( + OUT GPIO_GROUP *GroupToGpeDw0, + OUT UINT32 *GroupDwForGpeDw0, + OUT GPIO_GROUP *GroupToGpeDw1, + OUT UINT32 *GroupDwForGpeDw1, + OUT GPIO_GROUP *GroupToGpeDw2, + OUT UINT32 *GroupDwForGpeDw2 + ) +{ + UINT32 PmcGpeDwXValue[3]; + GPIO_GROUP GroupToGpeDwX[3]; + UINT32 GroupDwForGpeDwX[3]; + UINT8 GpeDwXIndex; + UINT32 Index; + GPIO_GROUP_TO_GPE_MAPPING *GpioGpeMap; + UINT32 GpioGpeMapLength; + + ZeroMem (GroupToGpeDwX, sizeof (GroupToGpeDwX)); + ZeroMem (GroupDwForGpeDwX, sizeof (GroupDwForGpeDwX)); + + PmcGetGpioGpe (&PmcGpeDwXValue[0], &PmcGpeDwXValue[1], &PmcGpeDwXValue[2= ]); + + GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength); + + for (GpeDwXIndex =3D 0; GpeDwXIndex < 3; GpeDwXIndex++) { + for (Index =3D 0; Index < GpioGpeMapLength; Index++) { + + if (GpioGpeMap[Index].PmcGpeDwxVal =3D=3D PmcGpeDwXValue[GpeDwXIndex= ]) { + GroupToGpeDwX[GpeDwXIndex] =3D GpioGpeMap[Index].Group; + GroupDwForGpeDwX[GpeDwXIndex] =3D GpioGpeMap[Index].GroupDw; + break; + } + } + } + + if ((GroupToGpeDwX[0] =3D=3D 0) || + (GroupToGpeDwX[1] =3D=3D 0) || + (GroupToGpeDwX[2] =3D=3D 0)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + *GroupToGpeDw0 =3D GroupToGpeDwX[0]; + *GroupDwForGpeDw0 =3D GroupDwForGpeDwX[0]; + *GroupToGpeDw1 =3D GroupToGpeDwX[1]; + *GroupDwForGpeDw1 =3D GroupDwForGpeDwX[1]; + *GroupToGpeDw2 =3D GroupToGpeDwX[2]; + *GroupDwForGpeDw2 =3D GroupDwForGpeDwX[2]; + + return EFI_SUCCESS; +} + + +/** + This procedure will set Group to GPE mapping. + It will assume that only first 32 pads can be mapped to GPE. + To handle cases where groups have more than 32 pads and higher part of g= roup + can be mapped please refer to GpioSetGroupDwToGpeDwX() + + @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0 + @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1 + @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2 + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioSetGroupToGpeDwX ( + IN GPIO_GROUP GroupToGpeDw0, + IN GPIO_GROUP GroupToGpeDw1, + IN GPIO_GROUP GroupToGpeDw2 + ) +{ + return GpioSetGroupDwToGpeDwX ( + GroupToGpeDw0, + 0, + GroupToGpeDw1, + 0, + GroupToGpeDw2, + 0 + ); +} + +/** + This procedure will set Group to GPE mapping. If group has more than 32 = bits + it is possible to map only single DW of pins (e.g. 0-31, 32-63) because + ACPI GPE_DWx register is 32 bits large. + + @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0 + @param[in] GroupDwForGpeDw0 DW of pins to be mapped to GPE_DW0 + @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1 + @param[in] GroupDwForGpeDw1 DW of pins to be mapped to GPE_DW1 + @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2 + @param[in] GroupDwForGpeDw2 DW of pins to be mapped to GPE_DW2 + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioSetGroupDwToGpeDwX ( + IN GPIO_GROUP GroupToGpeDw0, + IN UINT32 GroupDwForGpeDw0, + IN GPIO_GROUP GroupToGpeDw1, + IN UINT32 GroupDwForGpeDw1, + IN GPIO_GROUP GroupToGpeDw2, + IN UINT32 GroupDwForGpeDw2 + ) +{ + UINT32 Data32Or; + UINT32 Data32And; + PCH_SBI_PID *GpioComSbiIds; + UINT32 NoOfGpioComs; + UINT32 GpioComIndex; + UINT32 GpioGpeDwx[3]; + UINT32 PmcGpeDwx[3]; + GPIO_GROUP GroupToGpeDwX[3]; + UINT32 GroupDwForGpeDwX[3]; + UINT8 GpeDwXIndex; + UINT32 Index; + GPIO_GROUP_TO_GPE_MAPPING *GpioGpeMap; + UINT32 GpioGpeMapLength; + + ZeroMem (GpioGpeDwx, sizeof (GpioGpeDwx)); + ZeroMem (PmcGpeDwx, sizeof (PmcGpeDwx)); + // + // Check if each group number is unique + // + if ((GroupToGpeDw0 =3D=3D GroupToGpeDw1) || + (GroupToGpeDw0 =3D=3D GroupToGpeDw2) || + (GroupToGpeDw1 =3D=3D GroupToGpeDw2)) { + return EFI_INVALID_PARAMETER; + } + + GroupToGpeDwX[0] =3D GroupToGpeDw0; + GroupDwForGpeDwX[0] =3D GroupDwForGpeDw0; + GroupToGpeDwX[1] =3D GroupToGpeDw1; + GroupDwForGpeDwX[1] =3D GroupDwForGpeDw1; + GroupToGpeDwX[2] =3D GroupToGpeDw2; + GroupDwForGpeDwX[2] =3D GroupDwForGpeDw2; + + GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength); + + for (GpeDwXIndex =3D 0; GpeDwXIndex < 3; GpeDwXIndex++) { + for (Index =3D 0; Index < GpioGpeMapLength; Index++) { + + if ((GpioGpeMap[Index].Group =3D=3D GroupToGpeDwX[GpeDwXIndex]) && + (GpioGpeMap[Index].GroupDw =3D=3D GroupDwForGpeDwX[GpeDwXIndex])= ) { + PmcGpeDwx[GpeDwXIndex] =3D GpioGpeMap[Index].PmcGpeDwxVal; + GpioGpeDwx[GpeDwXIndex] =3D GpioGpeMap[Index].GpioGpeDwxVal; + break; + } + } + + if (Index =3D=3D GpioGpeMapLength) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + } + + // + // Program GPE configuration in PMC register + // + PmcSetGpioGpe ( + PmcGpeDwx[0], + PmcGpeDwx[1], + PmcGpeDwx[2] + ); + + // + // Program GPE configuration in GPIO registers + // + Data32And =3D (UINT32) ~(B_GPIO_PCR_MISCCFG_GPE0_DW2 | B_GPIO_PCR_MISCCF= G_GPE0_DW1 | B_GPIO_PCR_MISCCFG_GPE0_DW0); + Data32Or =3D (UINT32) ((GpioGpeDwx[2] << N_GPIO_PCR_MISCCFG_GPE0_DW2) | + (GpioGpeDwx[1] << N_GPIO_PCR_MISCCFG_GPE0_DW1) | + (GpioGpeDwx[0] << N_GPIO_PCR_MISCCFG_GPE0_DW0)); + + NoOfGpioComs =3D GpioGetComSbiPortIds (&GpioComSbiIds); + + // + // Program MISCCFG register for each community + // + for (GpioComIndex =3D 0; GpioComIndex < NoOfGpioComs; GpioComIndex++) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioComSbiIds[GpioComIndex], R_GPIO_PCR_MISCCFG), + Data32And, + Data32Or + ); + } + + return EFI_SUCCESS; +} + +/** + This procedure will get GPE number for provided GpioPad. + PCH allows to configure mapping between GPIO groups and related GPE (Gpi= oSetGroupToGpeDwX()) + what results in the fact that certain Pad can cause different General Pu= rpose Event. Only three + GPIO groups can be mapped to cause unique GPE (1-tier), all others group= s will be under one common + event (GPE_111 for 2-tier). + + 1-tier: + Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used + to determine what _LXX ACPI method would be called on event on selected = GPIO pad + + 2-tier: + Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to = 1-tier GPE + will be under one master GPE_111 which is linked to _L6F ACPI method. If= it is needed to determine + what Pad from 2-tier has caused the event, _L6F method should check GPI_= GPE_STS and GPI_GPE_EN + registers for all GPIO groups not mapped to 1-tier GPE. + + @param[in] GpioPad GPIO pad + @param[out] GpeNumber GPE number + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetGpeNumber ( + IN GPIO_PAD GpioPad, + OUT UINT32 *GpeNumber + ) +{ + GPIO_GROUP GroupToGpeDwX[3]; + UINT32 GroupDw[3]; + GPIO_GROUP Group; + UINT32 PadNumber; + UINT32 Index; + EFI_STATUS Status; + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get GPIO groups mapping to 1-tier GPE + // This mapping is dependent on GPIO IP implementation + // and may change between chipset generations + // + Status =3D GpioGetGroupDwToGpeDwX ( + &GroupToGpeDwX[0], &GroupDw[0], + &GroupToGpeDwX[1], &GroupDw[1], + &GroupToGpeDwX[2], &GroupDw[2] + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if pad is routed to 1-Tier GPE + // + for (Index =3D 0; Index < 3; Index++) { + if ((Group =3D=3D GroupToGpeDwX[Index]) && (PadNumber >=3D (32 * Group= Dw[Index])) && (PadNumber < (32 * (GroupDw[Index] + 1)))) { + *GpeNumber =3D PadNumber + (32 * Index) - (32 * GroupDw[Index]); + return EFI_SUCCESS; + } + } + + // + // If Group number doesn't match any of above then + // it means that the pad is routed to 2-tier GPE + // which corresponds to GPE_111 (0x6F) + // + *GpeNumber =3D PCH_GPIO_2_TIER_MASTER_GPE_NUMBER; + + return EFI_SUCCESS; +} + +/** + This procedure is used to clear SMI STS for a specified Pad + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioClearGpiSmiSts ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + UINT32 DwNum; + UINT32 PadBitPosition; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + + // + // Clear GPI SMI Status bit by writing '1' + // + GpioWriteReg ( + GpioSmiStatusRegister, + Group, + DwNum, + 0u, + (UINT32) (BIT0 << PadBitPosition) + ); + + return EFI_SUCCESS; +} + +/** + This procedure is used by PchSmiDispatcher and will clear + all GPI SMI Status bits + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioClearAllGpiSmiSts ( + VOID + ) +{ + UINT32 DwNum; + GPIO_GROUP Group; + GPIO_GROUP GroupMin; + GPIO_GROUP GroupMax; + + GroupMin =3D GpioGetLowestGroup (); + GroupMax =3D GpioGetHighestGroup (); + + for (Group =3D GroupMin; Group <=3D GroupMax; Group++) { + // + // Clear all GPI SMI STS + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (Grou= p)); DwNum++) { + if (GpioIsSmiSupportedByGroupDw(Group, DwNum)) { + GpioWriteReg ( + GpioSmiStatusRegister, + Group, + DwNum, + 0u, + 0xFFFFFFFF + ); + } + } + } + return EFI_SUCCESS; + +} + +/** + This procedure is used to disable all GPI SMI + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioDisableAllGpiSmi ( + VOID + ) +{ + UINT32 DwNum; + GPIO_GROUP Group; + GPIO_GROUP GroupMin; + GPIO_GROUP GroupMax; + UINT32 SmiEnRegVal; + + GroupMin =3D GpioGetLowestGroup (); + GroupMax =3D GpioGetHighestGroup (); + + for (Group =3D GroupMin; Group <=3D GroupMax; Group++) { + // + // Disable all GPI SMI + // + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (Grou= p)); DwNum++) { + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) { + SmiEnRegVal =3D 0; + // + // Check which pins have SMI_EN set + // + GpioReadReg ( + GpioSmiEnableRegister, + Group, + DwNum, + &SmiEnRegVal + ); + // + // Set HOSTSW_OWN to GPIO mode (1) for those pins to disable SMI= capability + // + GpioWriteReg ( + GpioHostOwnershipRegister, + Group, + DwNum, + ~0u, + SmiEnRegVal + ); + } + } + } + return EFI_SUCCESS; +} + +/** + This procedure is used to register GPI SMI dispatch function. + + @param[in] GpioPad GPIO pad + @param[out] GpiNum GPI number + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetGpiSmiNum ( + IN GPIO_PAD GpioPad, + OUT UINTN *GpiNum + ) +{ + UINT32 GroupIndex; + UINT32 Index; + UINT32 PadNumber; + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + *GpiNum =3D 0; + + for (Index =3D 0; Index < GroupIndex; Index++) { + *GpiNum +=3D (UINTN) (GpioGroupInfo[Index].PadPerGroup); + } + *GpiNum +=3D (UINTN) PadNumber; + + return EFI_SUCCESS; +} + +/** + This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier = architecture + + @param[in] GpioPad GPIO pad + + @retval Data 0 means 1-tier, 1 means 2-tier +**/ +BOOLEAN +GpioCheckFor2Tier ( + IN GPIO_PAD GpioPad + ) +{ + UINT32 Data32; + EFI_STATUS Status; + + Status =3D GpioGetGpeNumber (GpioPad, &Data32); + if (EFI_ERROR (Status)) { + DEBUG (( DEBUG_ERROR, "GpioCheckFor2Tier: Failed to get GPE number. St= atus: %r\n", Status )); + return FALSE; + } + + if (Data32 =3D=3D PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) { + return TRUE; + } + + return FALSE; +} + +/** + This procedure is used to clear GPE STS for a specified GpioPad + + @param[in] GpioPad GPIO pad + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioClearGpiGpeSts ( + IN GPIO_PAD GpioPad + ) +{ + GPIO_GROUP Group; + UINT32 PadNumber; + UINT32 DwNum; + UINT32 PadBitPosition; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + // + // Check for 2-tier + // + if (!(GpioCheckFor2Tier (GpioPad))) { + return EFI_INVALID_PARAMETER; + } + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + + // + // Clear GPI GPE Status bit by writing '1' + // + GpioWriteReg ( + GpioGpeStatusRegister, + Group, + DwNum, + 0u, + (UINT32) (BIT0 << PadBitPosition) + ); + + return EFI_SUCCESS; +} + +/** + This procedure is used to read GPE STS for a specified Pad + + @param[in] GpioPad GPIO pad + @param[out] Data GPE STS data + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid GpioPad +**/ +EFI_STATUS +GpioGetGpiGpeSts ( + IN GPIO_PAD GpioPad, + OUT UINT32 *Data + ) +{ + UINT32 GpeStsRegVal; + GPIO_GROUP Group; + UINT32 PadNumber; + UINT32 DwNum; + UINT32 PadBitPosition; + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + // + // Check for 2-tier + // + if (!(GpioCheckFor2Tier (GpioPad))) { + return EFI_INVALID_PARAMETER; + } + + Group =3D GpioGetGroupFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + DwNum =3D GPIO_GET_DW_NUM (PadNumber); + PadBitPosition =3D GPIO_GET_PAD_POSITION (PadNumber); + + // + // Read GPI GPE Status bits + // + GpioReadReg ( + GpioGpeStatusRegister, + Group, + DwNum, + &GpeStsRegVal + ); + + *Data =3D (GpeStsRegVal >> PadBitPosition) & 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure is used to lock all GPIO pads except the ones + which were requested during their configuration to be left unlocked. + This function must be called before BIOS_DONE - before POSTBOOT_SAI is e= nabled. + FSP - call this function from wrapper before transition to FSP-S + UEFI/EDK - call this function before EndOfPei event + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioLockPads ( + VOID + ) +{ + UINT32 DwNum; + GPIO_GROUP Group; + GPIO_GROUP GroupMin; + GPIO_GROUP GroupMax; + UINT32 UnlockedPads; + EFI_STATUS Status; + + GroupMin =3D GpioGetLowestGroup (); + GroupMax =3D GpioGetHighestGroup (); + + for (Group =3D GroupMin; Group <=3D GroupMax; Group++) { + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (Grou= p)); DwNum++) { + + UnlockedPads =3D GpioGetGroupDwUnlockPadConfigMask (GpioGetGroupInde= xFromGroup (Group), DwNum); + + Status =3D GpioLockPadCfgForGroupDw (Group, DwNum, (UINT32)~Unlocked= Pads); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + UnlockedPads =3D GpioGetGroupDwUnlockOutputMask (GpioGetGroupIndexFr= omGroup (Group), DwNum); + + Status =3D GpioLockPadCfgTxForGroupDw (Group, DwNum, (UINT32)~Unlock= edPads); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + } + } + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/GpioNames.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpi= oLib/GpioNames.c new file mode 100644 index 0000000000..ec33d06156 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioN= ames.c @@ -0,0 +1,87 @@ +/** @file + This file contains GPIO name library implementation + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "GpioLibrary.h" +#include + +/** + Generates GPIO group name from GpioPad + + @param[in] GpioPad GpioPad + + @retval CHAR8* Pointer to the GPIO group name +**/ +CONST +CHAR8* +GpioGetGroupName ( + IN UINT32 GroupIndex + ) +{ + CONST GPIO_GROUP_NAME_INFO* GroupNameInfo; + + GroupNameInfo =3D GpioGetGroupNameInfo (GroupIndex); + if (GroupNameInfo =3D=3D NULL) { + return NULL; + } else { + return GroupNameInfo->GpioGroupPrefix; + } +} + +/** + Generates GPIO name from GpioPad + + @param[in] GpioPad GpioPad + @param[out] GpioNameBuffer Caller allocated buffer of GPIO_NAME_LEN= GTH_MAX size + @param[in] GpioNameBufferSize Size of the buffer + + @retval CHAR8* Pointer to the GPIO name +**/ +CHAR8* +GpioGetPadName ( + IN GPIO_PAD GpioPad, + OUT CHAR8* GpioNameBuffer, + IN UINT32 GpioNameBufferSize + ) +{ + UINT32 GroupIndex; + UINT32 PadNumber; + UINT32 FirstUniquePadNumber; + CONST GPIO_GROUP_NAME_INFO* GroupNameInfo; + + if (GpioNameBuffer =3D=3D NULL) { + ASSERT (FALSE); + return NULL; + } + if ((GpioNameBufferSize < GPIO_NAME_LENGTH_MAX) || !GpioIsPadValid (Gpio= Pad)) { + ASSERT (FALSE); + *GpioNameBuffer =3D 0; + return NULL; + } + + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + GroupNameInfo =3D GpioGetGroupNameInfo (GroupIndex); + if (GroupNameInfo =3D=3D NULL) { + return NULL; + } + + FirstUniquePadNumber =3D GpioGetPadNumberFromGpioPad (GroupNameInfo->Fir= stUniqueGpio); + if ((PadNumber < FirstUniquePadNumber) || (GroupNameInfo->GroupUniqueNam= es =3D=3D NULL)) { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a%d", GpioGe= tGroupName (GroupIndex), PadNumber); + } else { + if (PadNumber - FirstUniquePadNumber < GroupNameInfo->UniqueNamesTable= Size) { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a", GroupN= ameInfo->GroupUniqueNames[PadNumber - FirstUniquePadNumber]); + } else { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%08X", Gpio= Pad); + ASSERT (FALSE); + } + } + + return GpioNameBuffer; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLi= b/GpioNativeLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSm= mGpioLib/GpioNativeLib.c new file mode 100644 index 0000000000..9b71cb1d95 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioN= ativeLib.c @@ -0,0 +1,234 @@ +/** @file + This file contains routines for GPIO native and chipset specific usage + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "GpioLibrary.h" + +/** + This procedure will get number of pads for certain GPIO group + + @param[in] Group GPIO group number + + @retval Value Pad number for group + If illegal group number then return 0 +**/ +UINT32 +GpioGetPadPerGroup ( + IN GPIO_GROUP Group + ) +{ + CONST GPIO_GROUP_INFO *GpioGroupInfo; + UINT32 GpioGroupInfoLength; + UINT32 GroupIndex; + // + // Check if group argument exceeds GPIO GROUP INFO array + // + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + GroupIndex =3D GpioGetGroupIndexFromGroup (Group); + + if ((UINTN) GroupIndex >=3D GpioGroupInfoLength) { + return 0; + } else { + return GpioGroupInfo[GroupIndex].PadPerGroup; + } +} + +/** + This procedure will get number of groups + + @param[in] none + + @retval Value Group number +**/ +UINT32 +GpioGetNumberOfGroups ( + VOID + ) +{ + UINT32 GpioGroupInfoLength; + + GpioGetGroupInfoTable (&GpioGroupInfoLength); + return GpioGroupInfoLength; +} +/** + This procedure will get lowest group + + @param[in] none + + @retval Value Lowest Group +**/ +GPIO_GROUP +GpioGetLowestGroup ( + VOID + ) +{ + return GpioGetGroupFromGroupIndex (0); +} +/** + This procedure will get highest group + + @param[in] none + + @retval Value Highest Group +**/ +GPIO_GROUP +GpioGetHighestGroup ( + VOID + ) +{ + return GpioGetGroupFromGroupIndex (GpioGetNumberOfGroups () - 1); +} + +/** + This procedure will get group number + + @param[in] GpioPad Gpio Pad + + @retval Value Group number +**/ +GPIO_GROUP +GpioGetGroupFromGpioPad ( + IN GPIO_PAD GpioPad + ) +{ + return GPIO_GET_GROUP_FROM_PAD (GpioPad); +} + +/** + This procedure will get group index (0 based) + + @param[in] GpioPad Gpio Pad + + @retval Value Group Index +**/ +UINT32 +GpioGetGroupIndexFromGpioPad ( + IN GPIO_PAD GpioPad + ) +{ + return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad); +} + +/** + This procedure will get group index (0 based) from group + + @param[in] GpioGroup Gpio Group + + @retval Value Group Index +**/ +UINT32 +GpioGetGroupIndexFromGroup ( + IN GPIO_GROUP GpioGroup + ) +{ + return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup); +} + +/** + This procedure will get group from group index (0 based) + + @param[in] GroupIndex Group Index + + @retval GpioGroup Gpio Group +**/ +GPIO_GROUP +GpioGetGroupFromGroupIndex ( + IN UINT32 GroupIndex + ) +{ + return GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ()); +} + +/** + This procedure will get pad number (0 based) from Gpio Pad + + @param[in] GpioPad Gpio Pad + + @retval Value Pad Number +**/ +UINT32 +GpioGetPadNumberFromGpioPad ( + IN GPIO_PAD GpioPad + ) +{ + return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad); +} +/** + This procedure will return GpioPad from Group and PadNumber + + @param[in] Group GPIO group + @param[in] PadNumber GPIO PadNumber + + @retval GpioPad GpioPad +**/ +GPIO_PAD +GpioGetGpioPadFromGroupAndPadNumber ( + IN GPIO_GROUP Group, + IN UINT32 PadNumber + ) +{ + if (IsPchLp ()) { + return GPIO_PAD_DEF (Group,PadNumber); + } else { + return GPIO_PAD_DEF (Group,PadNumber); + } +} + +/** + This procedure will return GpioPad from GroupIndex and PadNumber + + @param[in] GroupIndex GPIO GroupIndex + @param[in] PadNumber GPIO PadNumber + + @retval GpioPad GpioPad +**/ +GPIO_PAD +GpioGetGpioPadFromGroupIndexAndPadNumber ( + IN UINT32 GroupIndex, + IN UINT32 PadNumber + ) +{ + GPIO_GROUP Group; + + Group =3D GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ()); + return GPIO_PAD_DEF (Group, PadNumber); +} + +/** + This function checks if SATA GP pin is enabled + + @param[in] SataCtrlIndex SATA controller index + @param[in] SataPort SATA port number + + @retval TRUE SATA GPx is enabled (pad is in required = native mode) + FALSE SATA GPx is not enabled +**/ +BOOLEAN +GpioIsSataGpEnabled ( + IN UINT32 SataCtrlIndex, + IN UINTN SataPort + ) +{ + EFI_STATUS Status; + GPIO_PAD_NATIVE_FUNCTION SataGpGpio; + GPIO_PAD_MODE GpioMode; + + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + GpioGetSataGpPin ( + SataCtrlIndex, + SataPort, + &SataGpGpio + ); + + Status =3D GpioGetPadMode (SataGpGpio.Pad, &GpioMode); + if ((EFI_ERROR (Status)) || (GpioMode !=3D SataGpGpio.Mode)) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCyc= leDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pc= h/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c new file mode 100644 index 0000000000..24afbbf712 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecod= ingLib/PchCycleDecodingLib.c @@ -0,0 +1,1136 @@ +/** @file + PCH cycle deocding configuration and query library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + SlaveLpcEspiCS0, + SlaveEspiCS1, + SlaveId_Max +} SLAVE_ID_INDEX; + +/** + Set PCH TCO base address. + This cycle decoding is required also on DMI side + Programming steps: + 1. set Smbus PCI offset 54h [8] to enable TCO base address. + 2. program Smbus PCI offset 50h [15:5] to TCO base address. + 3. set Smbus PCI offset 54h [8] to enable TCO base address. + 4. program "TCO Base Address" in DMI + + @param[in] Address Address for TCO base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchTcoBaseSet ( + IN UINT16 Address + ) +{ + UINT64 SmbusBase; + EFI_STATUS Status; + + if ((Address & ~B_SMBUS_CFG_TCOBASE_BAR) !=3D 0) { + DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n", Ad= dress)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Status =3D PchDmiSetTcoBase (Address); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + SmbusBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + 0 + ); + if (PciSegmentRead16 (SmbusBase) =3D=3D 0xFFFF) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + // + // Verify TCO base is not locked. + // + if ((PciSegmentRead8 (SmbusBase + R_SMBUS_CFG_TCOCTL) & B_SMBUS_CFG_TCOC= TL_TCO_BASE_LOCK) !=3D 0) { + ASSERT (FALSE); + return EFI_DEVICE_ERROR; + } + // + // Disable TCO in SMBUS Device first before changing base address. + // Byte access to not touch the TCO_BASE_LOCK bit + // + PciSegmentAnd8 ( + SmbusBase + R_SMBUS_CFG_TCOCTL + 1, + (UINT8) ~(B_SMBUS_CFG_TCOCTL_TCO_BASE_EN >> 8) + ); + // + // Program TCO in SMBUS Device + // + PciSegmentAndThenOr16 ( + SmbusBase + R_SMBUS_CFG_TCOBASE, + (UINT16) (~B_SMBUS_CFG_TCOBASE_BAR), + Address + ); + // + // Enable TCO in SMBUS Device and lock TCO BASE + // + PciSegmentOr16 ( + SmbusBase + R_SMBUS_CFG_TCOCTL, + B_SMBUS_CFG_TCOCTL_TCO_BASE_EN | B_SMBUS_CFG_TCOCTL_TCO_BASE_LOCK + ); + + return Status; +} + +/** + Get PCH TCO base address. + + @param[out] Address Address of TCO base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid pointer passed. +**/ +EFI_STATUS +PchTcoBaseGet ( + OUT UINT16 *Address + ) +{ + if (Address =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n")); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + // + // Read "TCO Base Address" from DMI + // Don't read TCO base address from SMBUS PCI register since SMBUS might= be disabled. + // + *Address =3D PchDmiGetTcoBase (); + + return EFI_SUCCESS; +} + +/** + Returns PCH LPC device PCI base address. + + @retval PCH LPC PCI base address. +**/ +STATIC +UINT64 +LpcPciBase ( + VOID + ) +{ + return PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); +} + +/** + Function checks if passed Generic LPC IO Address and Length meets requir= ements. + + @param[in] Address Address for generic IO range decod= ing. + @param[in] Length Length of generic IO range. + + @retval TRUE Passed IO range meets requirements + @retval FALSE Passed IO range does not meets req= uirements. +**/ +STATIC +BOOLEAN +IsLpcIoRangeValid ( + IN UINT32 Address, + IN UINT32 Length + ) +{ + UINT32 Index; + UINT32 NumRanges; + + STATIC struct EXCEPT_RANGE { + UINT8 Start; + UINT8 Length; + } ExceptRanges[] =3D { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, = 0x08}, {0x80, 0x10}, {0xC0, 0x40} }; + + NumRanges =3D ARRAY_SIZE (ExceptRanges); + // + // For generic IO range, the base address must align to 4 and less than = 0xFFFF, + // the length must be power of 2 and less than or equal to 256, and the = address must be length aligned. + // IO range below 0x100 will be rejected in this function except below r= anges: + // 0x00-0x1F, + // 0x44-0x4B, + // 0x54-0x5F, + // 0x68-0x6F, + // 0x80-0x8F, + // 0xC0-0xFF + // + if (((Length & (Length - 1)) !=3D 0) || + ((Address & (UINT16) ~B_LPC_CFG_GENX_DEC_IOBAR) !=3D 0) || + (Length > 256)) { + return FALSE; + } + if (Address < 0x100) { + for (Index =3D 0; Index < NumRanges; Index++) { + if ((Address >=3D ExceptRanges[Index].Start) && + ((Address + Length) <=3D ((UINTN) ExceptRanges[Index].Start + (U= INTN) ExceptRanges[Index].Length))) { + break; + } + } + if (Index >=3D NumRanges) { + return FALSE; + } + } + + return TRUE; +} + +/** + Function checks if passed Generic LPC IO Range is already in Gen IO Rang= e list + + @param[in] Address Address for generic IO range decod= ing. + @param[in] Length Length of generic IO range. + @param[in] GenIoRangeList Pointer to Generic IO Ranges List + + @retval TRUE Passed IO range alredy covered + @retval FALSE Passed IO range NOT covered +**/ +STATIC +BOOLEAN +IsRangeInList ( + IN UINT32 Address, + IN UINT32 Length, + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList + ) +{ + UINT32 CurrentBaseAddr; + UINT32 CurrentLength; + UINT32 Index; + + for (Index =3D 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + CurrentBaseAddr =3D GenIoRangeList->Range[Index].BaseAddr; + CurrentLength =3D GenIoRangeList->Range[Index].Length; + if (GenIoRangeList->Range[Index].Enable =3D=3D 0) { + continue; + } + if ((Address >=3D CurrentBaseAddr) && ((Address + Length) <=3D (Curren= tBaseAddr + CurrentLength))) { + return TRUE; + } + } + + return FALSE; +} + +/** + Function checks if passed Generic LPC IO Range overlaps with existing ra= nge + + @param[in] Address Address for generic IO range base = address. + @param[in] Length Length of generic IO range. + @param[in] GenIoRangeList Pointer to Generic IO Ranges List + + @retval TRUE Passed LPC IO range overlaps with = existing range + @retval FALSE Passed LPC IO range NOT overlaps +**/ +STATIC +BOOLEAN +FindOverlappingGenIoRange ( + IN UINT32 Address, + IN UINT32 Length, + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList + ) +{ + UINT32 Index; + UINT32 CurrentBaseAddr; + UINT32 CurrentLength; + + for (Index =3D 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + CurrentBaseAddr =3D GenIoRangeList->Range[Index].BaseAddr; + CurrentLength =3D GenIoRangeList->Range[Index].Length; + if (GenIoRangeList->Range[Index].Enable =3D=3D 0) { + continue; + } + + if ((Address >=3D CurrentBaseAddr) && + (Address <=3D (CurrentBaseAddr + CurrentLength))) { + return TRUE; + } else if (((Address + Length) >=3D CurrentBaseAddr) && + ((Address + Length) <=3D (CurrentBaseAddr + CurrentLength)))= { + return TRUE; + } + } + + return FALSE; +} + +/** + Function look for empty Generic IO range register. + If found return range index. + + @param[in] GenIoRangeList Pointer to Generic IO Ranges List + @param[in] ListLength Length of passed list + @param[out] RangeIndex Generic IO Range Index + + @retval TRUE Empty range found + @retval FALSE NOT found empty range +**/ +STATIC +BOOLEAN +FindEmptyGenIoRange ( + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList, + IN UINT32 ListLength, + OUT UINT32 *RangeIndex + ) +{ + UINT32 Index; + + for (Index =3D 0; Index < ListLength; Index++) { + if (GenIoRangeList->Range[Index].Enable =3D=3D 0) { + *RangeIndex =3D Index; + return TRUE; + } + } + + return FALSE; +} + +/** + Get PCH LPC/eSPI and eSPI CS1# generic IO range list. + This function returns a list of base address, length, and enable for all= LPC/eSPI or eSPI CS1# generic IO range registers. + + @param[in] RangeIndex Slave ID (refer to SLAVE_ID_INDEX) + @param[out] GenIoRangeList LPC/eSPI or eSPI CS1# generic IO r= ange registers. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. +**/ +EFI_STATUS +LpcEspiGenIoRangeGetHelper ( + IN SLAVE_ID_INDEX SlaveId, + OUT PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList + ) +{ + UINT32 Index; + UINT64 LpcBase; + UINT32 Data32; + UINT32 GenIoReg; + + if ((GenIoRangeList =3D=3D NULL) || (SlaveId >=3D SlaveId_Max)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + LpcBase =3D LpcPciBase (); + + if (SlaveId =3D=3D SlaveEspiCS1) { + GenIoReg =3D R_ESPI_CFG_CS1GIR1; + } else { + GenIoReg =3D R_LPC_CFG_GEN1_DEC; + } + + for (Index =3D 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + if ((SlaveId =3D=3D SlaveEspiCS1) && + (Index > 0)) { + // For eSPI CS1# we have only one range. Reset remaining entries to = zero. + GenIoRangeList->Range[Index].BaseAddr =3D 0; + GenIoRangeList->Range[Index].Enable =3D 0; + GenIoRangeList->Range[Index].Length =3D 0; + continue; + } + Data32 =3D PciSegmentRead32 (LpcBase + GenIoReg + Index * 4); + GenIoRangeList->Range[Index].BaseAddr =3D Data32 & B_LPC_CFG_GENX_DEC_= IOBAR; + GenIoRangeList->Range[Index].Length =3D ((Data32 & B_LPC_CFG_GENX_DE= C_IODRA) >> 16) + 4; + GenIoRangeList->Range[Index].Enable =3D Data32 & B_LPC_CFG_GENX_DEC_= EN; + } + + return EFI_SUCCESS; +} + + +/** + Function checks if passed Generic LPC IO Range colliding + with range alredy defined for other eSPI chiselect (CS) + + @param[in] Address Address for generic IO range base = address. + @param[in] Length Length of generic IO range. + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX) + + @retval TRUE Passed IO range conflicting + @retval FALSE There is no conflict +**/ +STATIC +BOOLEAN +IsRangeColliding ( + IN UINT32 Address, + IN UINT32 Length, + IN SLAVE_ID_INDEX SlaveId + ) +{ + EFI_STATUS Status; + PCH_LPC_GEN_IO_RANGE_LIST GenIoRangeList; + + if (SlaveId =3D=3D SlaveEspiCS1) { + Status =3D LpcEspiGenIoRangeGetHelper (SlaveLpcEspiCS0, &GenIoRangeLi= st); + if (!EFI_ERROR (Status)) { + if (FindOverlappingGenIoRange (Address, Length, &GenIoRangeList) || + IsRangeInList (Address, Length, &GenIoRangeList)) { + return TRUE; + } + } + } else { + Status =3D LpcEspiGenIoRangeGetHelper (SlaveEspiCS1, &GenIoRangeList)= ; + if (!EFI_ERROR (Status)) { + if (FindOverlappingGenIoRange (Address, Length, &GenIoRangeList) || + IsRangeInList (Address, Length, &GenIoRangeList)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + Set PCH LPC/eSPI and eSPI CS1# generic IO range decoding. + + Steps of programming generic IO range: + 1. Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI C= S1#) of Mask, Address, and Enable. + 2. Program LPC/eSPI Generic IO Range in DMI + + @param[in] Address Address for generic IO range decod= ing. + @param[in] Length Length of generic IO range. + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX) + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. + @retval EFI_OUT_OF_RESOURCES No more generic range available. + @retval EFI_UNSUPPORTED DMI configuration is locked, + GenIO range conflicting with other= eSPI CS +**/ +STATIC +EFI_STATUS +LpcEspiGenIoRangeSetHelper ( + IN UINT32 Address, + IN UINT32 Length, + IN SLAVE_ID_INDEX SlaveId + ) +{ + EFI_STATUS Status; + PCH_LPC_GEN_IO_RANGE_LIST GenIoRangeList; + UINT32 RangeIndex; + UINT32 Data32; + UINT32 GenIoReg; + UINT32 ListLength; + + // + // Check if pasesed Address and Length meets all requirements + // + if(!IsLpcIoRangeValid (Address, Length) || (SlaveId >=3D SlaveId_Max)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Read current Generic IO configuration + // + Status =3D LpcEspiGenIoRangeGetHelper (SlaveId, &GenIoRangeList); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if passed Generic IO range is already covered in current config= uration + // + if (IsRangeInList (Address, Length, &GenIoRangeList)) { + return EFI_SUCCESS; + } + + // + // Check if passed Generic IO range conflicting with other eSPI CS decod= ing + // + if (IsRangeColliding (Address, Length, SlaveId)) { + return EFI_UNSUPPORTED; + } + + if (SlaveId =3D=3D SlaveEspiCS1) { + GenIoReg =3D R_ESPI_CFG_CS1GIR1; + ListLength =3D ESPI_CS1_GEN_IO_RANGE_MAX; + } else { + GenIoReg =3D R_LPC_CFG_GEN1_DEC; + ListLength =3D PCH_LPC_GEN_IO_RANGE_MAX; + } + + RangeIndex =3D ListLength; + // + // Check if there is an empty Generic IO range register + // + if (FindEmptyGenIoRange (&GenIoRangeList, ListLength, &RangeIndex) =3D= =3D FALSE) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Program decoding in DMI and LPC/eSPI registers + // + if (SlaveId =3D=3D SlaveEspiCS1) { + ASSERT (RangeIndex =3D=3D 0); + Status =3D PchDmiSetEspiCs1GenIoRange (Address, Length); + } else { + Status =3D PchDmiSetLpcGenIoRange (Address, Length, RangeIndex); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Program LPC/eSPI generic IO range register accordingly. + // + Data32 =3D (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA); + Data32 |=3D (UINT32) Address; + Data32 |=3D B_LPC_CFG_GENX_DEC_EN; + + // + // Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI C= S1#) of Mask, Address, and Enable. + // + PciSegmentWrite32 ( + LpcPciBase () + GenIoReg + RangeIndex * 4, + Data32 + ); + + return Status; +} + +/** + Set PCH LPC/eSPI generic IO range. + For generic IO range, the base address must align to 4 and less than 0xF= FFF, and the length must be power of 2 + and less than or equal to 256. Moreover, the address must be length alig= ned. + This function basically checks the address and length, which should not = overlap with all other generic ranges. + If no more generic range register available, it returns out of resource = error. + This cycle decoding is also required on DMI side + Some IO ranges below 0x100 have fixed target. The target might be ITSS,R= TC,LPC,PMC or terminated inside P2SB + but all predefined and can't be changed. IO range below 0x100 will be re= jected in this function except below ranges: + 0x00-0x1F, + 0x44-0x4B, + 0x54-0x5F, + 0x68-0x6F, + 0x80-0x8F, + 0xC0-0xFF + Steps of programming generic IO range: + 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable. + 2. Program LPC/eSPI Generic IO Range in DMI + + @param[in] Address Address for generic IO range base = address. + @param[in] Length Length of generic IO range. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. + @retval EFI_OUT_OF_RESOURCES No more generic range available. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchLpcGenIoRangeSet ( + IN UINT16 Address, + IN UINTN Length + ) +{ + return LpcEspiGenIoRangeSetHelper ((UINT32)Address, (UINT32)Length, Slav= eLpcEspiCS0); +} + +/** + Set PCH eSPI CS1# generic IO range decoding. + + Steps of programming generic IO range: + 1. Program eSPI PCI Offset A4h (eSPI CS1#) of Mask, Address, and Enable. + 2. Program eSPI Generic IO Range in DMI + + @param[in] Address Address for generic IO range decod= ing. + @param[in] Length Length of generic IO range. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. + @retval EFI_OUT_OF_RESOURCES No more generic range available. + @retval EFI_UNSUPPORTED eSPI secondary slave not supported +**/ +EFI_STATUS +PchEspiCs1GenIoRangeSet ( + IN UINT16 Address, + IN UINTN Length + ) +{ + if (!IsEspiSecondSlaveSupported ()) { + return EFI_UNSUPPORTED; + } + + return LpcEspiGenIoRangeSetHelper ((UINT32)Address, (UINT32)Length, Slav= eEspiCS1); +} + +/** + Get PCH LPC/eSPI generic IO range list. + This function returns a list of base address, length, and enable for all= LPC/eSPI generic IO range registers. + + @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO ran= ge register status. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. +**/ +EFI_STATUS +PchLpcGenIoRangeGet ( + OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList + ) +{ + return LpcEspiGenIoRangeGetHelper (SlaveLpcEspiCS0, LpcGenIoRangeList); +} + +/** + Get PCH eSPI CS1# generic IO range list. + This function returns a list of base address, length, and enable for all= eSPI CS1# generic IO range registers. + + @param[out] GenIoRangeList eSPI generic IO range registers. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. + @retval EFI_UNSUPPORTED eSPI secondary slave not supported +**/ +EFI_STATUS +PchEspiCs1GenIoRangeGet ( + OUT PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList + ) +{ + if (!IsEspiSecondSlaveSupported ()) { + return EFI_UNSUPPORTED; + } + + return LpcEspiGenIoRangeGetHelper (SlaveEspiCS1, GenIoRangeList); +} + +/** + Set PCH LPC/eSPI and eSPI CS1# memory range decoding. + This cycle decoding is required to be set on DMI side + Programming steps: + 1. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [= 0] to [0] to disable memory decoding first before changing base address. + 2. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [= 31:16, 0] to [Address, 1]. + 3. Program LPC/eSPI Memory Range in DMI + + @param[in] Address Address for memory for decoding. + @param[in] RangeIndex Slave ID (refer to SLAVE_ID_INDEX) + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. +**/ +EFI_STATUS +LpcEspiMemRangeSetHelper ( + IN UINT32 Address, + IN SLAVE_ID_INDEX SlaveId + ) +{ + UINT64 LpcBase; + EFI_STATUS Status; + UINT32 GenMemReg; + UINT32 MemRangeAddr; + + if (((Address & (~B_LPC_CFG_LGMR_MA)) !=3D 0) || (SlaveId >=3D SlaveId_M= ax)) { + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeSet Error. Invalid Address: %x= or invalid SlaveId\n", Address)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + LpcBase =3D LpcPciBase (); + + MemRangeAddr =3D ~Address; + if (SlaveId =3D=3D SlaveEspiCS1) { + GenMemReg =3D R_ESPI_CFG_CS1GMR1; + // Memory Range already decoded for LPC/eSPI? + Status =3D PchLpcMemRangeGet (&MemRangeAddr); + if (MemRangeAddr !=3D Address) { + Status =3D PchDmiSetEspiCs1MemRange (Address); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } else { + GenMemReg =3D R_LPC_CFG_LGMR; + // Memory Range already decoded for eSPI CS1? + Status =3D PchEspiCs1MemRangeGet (&MemRangeAddr); + if (MemRangeAddr !=3D Address) { + Status =3D PchDmiSetLpcMemRange (Address); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } + + // + // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [= 0] to [0] to disable memory decoding first before changing base address. + // + PciSegmentAnd32 ( + LpcBase + GenMemReg, + (UINT32) ~B_LPC_CFG_LGMR_LMRD_EN + ); + // + // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [= 31:16, 0] to [Address, 1]. + // + PciSegmentWrite32 ( + LpcBase + GenMemReg, + (Address | B_LPC_CFG_LGMR_LMRD_EN) + ); + + return Status; +} + +/** + Set PCH LPC/eSPI memory range decoding. + This cycle decoding is required to be set on DMI side + Programming steps: + 1. Program LPC PCI Offset 98h [0] to [0] to disable memory decoding firs= t before changing base address. + 2. Program LPC PCI Offset 98h [31:16, 0] to [Address, 1]. + 3. Program LPC Memory Range in DMI + + @param[in] Address Address for memory base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. + @retval EFI_OUT_OF_RESOURCES No more generic range available. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchLpcMemRangeSet ( + IN UINT32 Address + ) +{ + return LpcEspiMemRangeSetHelper (Address, SlaveLpcEspiCS0); +} + +/** + Set PCH eSPI CS1# memory range decoding. + This cycle decoding is required to be set on DMI side + Programming steps: + 1. Program eSPI PCI Offset A8h (eSPI CS1#) [0] to [0] to disable memory = decoding first before changing base address. + 2. Program eSPI PCI Offset A8h (eSPI CS1#) [31:16, 0] to [Address, 1]. + 3. Program eSPI Memory Range in DMI + + @param[in] Address Address for memory for decoding. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length pas= sed. + @retval EFI_UNSUPPORTED eSPI secondary slave not supported +**/ +EFI_STATUS +PchEspiCs1MemRangeSet ( + IN UINT32 Address + ) +{ + if (!IsEspiSecondSlaveSupported ()) { + return EFI_UNSUPPORTED; + } + + return LpcEspiMemRangeSetHelper (Address, SlaveEspiCS1); +} + +/** + @deprecated. Keep this for backward compatibility. + It's replaced by PchEspiCs1MemRangeSet. +**/ +EFI_STATUS +PchEspiMemRange2Set ( + IN UINT32 Address + ) +{ + return PchEspiCs1MemRangeSet (Address); +} + +/** + Get PCH LPC/eSPI and eSPI CS1# memory range decoding address. + + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX) + @param[out] Address Address of LPC/eSPI or eSPI CS1# m= emory decoding base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. + @retval EFI_UNSUPPORTED eSPI secondary slave not supported +**/ +EFI_STATUS +LpcEspiMemRangeGetHelper ( + IN SLAVE_ID_INDEX SlaveId, + OUT UINT32 *Address + ) +{ + UINT32 GenMemReg; + + if ((Address =3D=3D NULL) || (SlaveId >=3D SlaveId_Max)) { + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeGet Error. Invalid pointer or = SlaveId.\n")); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + if (SlaveId =3D=3D SlaveEspiCS1) { + GenMemReg =3D R_ESPI_CFG_CS1GMR1; + } else { + GenMemReg =3D R_LPC_CFG_LGMR; + } + *Address =3D PciSegmentRead32 (LpcPciBase () + GenMemReg) & B_LPC_CFG_LG= MR_MA; + return EFI_SUCCESS; +} + +/** + Get PCH LPC/eSPI memory range decoding address. + + @param[out] Address Address of LPC/eSPI memory decodin= g base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. +**/ +EFI_STATUS +PchLpcMemRangeGet ( + OUT UINT32 *Address + ) +{ + return LpcEspiMemRangeGetHelper (SlaveLpcEspiCS0, Address); +} + +/** + Get PCH eSPI CS1# memory range decoding address. + + @param[out] Address Address of eSPI CS1# memory decodi= ng base address. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address passed. + @retval EFI_UNSUPPORTED eSPI secondary slave not supported +**/ +EFI_STATUS +PchEspiCs1MemRangeGet ( + OUT UINT32 *Address + ) +{ + if (!IsEspiSecondSlaveSupported ()) { + return EFI_UNSUPPORTED; + } + + return LpcEspiMemRangeGetHelper (SlaveEspiCS1, Address); +} + +/** + Set PCH BIOS range deocding. + This will check General Control and Status bit 10 (GCS.BBS) to identify = SPI or LPC/eSPI and program BDE register accordingly. + Please check EDS for detail of BiosDecodeEnable bit definition. + bit 15: F8-FF Enable + bit 14: F0-F8 Enable + bit 13: E8-EF Enable + bit 12: E0-E8 Enable + bit 11: D8-DF Enable + bit 10: D0-D7 Enable + bit 9: C8-CF Enable + bit 8: C0-C7 Enable + bit 7: Legacy F Segment Enable + bit 6: Legacy E Segment Enable + bit 5: Reserved + bit 4: Reserved + bit 3: 70-7F Enable + bit 2: 60-6F Enable + bit 1: 50-5F Enable + bit 0: 40-4F Enable + This cycle decoding is also required in DMI + Programming steps: + 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable. + if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnabl= e. + 2. program LPC BIOS Decode Enable in DMI + + @param[in] BiosDecodeEnable Bios decode enable setting. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchBiosDecodeEnableSet ( + IN UINT16 BiosDecodeEnable + ) +{ + UINT64 BaseAddr; + EFI_STATUS Status; + + Status =3D PchDmiSetBiosDecodeEnable (BiosDecodeEnable); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Check Boot BIOS Strap in DMI + // + if (PchDmiIsBootBiosStrapSetForSpi ()) { + BaseAddr =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + // + // Read SPI CFG cycle before write SPI CFG cycle + PciSegmentRead16 (BaseAddr + R_SPI_CFG_BDE); + // + // If SPI, Program SPI offset D8h to BiosDecodeEnable. + // + PciSegmentWrite16 (BaseAddr + R_SPI_CFG_BDE, BiosDecodeEnable); + } else { + BaseAddr =3D LpcPciBase (); + // + // If LPC/eSPi, program LPC offset D8h to BiosDecodeEnable. + // + PciSegmentWrite16 (BaseAddr + R_LPC_CFG_BDE, BiosDecodeEnable); + } + + return Status; +} + +/** + Set PCH LPC/eSPI IO decode ranges. + Program LPC/eSPI I/O Decode Ranges in DMI to the same value programmed i= n LPC/eSPI PCI offset 80h. + Please check EDS for detail of LPC/eSPI IO decode ranges bit definition. + Bit 12: FDD range + Bit 9:8: LPT range + Bit 6:4: ComB range + Bit 2:0: ComA range + + @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit sett= ings. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchLpcIoDecodeRangesSet ( + IN UINT16 LpcIoDecodeRanges + ) +{ + UINT64 LpcBaseAddr; + EFI_STATUS Status; + + // + // Note: Inside this function, don't use debug print since it's could us= ed before debug print ready. + // + + LpcBaseAddr =3D LpcPciBase (); + + // + // check if setting is identical + // + if (LpcIoDecodeRanges =3D=3D PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_I= OD)) { + return EFI_SUCCESS; + } + + Status =3D PchDmiSetLpcIoDecodeRanges (LpcIoDecodeRanges); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // program LPC/eSPI PCI offset 80h. + // + PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOD, LpcIoDecodeRanges); + + return Status; +} + +/** + Set PCH LPC/eSPI and eSPI CS1# IO enable decoding. + Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offse= t 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#). + Note: Bit[15:10] of the source decode register is Read-Only. The IO rang= e indicated by the Enables field + in LPC/eSPI PCI offset 82h[13:10] or A0h[13:10] is always forwarded by D= MI to subtractive agent for handling. + Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition. + + @param[in] IoEnableDecoding LPC/eSPI IO enable decoding bit se= ttings. + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX) + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMI configuration is locked +**/ +EFI_STATUS +LpcEspiIoEnableDecodingSetHelper ( + IN UINT16 IoEnableDecoding, + IN SLAVE_ID_INDEX SlaveId + ) +{ + UINT64 LpcBaseAddr; + EFI_STATUS Status; + UINT16 Cs1IoEnableDecodingOrg; + UINT16 Cs0IoEnableDecodingOrg; + UINT16 IoEnableDecodingMerged; + + LpcBaseAddr =3D LpcPciBase (); + + Cs0IoEnableDecodingOrg =3D PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOE= ); + + if (IsEspiSecondSlaveSupported ()) { + Cs1IoEnableDecodingOrg =3D PciSegmentRead16 (LpcBaseAddr + R_ESPI_CFG_= CS1IORE); + } else { + Cs1IoEnableDecodingOrg =3D 0; + } + + if (SlaveId =3D=3D SlaveEspiCS1) { + if (IoEnableDecoding =3D=3D Cs1IoEnableDecodingOrg) { + return EFI_SUCCESS; + } else { + IoEnableDecodingMerged =3D (Cs0IoEnableDecodingOrg | IoEnableDecodin= g); + } + } else { + if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) =3D=3D Cs0IoEnableDeco= dingOrg) { + return EFI_SUCCESS; + } else { + IoEnableDecodingMerged =3D (Cs1IoEnableDecodingOrg | IoEnableDecodin= g); + } + } + + Status =3D PchDmiSetLpcIoEnable (IoEnableDecodingMerged); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // program PCI offset 82h for LPC/eSPI. + // + PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOE, IoEnableDecodingMerged); + + if (SlaveId =3D=3D SlaveEspiCS1) { + // + // For eSPI CS1# device program eSPI PCI offset A0h. + // + PciSegmentWrite16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE, IoEnableDecoding)= ; + } + + return Status; +} + + +/** + Set PCH LPC and eSPI CS0# IO enable decoding. + Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offse= t 82h. + Note: Bit[15:10] of the source decode register is Read-Only. The IO rang= e indicated by the Enables field + in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtract= ive agent for handling. + Please check EDS for detail of LPC/eSPI IO decode ranges bit definition. + + @param[in] LpcIoEnableDecoding LPC IO enable decoding bit setting= s. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchLpcIoEnableDecodingSet ( + IN UINT16 LpcIoEnableDecoding + ) +{ + return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding, SlaveLpcEs= piCS0); +} + +/** + Set PCH eSPI CS1# IO enable decoding. + Setup I/O Enables in DMI to the same value program in eSPI PCI offset A0= h (eSPI CS1#). + Note: Bit[15:10] of the source decode register is Read-Only. The IO rang= e indicated by the Enables field + in eSPI PCI offset A0h[13:10] is always forwarded by DMI to subtractive = agent for handling. + Please check EDS for detail of eSPI IO decode ranges bit definition. + + @param[in] IoEnableDecoding eSPI IO enable decoding bit settin= gs. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMI configuration is locked +**/ +EFI_STATUS +PchEspiCs1IoEnableDecodingSet ( + IN UINT16 IoEnableDecoding + ) +{ + if (!IsEspiSecondSlaveSupported ()) { + return EFI_UNSUPPORTED; + } + + return LpcEspiIoEnableDecodingSetHelper (IoEnableDecoding, SlaveEspiCS1)= ; +} + +/** + Set PCH IO port 80h cycle decoding to PCIE root port. + System BIOS is likely to do this very soon after reset before PCI bus en= umeration. + This cycle decoding is allowed to set when DMI is unlocked + + @param[in] RpNumber PCIE root port physical number. + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PchIoPort80DecodeSet ( + IN UINTN RpNumber + ) +{ + EFI_STATUS Status; + + Status =3D PchDmiSetIoPort80Decode (RpNumber); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Get IO APIC registers base address. + + @param[out] IoApicBase Buffer of IO APIC register address + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PchIoApicBaseGet ( + OUT UINT32 *IoApicBase + ) +{ + *IoApicBase =3D PcdGet32 (PcdIoApicBaseAddress); + return EFI_SUCCESS; +} + +/** + Get HPET base address. + + @param[out] HpetBase Buffer of HPET base address + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid offset passed. +**/ +EFI_STATUS +PchHpetBaseGet ( + OUT UINT32 *HpetBase + ) +{ + if (HpetBase =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n")); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + *HpetBase =3D PcdGet32 (PcdSiHpetBaseAddress); + return EFI_SUCCESS; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEsp= iLib/PchEspiLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSm= mPchEspiLib/PchEspiLib.c new file mode 100644 index 0000000000..1bbecc71ed --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/Pc= hEspiLib.c @@ -0,0 +1,505 @@ +/** @file + This file contains routines for eSPI + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHANNEL_RESET_TIMEOUT 100 ///< Channel reset timeout in us a= fter which to report error +#define SLAVE_CHANNELS_MAX 7 ///< Max number of channels + +// +// eSPI Slave registers +// +#define R_ESPI_SLAVE_GENCAP 0x08 ///< General Capabilit= ies and Configurations +#define B_ESPI_SLAVE_GENCAP_SUPPCHAN 0xFF ///< Channels supporte= d bit mask +#define R_ESPI_SLAVE_CHACAP_BASE 0x10 ///< Base address from= which channel Cap and Conf registers start on slave +#define S_ESPI_SLAVE_CHACAP_OFFSET 0x10 ///< Offset for each c= hannel from base +#define B_ESPI_SLAVE_CHACAP_CHEN BIT0 ///< Slave Channel ena= ble bit +#define B_ESPI_SLAVE_CHACAP_CHRDY BIT1 ///< Slave Channel rea= dy bit + +/** + Checks if second slave capability is enabled + + @retval TRUE There's second slave + @retval FALSE There's no second slave +**/ +BOOLEAN +IsEspiSecondSlaveSupported ( + VOID + ) +{ + return (IsPchH () && ((PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SOFTSTRAPS)= & R_ESPI_PCR_SOFTSTRAPS_CS1_EN) !=3D 0)); +} + +/** + Checks in slave General Capabilities register if it supports channel wit= h requested number + + @param[in] SlaveId Id of slave to check + @param[in] ChannelNumber Number of channel of which to check + + @retval TRUE Channel with requested number is supported by slave de= vice + @retval FALSE Channel with requested number is not supported by slav= e device +**/ +BOOLEAN +IsEspiSlaveChannelSupported ( + UINT8 SlaveId, + UINT8 ChannelNumber + ) +{ + EFI_STATUS Status; + UINT32 Data32; + UINT8 SupportedChannels; + + Status =3D PchEspiSlaveGetConfig (SlaveId, R_ESPI_SLAVE_GENCAP, &Data32)= ; + if (EFI_ERROR (Status)) { + return FALSE; + } + SupportedChannels =3D (UINT8) (Data32 & B_ESPI_SLAVE_GENCAP_SUPPCHAN); + + DEBUG ((DEBUG_INFO, "Slave %d supported channels 0x%4X\n", SlaveId, Supp= ortedChannels)); + + if (ChannelNumber > SLAVE_CHANNELS_MAX || !(SupportedChannels & (BIT0 <<= ChannelNumber))) { + // Incorrect channel number was specified. Either exceeded max or Slav= e doesn't support that channel. + return FALSE; + } + + return TRUE; +} + +/** + Is eSPI enabled in strap. + + @retval TRUE Espi is enabled in strap + @retval FALSE Espi is disabled in strap +**/ +BOOLEAN +IsEspiEnabled ( + VOID + ) +{ + return (PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_CFG_VAL) & B_ESPI_PCR_CFG_= VAL_ESPI_EN) !=3D 0; +} + +/** + eSPI helper function to clear slave configuration register status + + @retval EFI_SUCCESS Write to private config space succeed + @retval others Read / Write failed +**/ +STATIC +VOID +EspiClearScrs ( + VOID + ) +{ + PchPcrAndThenOr32 ( + PID_ESPISPI, + R_ESPI_PCR_SLV_CFG_REG_CTL, + (UINT32) ~0, + B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS + ); +} + +/** + eSPI helper function to poll slave configuration register enable for 0 + and to check for slave configuration register status + + @retval EFI_SUCCESS Enable bit is zero and no error in status bits + @retval EFI_DEVICE_ERROR Error in SCRS + @retval others Read / Write to private config space failed +**/ +STATIC +EFI_STATUS +EspiPollScreAndCheckScrs ( + VOID + ) +{ + UINT32 ScrStat; + + do { + ScrStat =3D PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SLV_CFG_REG_CTL); + } while ((ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE) !=3D 0); + + ScrStat =3D (ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS) >> N_ESPI_PCR_SL= V_CFG_REG_CTL_SCRS; + if (ScrStat !=3D V_ESPI_PCR_SLV_CFG_REG_CTL_SCRS_NOERR) { + DEBUG ((DEBUG_ERROR, "eSPI slave config register status (error) is %x = \n", ScrStat)); + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +typedef enum { + EspiSlaveOperationConfigRead, + EspiSlaveOperationConfigWrite, + EspiSlaveOperationStatusRead, + EspiSlaveOperationInBandReset +} ESPI_SLAVE_OPERATION; + +/** + Helper library to do all the operations regards to eSPI slave + + @param[in] SlaveId eSPI Slave ID + @param[in] SlaveAddress Slave address to be put in R_ESPI_PCR_SL= V_CFG_REG_CTL[11:0] + @param[in] SlaveOperation Based on ESPI_SLAVE_OPERATION + @param[in,out] Data + + @retval EFI_SUCCESS Operation succeed + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is = used in PCH_LP + @retval EFI_INVALID_PARAMETER Slave configuration register address excee= d maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is no= t DWord aligned + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7= FF has been locked + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of oper= ation +**/ +STATIC +EFI_STATUS +EspiSlaveOperationHelper ( + IN UINT32 SlaveId, + IN UINT32 SlaveAddress, + IN ESPI_SLAVE_OPERATION SlaveOperation, + IN OUT UINT32 *Data + ) +{ + EFI_STATUS Status; + UINT32 Data32; + + // + // Check the SlaveId is 0 or 1 + // + if (SlaveId >=3D PCH_MAX_ESPI_SLAVES) { + DEBUG ((DEBUG_ERROR, "eSPI Slave ID of %d or more is not accepted \n",= PCH_MAX_ESPI_SLAVES)); + return EFI_INVALID_PARAMETER; + } + // + // Check if SlaveId 1 is used, it is a PCH_H + // + if ((SlaveId =3D=3D 1) && (IsPchLp ())) { + DEBUG ((DEBUG_ERROR, "eSPI Slave ID of 1 is only available on PCH_H \n= ")); + return EFI_INVALID_PARAMETER; + } + // + // Check the address is not more then 0xFFF + // + if (SlaveAddress > B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA) { + DEBUG ((DEBUG_ERROR, "eSPI Slave address must be less than 0x%x \n", (= B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA + 1))); + return EFI_INVALID_PARAMETER; + } + // + // Check the address is DWord aligned + // + if ((SlaveAddress & 0x3) !=3D 0) { + DEBUG ((DEBUG_ERROR, "eSPI Slave address must be DWord aligned \n")); + return EFI_INVALID_PARAMETER; + } + + // + // Check if write is allowed + // + if ((SlaveOperation =3D=3D EspiSlaveOperationConfigWrite) && + (SlaveAddress <=3D 0x7FF)) { + + // + // If the SLCRR is not set in corresponding slave, we will check the l= ock bit + // + Data32 =3D PchPcrRead32 (PID_ESPISPI, (UINT16) (R_ESPI_PCR_LNKERR_SLV0= + (SlaveId * S_ESPI_PCR_LNKERR_SLV0))); + if ((Data32 & B_ESPI_PCR_LNKERR_SLV0_SLCRR) =3D=3D 0) { + + Data32 =3D PchPcrRead32 (PID_ESPISPI, (UINT16) R_ESPI_PCR_SLV_CFG_RE= G_CTL); + if ((Data32 & B_ESPI_PCR_SLV_CFG_REG_CTL_SBLCL) !=3D 0) { + DEBUG ((DEBUG_ERROR, "eSPI Slave write to address range 0 to 0x7FF= has been locked \n")); + return EFI_ACCESS_DENIED; + } + } + } + + // + // Input check done, now go through all the processes + // + EspiClearScrs (); + + if (SlaveOperation =3D=3D EspiSlaveOperationConfigWrite) { + PchPcrWrite32 ( + PID_ESPISPI, + (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA, + *Data + ); + } + + PchPcrAndThenOr32 ( + PID_ESPISPI, + (UINT16) R_ESPI_PCR_SLV_CFG_REG_CTL, + (UINT32) ~(B_ESPI_PCR_SLV_CFG_REG_CTL_SID | B_ESPI_PCR_SLV_CFG_REG_CTL= _SCRT | B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA), + (B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE | + (SlaveId << N_ESPI_PCR_SLV_CFG_REG_CTL_SID) | + (((UINT32) SlaveOperation) << N_ESPI_PCR_SLV_CFG_REG_CTL_SCRT) | + SlaveAddress + ) + ); + + Status =3D EspiPollScreAndCheckScrs (); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((SlaveOperation =3D=3D EspiSlaveOperationConfigRead) || (SlaveOperat= ion =3D=3D EspiSlaveOperationStatusRead)) { + Data32 =3D PchPcrRead32 ( + PID_ESPISPI, + (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA + ); + if (SlaveOperation =3D=3D EspiSlaveOperationStatusRead) { + *Data =3D Data32 & 0xFFFF; + } else { + *Data =3D Data32; + } + } + + return EFI_SUCCESS; +} + +/** + Get configuration from eSPI slave + + @param[in] SlaveId eSPI slave ID + @param[in] SlaveAddress Slave Configuration Register Address + @param[out] OutData Configuration data read + + @retval EFI_SUCCESS Operation succeed + @retval EFI_INVALID_PARAMETER Slave ID is not supported + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is = used in PCH_LP + @retval EFI_INVALID_PARAMETER Slave configuration register address excee= d maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is no= t DWord aligned + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of oper= ation +**/ +EFI_STATUS +PchEspiSlaveGetConfig ( + IN UINT32 SlaveId, + IN UINT32 SlaveAddress, + OUT UINT32 *OutData + ) +{ + // + // 1. Clear status from previous transaction by writing 111b to status i= n SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=3D01, Bit [2= 0:19]=3D, Bit [17:16] =3D 00b, Bit[11:0] =3D . + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0 + // 4. Check the transaction status in SCRS (bits [30:28]) + // 5. Read SLV_CFG_REG_DATA. + // + return EspiSlaveOperationHelper (SlaveId, SlaveAddress, EspiSlaveOperati= onConfigRead, OutData); +} + +/** + Set eSPI slave configuration + + Note: A Set_Configuration must always be followed by a Get_Configuration= in order to ensure + that the internal state of the eSPI-MC is consistent with the Slave's re= gister settings. + + @param[in] SlaveId eSPI slave ID + @param[in] SlaveAddress Slave Configuration Register Address + @param[in] InData Configuration data to write + + @retval EFI_SUCCESS Operation succeed + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is = used in PCH_LP + @retval EFI_INVALID_PARAMETER Slave configuration register address excee= d maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is no= t DWord aligned + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7= FF has been locked + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of oper= ation +**/ +EFI_STATUS +PchEspiSlaveSetConfig ( + IN UINT32 SlaveId, + IN UINT32 SlaveAddress, + IN UINT32 InData + ) +{ + EFI_STATUS Status; + UINT32 Data32; + + // + // 1. Clear status from previous transaction by writing 111b to status i= n SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_DATA with the write value. + // 3. Program SLV_CFG_REG_CTL with the right value (Bit[31]=3D01, Bit [2= 0:19]=3D, Bit [17:16] =3D 01b, Bit[11:0] =3D . + // 4. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0 + // 5. Check the transaction status in SCRS (bits [30:28]) + // + Status =3D EspiSlaveOperationHelper (SlaveId, SlaveAddress, EspiSlaveOpe= rationConfigWrite, &InData); + if (EFI_ERROR (Status)) { + return Status; + } + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveAddress, &Data32); + return Status; +} + +/** + Get status from eSPI slave + + @param[in] SlaveId eSPI slave ID + @param[out] OutData Configuration data read + + @retval EFI_SUCCESS Operation succeed + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is = used in PCH_LP + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of oper= ation +**/ +EFI_STATUS +PchEspiSlaveGetStatus ( + IN UINT32 SlaveId, + OUT UINT16 *OutData + ) +{ + EFI_STATUS Status; + UINT32 TempOutData; + + TempOutData =3D 0; + + // + // 1. Clear status from previous transaction by writing 111b to status i= n SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=3D01, Bit [2= 0:19]=3D, Bit [17:16] =3D 10b, Bit[11:0] =3D . + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0 + // 4. Check the transaction status in SCRS (bits [30:28]) + // 5. Read SLV_CFG_REG_DATA [15:0]. + // + Status =3D EspiSlaveOperationHelper (SlaveId, 0, EspiSlaveOperationStatu= sRead, &TempOutData); + *OutData =3D (UINT16) TempOutData; + + return Status; +} + +/** + eSPI slave in-band reset + + @param[in] SlaveId eSPI slave ID + + @retval EFI_SUCCESS Operation succeed + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is = used in PCH_LP + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of oper= ation +**/ +EFI_STATUS +PchEspiSlaveInBandReset ( + IN UINT32 SlaveId + ) +{ + // + // 1. Clear status from previous transaction by writing 111b to status i= n SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=3D01, Bit [2= 0:19]=3D, Bit [17:16] =3D 11b). + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0 + // 4. Check the transaction status in SCRS (bits [30:28]) + // + return EspiSlaveOperationHelper (SlaveId, 0, EspiSlaveOperationInBandRes= et, NULL); +} + +/** + eSPI Slave channel reset helper function + + @param[in] SlaveId eSPI slave ID + @param[in] ChannelNumber Number of channel to reset + + @retval EFI_SUCCESS Operation succeeded + @retval EFI_UNSUPPORTED Slave doesn't support that channel or inva= lid number specified + @retval EFI_TIMEOUT Operation has timeouted +**/ +EFI_STATUS +PchEspiSlaveChannelReset ( + IN UINT8 SlaveId, + IN UINT8 ChannelNumber + ) +{ + UINT8 Timeout; + UINT32 Data32; + UINT32 SlaveChannelAddress; + BOOLEAN SlaveBmeSet; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "eSPI slave %d channel %d reset\n", SlaveId, Channel= Number)); + + Timeout =3D CHANNEL_RESET_TIMEOUT; + SlaveBmeSet =3D FALSE; + + if (!IsEspiSlaveChannelSupported (SlaveId, ChannelNumber)) { + // Incorrect channel number was specified. Either exceeded max or Slav= e doesn't support that channel. + DEBUG ((DEBUG_ERROR, "Channel %d is not valid channel number for slave= %d!\n", ChannelNumber, SlaveId)); + return EFI_UNSUPPORTED; + } + + // Calculating slave channel address + SlaveChannelAddress =3D R_ESPI_SLAVE_CHACAP_BASE + (S_ESPI_SLAVE_CHACAP_= OFFSET * ChannelNumber); + + // If we're resetting Peripheral Channel then we need to disable Bus Mas= tering first and reenable after reset + if (ChannelNumber =3D=3D 0) { + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data3= 2); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Data32 & B_ESPI_SLAVE_BME) !=3D 0) { + Data32 &=3D ~(B_ESPI_SLAVE_BME); + Status =3D PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data= 32); + if (EFI_ERROR (Status)) { + return Status; + } + SlaveBmeSet =3D TRUE; + } + } + + // Disable channel + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32)= ; + if (EFI_ERROR (Status)) { + return Status; + } + Data32 &=3D ~(B_ESPI_SLAVE_CHACAP_CHEN); + Status =3D PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32); + if (EFI_ERROR (Status)) { + return Status; + } + // Enable channel + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32)= ; + if (EFI_ERROR (Status)) { + return Status; + } + Data32 |=3D B_ESPI_SLAVE_CHACAP_CHEN; + Status =3D PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32); + if (EFI_ERROR (Status)) { + return Status; + } + DEBUG ((DEBUG_INFO, "Waiting for Channel Ready bit\n")); + // Wait until channel is ready by polling Channel Ready bit + while (((Data32 & B_ESPI_SLAVE_CHACAP_CHRDY) =3D=3D 0) && (Timeout > 0))= { + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data3= 2); + if (EFI_ERROR (Status)) { + return Status; + } + MicroSecondDelay (1); + --Timeout; + } + + if (Timeout =3D=3D 0) { + // The waiting for channel to be ready has timed out + DEBUG ((DEBUG_ERROR, "The operation of channel %d reset for slave %d h= as timed out!\n", ChannelNumber, SlaveId)); + return EFI_TIMEOUT; + } + + if (ChannelNumber =3D=3D 0 && SlaveBmeSet) { + Status =3D PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data3= 2); + if (EFI_ERROR (Status)) { + return Status; + } + Data32 |=3D B_ESPI_SLAVE_BME; + Status =3D PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32= ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbe= Lib/PchGbeLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmP= chGbeLib/PchGbeLib.c new file mode 100644 index 0000000000..652a47ebaf --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/Pch= GbeLib.c @@ -0,0 +1,82 @@ +/** @file + PCH Gbe Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Check whether GbE region is valid + Check SPI region directly since GbE might be disabled in SW. + + @retval TRUE Gbe Region is valid + @retval FALSE Gbe Region is invalid +**/ +BOOLEAN +PchIsGbeRegionValid ( + VOID + ) +{ + UINT32 SpiBar; + SpiBar =3D PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + R_SPI_CFG_BAR0)) & ~B_SPI_CFG_BAR0_MASK; + ASSERT (SpiBar !=3D 0); + if (MmioRead32 (SpiBar + R_SPI_MEM_FREG3_GBE) !=3D B_SPI_MEM_FREGX_BASE_= MASK) { + return TRUE; + } + return FALSE; +} + + +/** + Check whether LAN controller is enabled in the platform. + + @retval TRUE GbE is enabled + @retval FALSE GbE is disabled +**/ +BOOLEAN +PchIsGbePresent ( + VOID + ) +{ + // + // Check PCH Support + // + if (!PchIsGbeSupported ()) { + return FALSE; + } + // + // Check PMC strap/fuse + // + if (!PmcIsGbeSupported ()) { + return FALSE; + } + // + // Check GbE NVM + // + if (PchIsGbeRegionValid () =3D=3D FALSE) { + return FALSE; + } + return TRUE; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsi= oLib/PchHsioLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSm= mPchHsioLib/PchHsioLib.c new file mode 100644 index 0000000000..2be8e8ed49 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/Pc= hHsioLib.c @@ -0,0 +1,127 @@ +/** @file + PCH HSIO Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + The function returns the Port Id and lane owner for the specified lane + + @param[in] PhyMode Phymode that needs to be checked + @param[out] PortId Common Lane End Point ID + @param[out] LaneOwner Lane Owner + + @retval EFI_SUCCESS Read success + @retval EFI_INVALID_PARAMETER Invalid lane number +**/ +EFI_STATUS +EFIAPI +PchGetLaneInfo ( + IN UINT32 LaneNum, + OUT UINT8 *PortId, + OUT UINT8 *LaneOwner + ) +{ + return EFI_SUCCESS; +} + +/** + Determine the lane number of a specified port + + @param[out] LaneNum GBE Lane Number + + @retval EFI_SUCCESS Lane number valid. + @retval EFI_UNSUPPORTED Incorrect input device port +**/ +EFI_STATUS +PchGetGbeLaneNum ( + UINT8 *LaneNum + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Determine the lane number of a specified port + + @param[in] Usb3LaneIndex USB3 Lane Index + @param[out] LaneNum Lane Number + + @retval EFI_SUCCESS Lane number valid. + @retval EFI_UNSUPPORTED Incorrect input device port +**/ +EFI_STATUS +PchGetUsb3LaneNum ( + UINT32 Usb3LaneIndex, + UINT8 *LaneNum + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Determine the lane number of a specified port + + @param[in] SataLaneIndex Sata Lane Index + @param[out] LaneNum Lane Number + + @retval EFI_SUCCESS Lane number valid. + @retval EFI_UNSUPPORTED Incorrect input device port +**/ +EFI_STATUS +PchGetSataLaneNum ( + UINT32 SataLaneIndex, + UINT8 *LaneNum + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Determine the lane number of a specified port + + @param[in] PcieLaneIndex PCIE Root Port Lane Index + @param[out] LaneNum Lane Number + + @retval EFI_SUCCESS Lane number valid. + @retval EFI_UNSUPPORTED Incorrect input device port +**/ +EFI_STATUS +PchGetPcieLaneNum ( + UINT32 PcieLaneIndex, + UINT8 *LaneNum + ) +{ + + return EFI_UNSUPPORTED; +} + +/** + Get HSIO lane representation needed to perform any operation on the lane= . + + @param[in] LaneIndex Number of the HSIO lane + @param[out] HsioLane HSIO lane representation +**/ +VOID +HsioGetLane ( + IN UINT8 LaneIndex, + OUT HSIO_LANE *HsioLane + ) +{ + +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInf= oLib/PchInfoLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSm= mPchInfoLib/PchInfoLib.c new file mode 100644 index 0000000000..7c3ade49b6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/Pc= hInfoLib.c @@ -0,0 +1,272 @@ +/** @file + Pch information library. + + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PchInfoLibPrivate.h" +#include +#include +#include +#include + +/** + Return LPC Device Id + + @retval PCH_LPC_DEVICE_ID PCH Lpc Device ID +**/ +UINT16 +PchGetLpcDid ( + VOID + ) +{ + UINT64 LpcBaseAddress; + + LpcBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + return PciSegmentRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET); +} + +/** + Return Pch Series + + @retval PCH_SERIES Pch Series +**/ +PCH_SERIES +PchSeries ( + VOID + ) +{ + PCH_SERIES PchSer; + static PCH_SERIES PchSeries =3D PCH_UNKNOWN_SERIES; + + if (PchSeries !=3D PCH_UNKNOWN_SERIES) { + return PchSeries; + } + + PchSer =3D PchSeriesFromLpcDid (PchGetLpcDid ()); + + PchSeries =3D PchSer; + + return PchSer; +} + +/** + Return Pch stepping type + + @retval PCH_STEPPING Pch stepping type +**/ +PCH_STEPPING +PchStepping ( + VOID + ) +{ + UINT8 RevId; + UINT64 LpcBaseAddress; + static PCH_STEPPING PchStepping =3D PCH_STEPPING_MAX; + + if (PchStepping !=3D PCH_STEPPING_MAX) { + return PchStepping; + } + + LpcBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + RevId =3D PciSegmentRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET); + + PchStepping =3D RevId; + + return RevId; +} + +/** + Determine if PCH is supported + + @retval TRUE PCH is supported + @retval FALSE PCH is not supported +**/ +BOOLEAN +IsPchSupported ( + VOID + ) +{ + UINT16 LpcDeviceId; + UINT16 LpcVendorId; + UINT64 LpcBaseAddress; + + LpcBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + LpcDeviceId =3D PciSegmentRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET)= ; + LpcVendorId =3D PciSegmentRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET)= ; + + /// + /// Verify that this is a supported chipset + /// + if ((LpcVendorId =3D=3D V_LPC_CFG_VENDOR_ID) && (PchSeries () !=3D PCH_U= NKNOWN_SERIES)) { + return TRUE; + } else { + DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x= !\n", LpcDeviceId)); + return FALSE; + } +} + +/** + Check if this is PCH LP series + + @retval TRUE It's PCH LP series + @retval FALSE It's not PCH LP series +**/ +BOOLEAN +IsPchLp ( + VOID + ) +{ + return (PchSeries () =3D=3D PCH_LP); +} + +/** + Check if this is PCH H series + + @retval TRUE It's PCH H series + @retval FALSE It's not PCH H series +**/ +BOOLEAN +IsPchH ( + VOID + ) +{ + return (PchSeries () =3D=3D PCH_H); +} + +/** + Check if this is CDF PCH generation + + @retval TRUE It's CDF PCH + @retval FALSE It's not CDF PCH +**/ +BOOLEAN +IsCdfPch ( + VOID + ) +{ + return (PchGeneration () =3D=3D CDF_PCH); +} + +/** + Check if this is PCH generation + + @retval TRUE It's CNL PCH + @retval FALSE It's not CNL PCH +**/ +BOOLEAN +IsCnlPch ( + VOID + ) +{ + return (PchGeneration () =3D=3D CNL_PCH); +} + +/** + Get PCH stepping ASCII string. + Function determines major and minor stepping versions and writes them in= to a buffer. + The return string is zero terminated + + @param [out] Buffer Output buffer of string + @param [in] BufferSize Buffer size. + Must not be less then PCH_STEPPING= _STR_LENGTH_MAX + + @retval EFI_SUCCESS String copied successfully + @retval EFI_INVALID_PARAMETER The stepping is not supported, or = parameters are NULL + @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small +**/ +EFI_STATUS +PchGetSteppingStr ( + OUT CHAR8 *Buffer, + IN UINT32 BufferSize + ) +{ + PCH_STEPPING PchStep; + + PchStep =3D PchStepping (); + + if ((Buffer =3D=3D NULL) || (BufferSize =3D=3D 0)) { + return EFI_INVALID_PARAMETER; + } + if (BufferSize < PCH_STEPPING_STR_LENGTH_MAX) { + return EFI_BUFFER_TOO_SMALL; + } + + AsciiSPrint (Buffer, BufferSize, "%c%c", 'A' + (PchStep >> 4), '0' + (Pc= hStep & 0xF)); + + return EFI_SUCCESS; +} + +/** + Get PCH Sku ASCII string + The return string is zero terminated. + + @retval Static ASCII string of PCH Sku +**/ +CHAR8* +PchGetSkuStr ( + VOID + ) +{ + UINTN Index; + UINT16 LpcDid; + + LpcDid =3D PchGetLpcDid (); + + for (Index =3D 0; mSkuStrs[Index].Id !=3D 0xFFFF; Index++) { + if (LpcDid =3D=3D mSkuStrs[Index].Id) { + return mSkuStrs[Index].String; + } + } + + return "Undefined SKU"; +} + +/** + Get Pch Maximum Pcie Controller Number + + @retval Pch Maximum Pcie Root Port Number +**/ +UINT8 +GetPchMaxPcieControllerNum ( + VOID + ) +{ + return GetPchMaxPciePortNum () / PCH_PCIE_CONTROLLER_PORTS; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInf= oLib/PchInfoLibClient.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pe= iDxeSmmPchInfoLib/PchInfoLibClient.c new file mode 100644 index 0000000000..7b09a2dbb9 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/Pc= hInfoLibClient.c @@ -0,0 +1,87 @@ +/** @file + Common Pch information library for Client PCH silicon. + + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +/** + Get Pch Maximum Pcie Clock Number + + @retval Pch Maximum Pcie Clock Number +**/ +UINT8 +GetPchMaxPcieClockNum ( + VOID + ) +{ + if (IsPchH ()) { + return 16; + } else { + return 6; + } +} + +/** + Get Pch Maximum Serial IO controllers number + + @retval Pch Maximum Serial IO controllers number +**/ +UINT8 +GetPchMaxSerialIoControllersNum ( + VOID + ) +{ + return 12; +} + +/** + Get Pch Maximum Serial IO I2C controllers number + + @retval Pch Maximum Serial IO I2C controllers number +**/ +UINT8 +GetPchMaxSerialIoI2cControllersNum ( + VOID + ) +{ + if (IsPchH ()) { + return 4; + } else { + return 6; + } +} + +/** + Get Pch Maximum Serial IO SPI controllers number + + @retval Pch Maximum Serial IO SPI controllers number +**/ +UINT8 +GetPchMaxSerialIoSpiControllersNum ( + VOID + ) +{ + return 3; +} + +/** + Get Pch Maximum Serial IO UART controllers number + + @retval Pch Maximum Serial IO UART controllers number +**/ +UINT8 +GetPchMaxSerialIoUartControllersNum ( + VOID + ) +{ + return 3; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInf= oLib/PchInfoLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDx= eSmmPchInfoLib/PchInfoLibCnl.c new file mode 100644 index 0000000000..431b1470c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/Pc= hInfoLibCnl.c @@ -0,0 +1,386 @@ +/** @file + Pch information library. + + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include "PchInfoLibPrivate.h" +#include +#include + +/** + Determine Pch Series based on Device Id + + @param[in] LpcDeviceId Lpc Device Id + + @retval PCH_SERIES Pch Series +**/ +PCH_SERIES +PchSeriesFromLpcDid ( + IN UINT16 LpcDeviceId + ) +{ + switch (LpcDeviceId & B_LPC_CFG_DID) { + + case V_LPC_CFG_DID_CNL_H: + return PCH_H; + + case V_LPC_CFG_DID_CNL_LP: + return PCH_LP; + + default: + return PCH_UNKNOWN_SERIES; + } +} + +/** + Return Pch Generation + + @retval PCH_GENERATION Pch Generation +**/ +PCH_GENERATION +PchGeneration ( + VOID + ) +{ + return CNL_PCH; +} + +/** + Check if this is Server PCH + + @retval TRUE It's a Server PCH + @retval FALSE It's not a Server PCH +**/ +BOOLEAN +IsPchServer ( + VOID + ) +{ + return FALSE; +} + +/** + Get RST mode supported by the silicon + + @retval RST_MODE RST mode supported by silicon +**/ +RST_MODE +PchGetSupportedRstMode ( + VOID + ) +{ + switch (PchGetLpcDid ()) { + + case V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_4: + case V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A303_SKU: + return RstUnsupported; + break; + + default: + return RstPremium; + break; + } +} + +/** + Check if this is Server SKU + + @retval TRUE It's PCH Server SKU + @retval FALSE It's not PCH Server SKU +**/ +BOOLEAN +IsPchServerSku ( + VOID + ) +{ + UINT16 LpcDid; + + LpcDid =3D PchGetLpcDid (); + + if (LpcDid =3D=3D V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A309_SKU) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Get PCH series ASCII string. + + @retval PCH Series string +**/ +CHAR8* +PchGetSeriesStr ( + VOID + ) +{ + switch (PchSeries ()) { + + case PCH_LP: + return "CNL PCH-LP"; + + case PCH_H: + return "CNL PCH-H"; + + default: + return NULL; + } +} + +GLOBAL_REMOVE_IF_UNREFERENCED +struct PCH_SKU_STRING mSkuStrs[] =3D { + // + // PCH LP Mobile LPC Device IDs + // + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_SUPER_SKU, "Super SKU"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_0, "(U) Super SKU"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_1, "Super SKU (locked)"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_2, "(Y) Premium SKU"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_3, "(U) Premium SKU"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_4, "(U) Base/Mainstream SKU"}, + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_5, "(Y) Super SKU"}, + // + // PCH H LPC Device IDs + // + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A300_SKU, "CNL PCH-H SKU A300"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A303_SKU, "H310"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A304_SKU, "H370"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A305_SKU, "Z390"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A306_SKU, "Q370"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A309_SKU, "C246"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30A_SKU, "C242"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30B_SKU, "X399"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30C_SKU, "QM370"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30D_SKU, "HM370"}, + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30E_SKU, "CM246"}, + {0xFFFF, NULL} +}; + +/** + Check whether integrated LAN controller is supported by PCH Series. + + @retval TRUE GbE is supported in current PCH + @retval FALSE GbE is not supported on current PCH +**/ +BOOLEAN +PchIsGbeSupported ( + VOID + ) +{ + return TRUE; +} + +/** + Get Pch Maximum Pcie Root Port Number + + @retval Pch Maximum Pcie Root Port Number +**/ +UINT8 +GetPchMaxPciePortNum ( + VOID + ) +{ + if (IsPchLp ()) { + return 16; + } else { + return 24; + } +} + +/** + Get Pch Usb2 Maximum Physical Port Number + + @retval Pch Usb2 Maximum Physical Port Number +**/ +UINT8 +GetPchUsb2MaxPhysicalPortNum ( + VOID + ) +{ + if (IsPchLp ()) { + return 10; + } else { + return 14; + } +} + +/** + Get Pch Maximum Usb2 Port Number of XHCI Controller + + @retval Pch Maximum Usb2 Port Number of XHCI Controller +**/ +UINT8 +GetPchXhciMaxUsb2PortNum ( + VOID + ) +{ + if (IsPchLp ()) { + return 12; + } else { + return 16; + } +} + +/** + Get Pch Maximum Usb3 Port Number of XHCI Controller + + @retval Pch Maximum Usb3 Port Number of XHCI Controller +**/ +UINT8 +GetPchXhciMaxUsb3PortNum ( + VOID + ) +{ + if (IsPchLp ()) { + return 6; + } else { + return 10; + } +} + +/** + Check if given Display Audio Link T-Mode is supported + + @param[in] Tmode T-mode support to be checked + + @retval TRUE T-mode supported + @retval FALSE T-mode not supported +**/ +BOOLEAN +IsAudioIDispTmodeSupported ( + IN PCH_HDAUDIO_IDISP_TMODE Tmode + ) +{ + // + // iDisplay Audio Link T-mode support per PCH Generation/Series: + // 1. 1T - CNP-LP + // 2. 2T - CNP-LP/H (default) + // + switch (Tmode) { + case PchHdaIDispMode1T: + return IsPchLp (); + case PchHdaIDispMode2T: + return TRUE; + case PchHdaIDispMode4T: + case PchHdaIDispMode8T: + case PchHdaIDispMode16T: + default: + return FALSE; + } +} + +/** + Gets the maximum number of UFS controller supported by this chipset. + + @return Number of supported UFS controllers +**/ +UINT8 +PchGetMaxUfsNum ( + VOID + ) +{ + if (IsPchLp ()) { + return 1; + } else { + return 0; + } +} + +/** + Check if this chipset supports eMMC controller + + @retval BOOLEAN TRUE if supported, FALSE otherwise +**/ +BOOLEAN +IsPchEmmcSupported ( + VOID + ) +{ + if (IsPchLp ()) { + return TRUE; + } + + return FALSE; +} + +/** + Check if this chipset supports SD controller + + @retval BOOLEAN TRUE if supported, FALSE otherwise +**/ +BOOLEAN +IsPchSdCardSupported ( + VOID + ) +{ + return TRUE; +} + +/** + Check if this chipset supports UFS controller + + @retval BOOLEAN TRUE if supported, FALSE otherwise +**/ +BOOLEAN +IsPchUfsSupported ( + VOID + ) +{ + if (IsPchLp ()) { + return TRUE; + } + + return FALSE; +} + +/** + Check if link between PCH and CPU is an P-DMI + + @retval TRUE P-DMI link + @retval FALSE Not an P-DMI link +**/ +BOOLEAN +IsPchWithPdmi ( + VOID + ) +{ + return IsPchH (); +} + +/** + Check if link between PCH and CPU is an OP-DMI + + @retval TRUE OP-DMI link + @retval FALSE Not an OP-DMI link +**/ +BOOLEAN +IsPchWithOpdmi ( + VOID + ) +{ + return !IsPchH (); +} + +/** + Check if link between PCH and CPU is an F-DMI + + @retval TRUE F-DMI link + @retval FALSE Not an F-DMI link +**/ +BOOLEAN +IsPchWithFdmi ( + VOID + ) +{ + return FALSE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPci= eRpLib/PchPcieRpLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiD= xeSmmPchPcieRpLib/PchPcieRpLib.c new file mode 100644 index 0000000000..9997c3612b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/= PchPcieRpLib.c @@ -0,0 +1,183 @@ +/** @file + PCH PCIE root port library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_PCIE_CONTROLLER_INFO mPchPcieContr= ollerInfo[] =3D { + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPA, 0 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPB, 4 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPC, 8 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPD, 12 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPE, 16 }, // PCH-H only + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPF, 20 } // PCH-H only +}; +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mPchPcieControllerInfoSize =3D = sizeof (mPchPcieControllerInfo) / sizeof (mPchPcieControllerInfo[0]); + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchLpRstPcieStorageSupportedPort[] = =3D { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORA= GE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORA= GE_CR_1, RST_PCIE_STORAGE_CR_1, // RP5..RP8 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORA= GE_CR_2, RST_PCIE_STORAGE_CR_2, // RP9..RP12 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORA= GE_CR_3, RST_PCIE_STORAGE_CR_3 // RP13..RP16 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchHRstPcieStorageSupportedPort[] =3D= { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORA= GE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORA= GE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORA= GE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORA= GE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP13..RP16 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORA= GE_CR_3, RST_PCIE_STORAGE_CR_3, // RP17..RP20 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORA= GE_CR_2, RST_PCIE_STORAGE_CR_2 // RP21..RP24 +}; + +/** + Get Pch Pcie Root Port Device and Function Number by Root Port physical = Number + + @param[in] RpNumber Root port physical number. (0-based) + @param[out] RpDev Return corresponding root port device = number. + @param[out] RpFun Return corresponding root port functio= n number. + + @retval EFI_SUCCESS Root port device and function is retri= eved + @retval EFI_INVALID_PARAMETER RpNumber is invalid +**/ +EFI_STATUS +EFIAPI +GetPchPcieRpDevFun ( + IN UINTN RpNumber, + OUT UINTN *RpDev, + OUT UINTN *RpFun + ) +{ + UINTN Index; + UINTN FuncIndex; + UINT32 PciePcd; + + if (RpNumber >=3D GetPchMaxPciePortNum ()) { + DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumbe= r)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Index =3D RpNumber / PCH_PCIE_CONTROLLER_PORTS; + FuncIndex =3D RpNumber - mPchPcieControllerInfo[Index].RpNumBase; + *RpDev =3D mPchPcieControllerInfo[Index].DevNum; + PciePcd =3D PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_SPX_PCR_P= CD); + *RpFun =3D (PciePcd >> (FuncIndex * S_SPX_PCR_PCD_RP_FIELD)) & B_SPX_PCR= _PCD_RP1FN; + + return EFI_SUCCESS; +} + +/** + Get Root Port physical Number by Pch Pcie Root Port Device and Function = Number + + @param[in] RpDev Root port device number. + @param[in] RpFun Root port function number. + @param[out] RpNumber Return corresponding physical Root Por= t index (0-based) + + @retval EFI_SUCCESS Physical root port is retrieved +**/ +EFI_STATUS +EFIAPI +GetPchPcieRpNumber ( + IN UINTN RpDev, + IN UINTN RpFun, + OUT UINTN *RpNumber + ) +{ + UINT64 RpBase; + + RpBase =3D PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFA= ULT_PCI_BUS_NUMBER_PCH, RpDev, RpFun, 0); + *RpNumber =3D (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) >> N_PCH_= PCIE_CFG_LCAP_PN) -1; + return EFI_SUCCESS; +} + +/** + Gets pci segment base address of PCIe root port. + + @param RpIndex Root Port Index (0 based) + @return PCIe port base address. +**/ +UINT64 +PchPcieBase ( + IN UINT32 RpIndex + ) +{ + UINTN RpDevice; + UINTN RpFunction; + + GetPchPcieRpDevFun (RpIndex, &RpDevice, &RpFunction); + + return PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_= PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction, 0); +} + +/** + Determines whether L0s is supported on current stepping. + + @return TRUE if L0s is supported, FALSE otherwise +**/ +BOOLEAN +PchIsPcieL0sSupported ( + VOID + ) +{ + return TRUE; +} + +/** + Some early PCH steppings require Native ASPM to be disabled due to hardw= are issues: + - RxL0s exit causes recovery + - Disabling PCIe L0s capability disables L1 + Use this function to determine affected steppings. + + @return TRUE if Native ASPM is supported, FALSE otherwise +**/ +BOOLEAN +PchIsPcieNativeAspmSupported ( + VOID + ) +{ + return PchIsPcieL0sSupported (); +} + +/** + Check the RST PCIe Storage Cycle Router number according to the root por= t number and PCH type + + @param[in] RootPortNum Root Port Number + + @return The RST PCIe Storage Cycle Router Number +**/ +UINT8 +RstGetCycleRouterNumber ( + IN UINT32 RootPortNum + ) +{ + if (IsPchLp ()) { + if (RootPortNum < ARRAY_SIZE (mPchLpRstPcieStorageSupportedPort)) { + return mPchLpRstPcieStorageSupportedPort[RootPortNum]; + } + } else if (IsPchH ()) { + if (RootPortNum < ARRAY_SIZE (mPchHRstPcieStorageSupportedPort)) { + return mPchHRstPcieStorageSupportedPort[RootPortNum]; + } + } + return RST_PCIE_STORAGE_CR_INVALID; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcr= Lib/PchPcrLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmP= chPcrLib/PchPcrLib.c new file mode 100644 index 0000000000..6f70733fe7 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/Pch= PcrLib.c @@ -0,0 +1,279 @@ +/** @file + PCH PCR library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef MDEPKG_NDEBUG +/** + Checks if the offset is valid for a given memory access width + + @param[in] Offset Offset of a register + @param[in] Size Size of memory access in bytes + + @retval FALSE Offset is not valid for a given memory access + @retval TRUE Offset is valid +**/ +STATIC +BOOLEAN +PchIsPcrOffsetValid ( + IN UINT32 Offset, + IN UINTN Size + ) +{ + if (((Offset & (Size - 1)) !=3D 0) || (Offset > 0xFFFF)) { + DEBUG ((DEBUG_ERROR, "PCR offset error. Invalid Offset: %x Size: %x", = Offset, Size)); + return FALSE; + } else { + return TRUE; + } +} +#endif + +/** + Read PCR register. + It returns PCR register and size in 4bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of this Port ID + + @retval UINT32 PCR register value. +**/ +UINT32 +PchPcrRead32 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset + ) +{ +#ifndef MDEPKG_NDEBUG + ASSERT (PchIsPcrOffsetValid (Offset, 4)); +#endif + return MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset)); +} + +/** + Read PCR register. + It returns PCR register and size in 2bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of this Port ID + + @retval UINT16 PCR register value. +**/ +UINT16 +PchPcrRead16 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset + ) +{ +#ifndef MDEPKG_NDEBUG + ASSERT (PchIsPcrOffsetValid (Offset, 2)); +#endif + return MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset)); +} + +/** + Read PCR register. + It returns PCR register and size in 1bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of this Port ID + + @retval UINT8 PCR register value +**/ +UINT8 +PchPcrRead8 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset + ) +{ + return MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset)); +} + +/** + Write PCR register. + It programs PCR register and size in 4bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] Data Input Data. Must be the same size as Size parameter= . + + @retval UINT32 Value written to register +**/ +UINT32 +PchPcrWrite32 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT32 Data + ) +{ +#ifndef MDEPKG_NDEBUG + ASSERT (PchIsPcrOffsetValid (Offset, 4)); +#endif + MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), Data); + + return Data; +} + +/** + Write PCR register. + It programs PCR register and size in 2bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] Data Input Data. Must be the same size as Size parameter= . + + @retval UINT16 Value written to register +**/ +UINT16 +PchPcrWrite16 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT16 Data + ) +{ +#ifndef MDEPKG_NDEBUG + ASSERT (PchIsPcrOffsetValid (Offset, 2)); +#endif + MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), Data); + + return Data; +} + +/** + Write PCR register. + It programs PCR register and size in 1bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] Data Input Data. Must be the same size as Size parameter= . + + @retval UINT8 Value written to register +**/ +UINT8 +PchPcrWrite8 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT8 Data + ) +{ + MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), Data); + + return Data; +} + +/** + Write PCR register. + It programs PCR register and size in 4bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] AndData AND Data. Must be the same size as Size parameter. + @param[in] OrData OR Data. Must be the same size as Size parameter. + + @retval UINT32 Value written to register + +**/ +UINT32 +PchPcrAndThenOr32 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData= ) | OrData); +} + +/** + Write PCR register and read back. + The read back ensures the PCR cycle is completed before next operation. + It programs PCR register and size in 4bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] AndData AND Data. Must be the same size as Size parameter. + @param[in] OrData OR Data. Must be the same size as Size parameter. + + @retval UINT32 Value read back from the register +**/ +UINT32 +PchPcrAndThenOr32WithReadback ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData) | OrD= ata); + return PchPcrRead32 (Pid, Offset); +} + +/** + Write PCR register. + It programs PCR register and size in 2bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] AndData AND Data. Must be the same size as Size parameter. + @param[in] OrData OR Data. Must be the same size as Size parameter. + + @retval UINT16 Value written to register + +**/ +UINT16 +PchPcrAndThenOr16 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PchPcrWrite16 (Pid, Offset, (PchPcrRead16 (Pid, Offset) & AndData= ) | OrData); +} + +/** + Write PCR register. + It programs PCR register and size in 1bytes. + The Offset should not exceed 0xFFFF and must be aligned with size. + + @param[in] Pid Port ID + @param[in] Offset Register offset of Port ID. + @param[in] AndData AND Data. Must be the same size as Size parameter. + @param[in] OrData OR Data. Must be the same size as Size parameter. + + @retval UINT8 Value written to register + +**/ +UINT8 +PchPcrAndThenOr8 ( + IN PCH_SBI_PID Pid, + IN UINT32 Offset, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PchPcrWrite8 (Pid, Offset, (PchPcrRead8 (Pid, Offset) & AndData) = | OrData); +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmc= Lib/PchPmcLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmP= chPmcLib/PchPmcLib.c new file mode 100644 index 0000000000..2654a76983 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/Pch= PmcLib.c @@ -0,0 +1,101 @@ +/** @file + PCH PMC Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Query PCH to determine the Pm Status + NOTE: + It's matter when did platform code use this library, since some status c= ould be cleared by write one clear. + Therefore this funciton is not always return the same result in one boot= . + It's suggested that platform code read this status in the beginning of p= ost. + For the ColdBoot case, this function only returns one case of the cold b= oot. Some cold boot case might + depends on the power cycle scenario and should check with different cond= tion. + + @param[in] PmStatus - The Pch Pm Status to be probed + + @retval Return TRUE if Status querried is Valid or FALSE if otherwise +**/ +BOOLEAN +GetPchPmStatus ( + PCH_PM_STATUS PmStatus + ) +{ + UINTN PmcRegBase; + UINT32 GblRst0; + + PmcRegBase =3D MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PMC, + PCI_FUNCTION_NUMBER_PCH_PMC + ); + + switch (PmStatus) { + case WarmBoot: + break; + + case PwrFlr: + break; + + case PwrFlrSys: + if (GblRst0 & BIT12) { + return TRUE; + } + break; + + case PwrFlrPch: + if (GblRst0 & BIT11) { + return TRUE; + } + break; + + case ColdBoot: + break; + + default: + break; + } + + return FALSE; +} + +/** + Funtion to check if Battery lost or CMOS cleared. + + @reval TRUE Battery is always present. + @reval FALSE CMOS is cleared. +**/ +BOOLEAN +EFIAPI +PchIsRtcBatteryGood ( + VOID + ) +{ + UINTN PmcBaseAddress; + + // + // Check if the CMOS battery is present + // Checks RTC_PWR_STS bit in the GEN_PMCON_3 register + // + PmcBaseAddress =3D MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PMC, + PCI_FUNCTION_NUMBER_PCH_PMC + ); + return FALSE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbi= AccessLib/PchSbiAccessLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Librar= y/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c new file mode 100644 index 0000000000..43690e2409 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessL= ib/PchSbiAccessLib.c @@ -0,0 +1,270 @@ +/** @file + PCH SBI access library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Execute PCH SBI message + Take care of that there is no lock protection when using SBI programming= in both POST time and SMI. + It will clash with POST time SBI programming when SMI happen. + Programmer MUST do the save and restore opration while using the PchSbiE= xecution inside SMI + to prevent from racing condition. + This function will reveal P2SB and hide P2SB if it's originally hidden. = If more than one SBI access + needed, it's better to unhide the P2SB before calling and hide it back a= fter done. + + When the return value is "EFI_SUCCESS", the "Response" do not need to be= checked as it would have been + SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would = provide additional information + when needed. + + @param[in] Pid Port ID of the SBI message + @param[in] Offset Offset of the SBI message + @param[in] Opcode Opcode + @param[in] Posted Posted message + @param[in, out] Data32 Read/Write data + @param[out] Response Response + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_DEVICE_ERROR Transaction fail + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_TIMEOUT Timeout while waiting for response +**/ +EFI_STATUS +EFIAPI +PchSbiExecution ( + IN PCH_SBI_PID Pid, + IN UINT64 Offset, + IN PCH_SBI_OPCODE Opcode, + IN BOOLEAN Posted, + IN OUT UINT32 *Data32, + OUT UINT8 *Response + ) +{ + // + // Check address valid + // + if (((UINT32) Offset & 0x3) !=3D 0) { + // + // Warning message for the address not DWORD alignment. + // + DEBUG ((DEBUG_INFO, "PchSbiExecution: Address is not DWORD aligned.\n"= )); + } + + return PchSbiExecutionEx ( Pid, + Offset, + Opcode, + Posted, + 0x000F, + 0x0000, + 0x0000, + Data32, + Response + ); +} + +/** + Full function for executing PCH SBI message + Take care of that there is no lock protection when using SBI programming= in both POST time and SMI. + It will clash with POST time SBI programming when SMI happen. + Programmer MUST do the save and restore opration while using the PchSbiE= xecution inside SMI + to prevent from racing condition. + This function will reveal P2SB and hide P2SB if it's originally hidden. = If more than one SBI access + needed, it's better to unhide the P2SB before calling and hide it back a= fter done. + + When the return value is "EFI_SUCCESS", the "Response" do not need to be= checked as it would have been + SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would = provide additional information + when needed. + + @param[in] Pid Port ID of the SBI message + @param[in] Offset Offset of the SBI message + @param[in] Opcode Opcode + @param[in] Posted Posted message + @param[in] Fbe First byte enable + @param[in] Bar Bar + @param[in] Fid Function ID + @param[in, out] Data32 Read/Write data + @param[out] Response Response + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_DEVICE_ERROR Transaction fail + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_TIMEOUT Timeout while waiting for response +**/ +EFI_STATUS +EFIAPI +PchSbiExecutionEx ( + IN PCH_SBI_PID Pid, + IN UINT64 Offset, + IN PCH_SBI_OPCODE Opcode, + IN BOOLEAN Posted, + IN UINT16 Fbe, + IN UINT16 Bar, + IN UINT16 Fid, + IN OUT UINT32 *Data32, + OUT UINT8 *Response + ) +{ + UINT64 P2sbBase; + UINTN Timeout; + UINT16 SbiStat; + + // + // Check opcode valid + // + switch (Opcode) { + case MemoryRead: + case MemoryWrite: + case PciConfigRead: + case PciConfigWrite: + case PrivateControlRead: + case PrivateControlWrite: + case GpioLockUnlock: + break; + default: + return EFI_INVALID_PARAMETER; + break; + } + + P2sbBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_P2SB, + PCI_FUNCTION_NUMBER_PCH_P2SB, + 0 + ); + if (PciSegmentRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) =3D=3D 0xFFFF) { + ASSERT (FALSE); + return EFI_DEVICE_ERROR; + } + /// + /// BWG Section 2.2.1 + /// 1. Poll P2SB PCI offset D8h[0] =3D 0b + /// Make sure the previous opeartion is completed. + /// + Timeout =3D 0xFFFFFFF; + while (Timeout > 0) { + SbiStat =3D PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT); + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) =3D=3D 0) { + break; + } + Timeout--; + } + if (Timeout =3D=3D 0) { + return EFI_TIMEOUT; + } + // + // Initial Response status + // + *Response =3D SBI_INVALID_RESPONSE; + SbiStat =3D 0; + /// + /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port= ID + /// + PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIADDR, (UINT32) ((Pid << 24) = | (UINT16) Offset)); + /// + /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is e= xpected to be 0 in PCH. + /// + PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIEXTADDR, (UINT32) RShiftU64 = (Offset, 16)); + /// + /// 5. Set P2SB PCI offset D8h[15:8] =3D 00000110b for read + /// Set P2SB PCI offset D8h[15:8] =3D 00000111b for write + // + // Set SBISTAT[15:8] to the opcode passed in + // Set SBISTAT[7] to the posted passed in + // + PciSegmentAndThenOr16 ( + (P2sbBase + R_P2SB_CFG_SBISTAT), + (UINT16) ~(B_P2SB_CFG_SBISTAT_OPCODE | B_P2SB_CFG_SBISTAT_POSTED), + (UINT16) ((Opcode << 8) | (Posted << 7)) + ); + /// + /// 6. Write P2SB PCI offset DAh[15:0] =3D F000h + /// + // + // Set RID[15:0] =3D Fbe << 12 | Bar << 8 | Fid + // + PciSegmentWrite16 ( + (P2sbBase + R_P2SB_CFG_SBIRID), + (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF)) + ); + + switch (Opcode) { + case MemoryWrite: + case PciConfigWrite: + case PrivateControlWrite: + case GpioLockUnlock: + /// + /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accord= ingly + /// + PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), *Data32); + break; + default: + /// + /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0, + /// because all D0-DFh register range must be touched in PCH + /// for a successful SBI transaction. + /// + PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), 0); + break; + } + /// + /// 7. Set P2SB PCI offset D8h[0] =3D 1b, Poll P2SB PCI offset D8h[0] = =3D 0b + /// + // + // Set SBISTAT[0] =3D 1b, trigger the SBI operation + // + PciSegmentOr16 (P2sbBase + R_P2SB_CFG_SBISTAT, (UINT16) B_P2SB_CFG_SBIST= AT_INITRDY); + // + // Poll SBISTAT[0] =3D 0b, Polling for Busy bit + // + Timeout =3D 0xFFFFFFF; + while (Timeout > 0) { + SbiStat =3D PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT); + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) =3D=3D 0) { + break; + } + Timeout--; + } + if (Timeout =3D=3D 0) { + // + // If timeout, it's fatal error. + // + return EFI_TIMEOUT; + } else { + /// + /// 8. Check if P2SB PCI offset D8h[2:1] =3D 00b for successful transa= ction + /// + *Response =3D (UINT8) ((SbiStat & B_P2SB_CFG_SBISTAT_RESPONSE) >> N_P2= SB_CFG_SBISTAT_RESPONSE); + if (*Response =3D=3D SBI_SUCCESSFUL) { + switch (Opcode) { + case MemoryRead: + case PciConfigRead: + case PrivateControlRead: + /// + /// 9. Read P2SB PCI offset D4h[31:0] for SBI data + /// + *Data32 =3D PciSegmentRead32 (P2sbBase + R_P2SB_CFG_SBIDATA); + break; + default: + break; + } + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + } +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoLib/PchSerialIoLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/= PeiDxeSmmPchSerialIoLib/PchSerialIoLib.c new file mode 100644 index 0000000000..0e79d83a12 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLi= b/PchSerialIoLib.c @@ -0,0 +1,516 @@ +/** @file + PCH Serial IO Lib implementation. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCIEX_BAR_ADDR_MASK 0x0000007FFC000000 + +typedef struct { + UINT32 Bar0; + UINT32 Bar1; +} SERIAL_IO_CONTROLLER_DESCRIPTOR; + +GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoAcp= iAddress [PCH_MAX_SERIALIO_CONTROLLERS] =3D +{ + {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x10= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x30= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x50= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x70= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x90= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB0= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD0= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF0= 00}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11= 000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13= 000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15= 000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x16000, PCH_SERIAL_IO_BASE_ADDRESS + 0x17= 000} +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchSerialIoPciCfgCtrAddr [PCH_MAX_SE= RIALIO_CONTROLLERS] =3D +{ + R_SERIAL_IO_PCR_PCICFGCTRL1, + R_SERIAL_IO_PCR_PCICFGCTRL2, + R_SERIAL_IO_PCR_PCICFGCTRL3, + R_SERIAL_IO_PCR_PCICFGCTRL4, + R_SERIAL_IO_PCR_PCICFGCTRL5, + R_SERIAL_IO_PCR_PCICFGCTRL6, + R_SERIAL_IO_PCR_PCICFGCTRL13, + R_SERIAL_IO_PCR_PCICFGCTRL14, + R_SERIAL_IO_PCR_PCICFGCTRL9, + R_SERIAL_IO_PCR_PCICFGCTRL10, + R_SERIAL_IO_PCR_PCICFGCTRL11 +}; + +/** + Returns Serial IO Controller Type I2C, SPI or UART + + @param[in] Number Number of SerialIo controller + + @retval I2C, SPI or UART + @retval UNKNOWN - in case if undefined controller +**/ +PCH_SERIAL_IO_CONTROLLER_TYPE +GetSerialIoControllerType ( + IN PCH_SERIAL_IO_CONTROLLER Controller + ) +{ + if (Controller >=3D PchSerialIoIndexI2C0 && Controller <=3D GetMaxI2cNum= ber ()) { + return SERIAL_IO_I2C; + } else if (Controller >=3D PchSerialIoIndexSpi0 && Controller < (PchSeri= alIoIndexSpi0 + GetPchMaxSerialIoSpiControllersNum ())) { + return SERIAL_IO_SPI; + } else if (Controller >=3D PchSerialIoIndexUart0 && Controller <=3D PchS= erialIoIndexUart2) { + return SERIAL_IO_UART; + } + return SERIAL_IO_UNKNOWN; +} + +/** + Checks if given Serial IO Controller Function equals 0 + + @param[in] SerialIoNumber Serial IO device + + @retval TRUE if SerialIO Function is equal= to 0 + FALSE if Function is higher then 0 +**/ +BOOLEAN +IsSerialIoFunctionZero ( + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber + ) +{ + if (GetSerialIoFunctionNumber (SerialIoNumber) > 0) { + return FALSE; + } + return TRUE; +} + +/** + Checks if given Serial IO Controller is enabled or not + + @param[in] DeviceNumber device number + @param[in] FunctionNumber function number + + @retval TRUE TRUE if given serial io device is = enabled. + @retval FALSE FALSE if given serial io device is= disabled. +**/ +BOOLEAN +IsSerialIoDeviceEnabled ( + IN UINT8 DeviceNumber, + IN UINT8 FunctionNumber + ) +{ + if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBE= R_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, DeviceNumber, FunctionNumber, PCI_DEVICE= _ID_OFFSET)) !=3D 0xFFFF) { + return TRUE; + } + return FALSE; +} + +/** + Checks if given device corresponds to any of LPSS Devices + + @param[in] DeviceNumber device number + @param[in] FunctionNumber function number + + @retval TRUE if SerialIO Device/Function N= umber is equal to any of LPSS devices + FALSE Device/Function is not in Se= rial IO scope +**/ +BOOLEAN +IsSerialIoDevice ( + IN UINT8 DeviceNumber, + IN UINT8 FunctionNumber + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + PCH_SERIAL_IO_CONTROLLER ControllerMax; + + ControllerMax =3D GetPchMaxSerialIoControllersNum (); + + for (Controller =3D 0; Controller < ControllerMax; Controller++) { + if ((DeviceNumber =3D=3D GetSerialIoDeviceNumber (Controller)) && + (FunctionNumber =3D=3D GetSerialIoFunctionNumber (Controller))) { + return TRUE; + } + } + return FALSE; +} + +/** + Gets Pci Config control offset + + @param[in] DeviceNumber device number + @param[in] FunctionNumber function number + + @retval CfgCtrAddr Offset of Pci config control + 0 if Device and Function do not co= rrespond to Serial IO +**/ +UINT16 +GetSerialIoConfigControlOffset ( + IN UINT8 DeviceNumber, + IN UINT8 FunctionNumber + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + PCH_SERIAL_IO_CONTROLLER ControllerMax; + + ControllerMax =3D GetPchMaxSerialIoControllersNum (); + + for (Controller =3D 0; Controller < ControllerMax; Controller++) { + if ((DeviceNumber =3D=3D GetSerialIoDeviceNumber (Controller)) && + (FunctionNumber =3D=3D GetSerialIoFunctionNumber (Controller))) { + return mPchSerialIoPciCfgCtrAddr[Controller]; + } + } + + return 0; +} + +/** + Checks if Device with given AcpiHid string is one of SerialIo controller= s + If yes, its number is returned through Number parameter, otherwise Numbe= r is not updated + + @param[in] AcpiHid String + @param[out] Number Number of SerialIo controller + + @retval TRUE yes it is a SerialIo controller + @retval FALSE no it isn't a SerialIo controller +**/ +BOOLEAN +IsSerialIoAcpiHid ( + IN CHAR8 *AcpiHid, + OUT PCH_SERIAL_IO_CONTROLLER *Number + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + PCH_SERIAL_IO_CONTROLLER ControllerMax; + + ControllerMax =3D GetPchMaxSerialIoControllersNum (); + + for (Controller =3D 0; Controller < ControllerMax; Controller++) { + if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, GetSerialIoAcpiHid(Controll= er))) { + *Number =3D Controller; + return TRUE; + } + } + return FALSE; +} + +/** + Finds BAR values of SerialIo devices. + SerialIo devices can be configured to not appear on PCI so traditional m= ethod of reading BAR might not work. + If the SerialIo device is in PCI mode, a request for BAR1 will return it= s PCI CFG space instead + + @param[in] SerialIoDevice Serial IO device + @param[in] BarNumber 0=3DBAR0, 1=3DBAR1 + + @retval SerialIo Bar value +**/ +UINTN +FindSerialIoBar ( + IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice, + IN UINT8 BarNumber + ) +{ + UINT64 Bar; + UINT64 PcieBase; + UINT64 PciSegBase; + UINT16 VenId; + UINT32 Device; + UINT32 Function; + + Device =3D GetSerialIoDeviceNumber (SerialIoDevice); + Function =3D GetSerialIoFunctionNumber (SerialIoDevice); + + PcieBase =3D PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_M= C_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_PCIEXBAR)); // S0:B0:D0:F0:R60 + PcieBase =3D (PcieBase & PCIEX_BAR_ADDR_MASK) + LShiftU64 (DEFAULT_PCI_B= US_NUMBER_PCH, 20) + LShiftU64 (Device, 15) + LShiftU64 (Function, 12); + + PciSegBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + Device, + Function, + 0 + ); + + VenId =3D PciSegmentRead16 (PciSegBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF; + if (VenId =3D=3D V_PCH_INTEL_VENDOR_ID) { + if (BarNumber =3D=3D 1) { + return ((UINTN) PcieBase); + } + Bar =3D PciSegmentRead32 (PciSegBase + PCI_BASE_ADDRESSREG_OFFSET); + // For 64-Bit Memory Space BARs ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & = 0xFFFFFFFF) << 32) + if ((Bar & B_PCI_BAR_MEMORY_TYPE_MASK) =3D=3D B_PCI_BAR_MEMORY_TYPE_64= ) { + Bar =3D (Bar & 0xFFFFF000) + (UINTN) ((UINT64) LShiftU64 ((PciSegmen= tRead32 (PciSegBase + PCI_BASE_ADDRESSREG_OFFSET + 4) & 0xFFFFFFFF), 32)); + return (UINTN) Bar; + } + return (UINTN) (Bar & 0xFFFFF000); + } + //PCI mode failed? Try hardcoded addresses from ACPI + if (BarNumber =3D=3D 0) { + Bar =3D mSerialIoAcpiAddress[SerialIoDevice].Bar0; + } else { + Bar =3D mSerialIoAcpiAddress[SerialIoDevice].Bar1; + } + return (UINTN) Bar; +} + +/** + Get PSF_PORT for a given Serial IO Controller + + @param[in] Controller Serial IO controller number +**/ +STATIC +PSF_PORT +SerialIoPsfPort ( + IN PCH_SERIAL_IO_CONTROLLER Controller + ) +{ + switch (GetSerialIoControllerType (Controller)) { + case SERIAL_IO_I2C: + return PsfSerialIoI2cPort (Controller - PchSerialIoIndexI2C0); + case SERIAL_IO_SPI: + return PsfSerialIoSpiPort (Controller - PchSerialIoIndexSpi0); + case SERIAL_IO_UART: + return PsfSerialIoUartPort (Controller - PchSerialIoIndexUart0); + case SERIAL_IO_UNKNOWN: + default: + return (PSF_PORT){0}; + } +} + +/** + Configures Serial IO Controller + + @param[in] Controller Serial IO controller number + @param[in] DeviceMode Device operation mode + @param[in] PsfDisable Disable device at PSF level + + @retval None +**/ +VOID +ConfigureSerialIoController ( + IN PCH_SERIAL_IO_CONTROLLER Controller, + IN PCH_SERIAL_IO_MODE DeviceMode, + IN BOOLEAN PsfDisable + ) +{ + UINT64 PciCfgBase; + UINT32 Data32And; + UINT32 Data32Or; + UINT16 *SerialIoPciCfgCtrAddr; + UINT8 Uart8BitLoop; + +/* + Please do not add DEBUG message here because this routine is configuring= SerialIoUart. + Printing DEBUG message before SerialIoUart initialization may cause syst= em hang (in Debug build). +*/ + + // + // This is to prevent from overflow of array access. + // + if (Controller >=3D PCH_MAX_SERIALIO_CONTROLLERS) { + return; + } + + if (GetSerialIoControllerType (Controller) =3D=3D SERIAL_IO_UNKNOWN) { + return; + } + + PciCfgBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + GetSerialIoDeviceNumber (Controller), + GetSerialIoFunctionNumber (Controller), + 0 + ); + // + // Do not modify a device that has already been disabled/hidden + // + if (PciSegmentRead16 (PciCfgBase + PCI_VENDOR_ID_OFFSET) !=3D V_PCH_INTE= L_VENDOR_ID) { + return; + } + + /// + /// Step 0. set Bit 16,17,18. + /// + PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_D0I3MAXDEVPG, BIT18 | BIT17= | BIT16); + + SerialIoPciCfgCtrAddr =3D mPchSerialIoPciCfgCtrAddr; + + switch (DeviceMode) { + case PchSerialIoDisabled: + /// + /// Step 1. Put device in D3 + /// Step 2. Function Disable in PSF + /// + PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, BIT1 | BI= T0); + + if (PsfDisable) { + PsfDisableDevice (SerialIoPsfPort (Controller)); + } + break; + case PchSerialIoAcpi: + case PchSerialIoHidden: + /// + /// reenable BAR1 in case it was disabled earlier + /// Read back is needed to enforce the sideband and primary ordering= . + /// + PchPcrAndThenOr32WithReadback ( + PID_SERIALIO, + SerialIoPciCfgCtrAddr[Controller], + (UINT32) ~(B_SERIAL_IO_PCR_PCICFGCTRL_BAR1_DIS), + 0 + ); + PsfEnableDeviceBar (SerialIoPsfPort (Controller), BIT3 | BIT2); + /// + /// Step 1. Assign BAR0 + /// Step 2. Assign BAR1 + /// + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW, mSerialIo= AcpiAddress[Controller].Bar0); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR1_LOW, mSerialIo= AcpiAddress[Controller].Bar1); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR1_HIGH, 0x0); + /// + /// Step 3. Set Memory space Enable + /// + PciSegmentOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEM= ORY_SPACE); + /// + /// Step 4. Disable device's PciCfg and enable ACPI interrupts + /// Read back is needed to enforce the sideband and primary = ordering. + /// + PchPcrAndThenOr32WithReadback ( + PID_SERIALIO, + SerialIoPciCfgCtrAddr[Controller], + ~0u, + (B_SERIAL_IO_PCR_PCICFGCTRL_PCI_CFG_DIS | B_SERIAL_IO_PCR_PCICFGCT= RL_ACPI_INTR_EN) + ); + /// + /// Step 5. Disable device's PciCfg in PSF + /// + PsfHideDevice (SerialIoPsfPort (Controller)); + /// + /// get controller out of reset + /// + MmioOr32 ( + mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_PPR_RESETS= , + B_SERIAL_IO_MEM_PPR_RESETS_FUNC | B_SERIAL_IO_MEM_PPR_RESETS_APB |= B_SERIAL_IO_MEM_PPR_RESETS_IDMA + ); + break; + case PchSerialIoPci: + // + // Check If device is already initialized + // + if (PciSegmentRead32 (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET) & 0xF= FFFF000) { + return; + } + /// + /// reenable PciCfg in case it was disabled earlier + /// Read back is needed to enforce the sideband and primary ordering= . + /// + PchPcrAndThenOr32WithReadback ( + PID_SERIALIO, + SerialIoPciCfgCtrAddr[Controller], + (UINT32) ~(B_SERIAL_IO_PCR_PCICFGCTRL_PCI_CFG_DIS | B_SERIAL_IO_PC= R_PCICFGCTRL_ACPI_INTR_EN), + 0 + ); + PsfUnhideDevice (SerialIoPsfPort (Controller)); + /// + /// Disable Bar1 + /// Disable Bar1 in PSF + /// Read back is needed to enforce the sideband and primary ordering= . + /// + PchPcrAndThenOr32WithReadback ( + PID_SERIALIO, + SerialIoPciCfgCtrAddr[Controller], + ~0u, + B_SERIAL_IO_PCR_PCICFGCTRL_BAR1_DIS + ); + PsfDisableDeviceBar (SerialIoPsfPort (Controller), BIT3 | BIT2); + + // + // Assign BAR0 and Set Memory space Enable + // + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW, mSerialIo= AcpiAddress[Controller].Bar0); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0); + PciSegmentOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_= MEMORY_SPACE); + /// + /// get controller out of reset + /// + MmioOr32 ( + mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_PPR_RESETS= , + B_SERIAL_IO_MEM_PPR_RESETS_FUNC | B_SERIAL_IO_MEM_PPR_RESETS_APB |= B_SERIAL_IO_MEM_PPR_RESETS_IDMA + ); + break; + default: + return; + } + + /// + /// Step X. Program clock dividers for UARTs + /// Step Y. Enable Byte addressing for UARTs in legacy mode + /// + if ((Controller >=3D PchSerialIoIndexUart0 && Controller <=3D PchSerialI= oIndexUart2) && (DeviceMode !=3D PchSerialIoDisabled)) { + MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_P= PR_CLK, + (B_SERIAL_IO_MEM_PPR_CLK_UPDATE | (V_SERIAL_IO_MEM_PPR_CLK_N_DIV << = 16) | + (V_SERIAL_IO_MEM_PPR_CLK_M_DIV << 1) | B_SERIAL_IO_MEM_PPR_CLK_EN ) + ); + + Data32And =3D (UINT32) (~(B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN = << (Controller - PchSerialIoIndexUart0))); + Data32Or =3D 0x0; + if (DeviceMode =3D=3D PchSerialIoHidden) { + Data32Or =3D (B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN << (Contro= ller - PchSerialIoIndexUart0)); + } + PchPcrAndThenOr32 (PID_SERIALIO, R_SERIAL_IO_PCR_GPPRVRW7,Data32And,Da= ta32Or); + // + // Dummy read after setting any of GPPRVRW7. + // Required for UART 16550 8-bit Legacy mode to become active + // + MmioRead32 (mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_PP= R_CLK); + // + // Loop until Uart has successfuly moved to 8 bit mode + // + if (DeviceMode =3D=3D PchSerialIoHidden) { + Uart8BitLoop =3D 10; + while (Uart8BitLoop > 0) { + if (DetectAccessMode (mSerialIoAcpiAddress[Controller].Bar0) =3D= =3D AccessMode8bit) { + return; + } + Uart8BitLoop--; + } + } + } + + /// + /// Step Z. Program I2C SDA hold registers + /// + if (Controller >=3D PchSerialIoIndexI2C0 && Controller <=3D GetMaxI2cNum= ber ()) { + if (DeviceMode !=3D PchSerialIoDisabled) { + MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_I2= C_SDA_HOLD, V_SERIAL_IO_MEM_I2C_SDA_HOLD_VALUE); + } + } + +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoLib/PchSerialIoLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Libra= ry/PeiDxeSmmPchSerialIoLib/PchSerialIoLibCnl.c new file mode 100644 index 0000000000..28ccd626af --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLi= b/PchSerialIoLibCnl.c @@ -0,0 +1,181 @@ +/** @file + PCH Serial IO Lib implementation Cannon Lake specific. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "PchSerialIoLibInternal.h" + +GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mCnlAcpiHid[PCH_MAX_SERIALIO_CONTROLLE= RS][SERIALIO_HID_LENGTH] =3D +{ + "INT34B2", + "INT34B3", + "INT34B4", + "INT34B5", + "INT34B6", + "INT34B7", + "INT34B0", + "INT34B1", + "INT34BC", + "INT34B8", + "INT34B9", + "INT34BA" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mCnlPchLpSerialIoId [PCH_MAX_SERIALIO= _CONTROLLERS] =3D +{ + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C0_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C1_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C2_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C3_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C4_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C5_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_SPI0_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_SPI1_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_UART0_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_UART1_DEVICE_ID, + V_CNL_PCH_LP_SERIAL_IO_CFG_UART2_DEVICE_ID +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mCnlPchHSerialIoId [PCH_MAX_SERIALIO_= CONTROLLERS] =3D +{ + V_CNL_PCH_H_SERIAL_IO_CFG_I2C0_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_I2C1_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_I2C2_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_I2C3_DEVICE_ID, + 0, + 0, + V_CNL_PCH_H_SERIAL_IO_CFG_SPI0_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_SPI1_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_UART0_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_UART1_DEVICE_ID, + V_CNL_PCH_H_SERIAL_IO_CFG_UART2_DEVICE_ID +}; + +GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS mSerialIoBdf [PCH_MAX_= SERIALIO_CONTROLLERS] =3D +{ + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C2}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C3}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C4}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_I2C5}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_SPI0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_SPI1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_UART0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_UART1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2, PCI_FUNCTION_NUMBER_PCH_SERIAL_I= O_UART2} +}; + + +/** + Returns index of the last i2c controller + + @param[in] Number Number of SerialIo controller + + @retval Index of I2C controller +**/ +PCH_SERIAL_IO_CONTROLLER +GetMaxI2cNumber ( + VOID + ) +{ + if (IsPchH ()) { + return PchSerialIoIndexI2C3; + } else { + return PchSerialIoIndexI2C5; + } +} + +/** + Checks if Device with given PciDeviceId is one of SerialIo controllers + If yes, its number is returned through Number parameter, otherwise Numbe= r is not updated + + @param[in] PciDevId Device ID + @param[out] Number Number of SerialIo controller + + @retval TRUE Yes it is a SerialIo controller + @retval FALSE No it isn't a SerialIo controller +**/ +BOOLEAN +IsSerialIoPciDevId ( + IN UINT16 PciDevId, + OUT PCH_SERIAL_IO_CONTROLLER *Number + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + + for (Controller =3D 0; Controller < GetPchMaxSerialIoControllersNum (); = Controller++) { + if ((IsPchLp () && (PciDevId =3D=3D mCnlPchLpSerialIoId[Controller])) = || + (IsPchH () && (PciDevId =3D=3D mCnlPchHSerialIoId[Controller]))) + { + *Number =3D Controller; + return TRUE; + } + } + return FALSE; +} + +/** + Finds PCI Device Number of SerialIo devices. + + @param[in] SerialIoNumber Serial IO device + + @retval SerialIo device number +**/ +UINT8 +GetSerialIoDeviceNumber ( + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber + ) +{ + return mSerialIoBdf[SerialIoNumber].DevNum; +} + +/** + Finds PCI Function Number of SerialIo devices. + + @param[in] SerialIoNumber Serial IO device + + @retval SerialIo funciton number +**/ +UINT8 +GetSerialIoFunctionNumber ( + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber + ) +{ + return mSerialIoBdf[SerialIoNumber].FuncNum; +} + +/** + Returns string with AcpiHid assigned to selected SerialIo controller + + @param[in] Number Number of SerialIo controller + + @retval pointer to 8-byte string +**/ +CHAR8* +GetSerialIoAcpiHid ( + IN PCH_SERIAL_IO_CONTROLLER Number + ) +{ + return mCnlAcpiHid[Number]; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSer= ialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c b/Silicon/Intel/CoffeelakeSilico= nPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c new file mode 100644 index 0000000000..621a473cfa --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUa= rtLib/PeiDxeSmmPchSerialIoUartLib.c @@ -0,0 +1,372 @@ +/** @file + PCH Serial IO UART Lib implementation. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BAUD_RATE 115200 + +#define R_PCH_SERIAL_IO_8BIT_UART_RXBUF 0x00 +#define R_PCH_SERIAL_IO_8BIT_UART_TXBUF 0x00 +#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW 0x00 +#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH 0x01 +#define R_PCH_SERIAL_IO_8BIT_UART_FCR 0x02 +#define R_PCH_SERIAL_IO_8BIT_UART_IIR 0x02 +#define R_PCH_SERIAL_IO_8BIT_UART_LCR 0x03 +#define R_PCH_SERIAL_IO_8BIT_UART_MCR 0x04 +#define R_PCH_SERIAL_IO_8BIT_UART_LSR 0x05 +#define R_PCH_SERIAL_IO_8BIT_UART_USR 0x1F +#define R_PCH_SERIAL_IO_32BIT_UART_CTR 0xFC //Component Type Registe= r contains identification code +#define UART_COMPONENT_IDENTIFICATION_CODE 0x44570110 + +#define B_PCH_SERIAL_IO_UART_IIR_FIFOSE BIT7|BIT6 +#define B_PCH_SERIAL_IO_UART_LSR_RXDA BIT0 +#define B_PCH_SERIAL_IO_UART_LSR_BI BIT4 +#define B_PCH_SERIAL_IO_UART_LSR_TXRDY BIT5 +#define B_PCH_SERIAL_IO_UART_LCR_DLAB BIT7 +#define B_PCH_SERIAL_IO_UART_FCR_FCR BIT0 +#define B_PCH_SERIAL_IO_UART_MCR_RTS BIT1 +#define B_PCH_SERIAL_IO_UART_MCR_AFCE BIT5 +#define B_PCH_SERIAL_IO_UART_USR_TFNF BIT1 + +/** + Returns UART's currently active access mode, 8 or 32 bit + + @param[in] MmioBase Base address of UART MMIO space + + @retval AccessMode8bit + @retval AccessMode32bit +**/ +UART_ACCESS_MODE +DetectAccessMode ( + IN UINTN MmioBase + ) +{ + if (MmioRead32 (MmioBase + R_PCH_SERIAL_IO_32BIT_UART_CTR) =3D=3D UART_C= OMPONENT_IDENTIFICATION_CODE) { + return AccessMode32bit; + } else { + return AccessMode8bit; + } +} + + +/** + Register access helper. Depending on SerialIO UART mode, + its registers are aligned to 1 or 4 bytes and have 8 or 32bit size + + @param[in] AccessMode Selects between 8bit access to 1-byte aligned= registers or 32bit access to 4-byte algined + @param[in] BaseAddress Base address of UART MMIO space + @param[in] Offset Register offset in 8bit mode + @param[in] Data Data to be written +**/ +STATIC +VOID +WriteRegister ( + IN UART_ACCESS_MODE AccessMode, + IN UINTN BaseAddress, + IN UINTN Offset, + IN UINT8 Data + ) +{ + if (AccessMode =3D=3D AccessMode32bit) { + MmioWrite32 (BaseAddress + 4*Offset, Data); + } else { + MmioWrite8 (BaseAddress + Offset, Data); + } +} + +/** + Register access helper. Depending on SerialIO UART mode, + its registers are aligned to 1 or 4 bytes and have 8 or 32bit size + + @param[in] AccessMode Selects between 8bit access to 1-byte aligned= registers or 32bit access to 4-byte algined + @param[in] BaseAddress Base address of UART MMIO space + @param[in] Offset Register offset in 8bit mode + @retval retrieved register value, always 8bit regardl= ess of access mode +**/ +STATIC +UINT8 +ReadRegister ( + IN UART_ACCESS_MODE AccessMode, + IN UINTN BaseAddress, + IN UINTN Offset + ) +{ + if (AccessMode =3D=3D AccessMode32bit) { + return (UINT8) (0xFF & MmioRead32 (BaseAddress + 4*Offset)); + } else { + return MmioRead8 (BaseAddress + Offset); + } +} + +/** + SerialIo UART in PCI mode will become unavailable when PCI enumerator + disables its memory space. This function re-enables it + + @param[in] UartNumber Selects Serial IO UART device (0-2) +**/ +STATIC +VOID +EnablePciMse ( + IN UINT8 UartNumber + ) +{ + UINTN CfgSpace; + + CfgSpace =3D FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 1); + if (MmioRead16 (CfgSpace + PCI_VENDOR_ID_OFFSET) =3D=3D 0xFFFF) { + return; + } + if ((MmioRead16 (CfgSpace + PCI_COMMAND_OFFSET) & EFI_PCI_COMMAND_MEMORY= _SPACE) !=3D EFI_PCI_COMMAND_MEMORY_SPACE) { + if ((MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000) = !=3D 0x0 && + (MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000) = !=3D 0xFFFFF000 ) { + MmioOr8 (CfgSpace + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE= ); + } + } +} + +/** + Initialize selected SerialIo UART. + This init function MUST be used prior any SerialIo UART functions to ini= t serial io controller if platform is going use serialio UART as debug outp= ut. + + @param UartNumber Selects Serial IO UART device (0-2) + @param FifoEnable When TRUE, enables 64-byte FIFOs. + @param BaudRate Baud rate. + @param LineControl Data length, parity, stop bits. + @param HardwareFlowControl Automated hardware flow control. If TRUE, h= ardware automatically checks CTS when sending data, and sets RTS when recei= ving data. +**/ +VOID +EFIAPI +PchSerialIoUartInit ( + UINT8 UartNumber, + BOOLEAN FifoEnable, + UINT32 BaudRate, + UINT8 LineControl, + BOOLEAN HardwareFlowControl + ) +{ + UINTN Base; + UINTN Divisor; + UART_ACCESS_MODE AccessMode; + + Base =3D FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + if ((Base & 0xFFFFFF00) =3D=3D 0x0 || (Base & 0xFFFFF000) =3D=3D 0xFFFFF= 000) { + // + // Base is not programmed, skip it. + // + return; + } + EnablePciMse (UartNumber); + AccessMode =3D DetectAccessMode (Base); + + Divisor =3D MAX_BAUD_RATE / BaudRate; + + // + // Configure baud rate + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR, B_PCH_SE= RIAL_IO_UART_LCR_DLAB); + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH, (U= INT8) (Divisor >> 8)); + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW, (UI= NT8) (Divisor & 0xff)); + // + // Configure Line control and switch back to bank 0 + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR, LineCont= rol & 0x1F); + // + // Enable and reset FIFOs + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_FCR, FifoEnab= le?B_PCH_SERIAL_IO_UART_FCR_FCR:0 ); + // + // Put Modem Control Register(MCR) into its reset state of 0x00. + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_MCR, B_PCH_SE= RIAL_IO_UART_MCR_RTS | (HardwareFlowControl?B_PCH_SERIAL_IO_UART_MCR_AFCE:0= )); +} + +/** + Write data to serial device. + + If the buffer is NULL, then return 0; + if NumberOfBytes is zero, then return 0. + + @param UartNumber Selects Serial IO UART device (0-2) + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buff= er. + + @retval Actual number of bytes writed to serial device. +**/ +UINTN +EFIAPI +PchSerialIoUartOut ( + IN UINT8 UartNumber, + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + UINTN BytesLeft; + UINTN Base; + UART_ACCESS_MODE AccessMode; + + if (NULL =3D=3D Buffer) { + return 0; + } + + Base =3D FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uni= nitialized UART + // + if ((Base & 0xFFFFFF00) =3D=3D 0x0 || (Base & 0xFFFFF000) =3D=3D 0xFFFFF= 000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode =3D DetectAccessMode (Base); + + if (ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_USR) =3D= =3D 0xFF) { + return 0; + } + + BytesLeft =3D NumberOfBytes; + + while (BytesLeft !=3D 0) { + // + // Write data while there's room in TXFIFO. If HW Flow Control was ena= bled, it happens automatically on hardware level. + // + if (ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_USR) & B= _PCH_SERIAL_IO_UART_USR_TFNF) { + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_TXBUF, *B= uffer); + Buffer++; + BytesLeft--; + } + } + + return NumberOfBytes; +} + +/* + Read data from serial device and save the datas in buffer. + + If the buffer is NULL, then return 0; + if NumberOfBytes is zero, then return 0. + + @param UartNumber Selects Serial IO UART device (0-2) + @param Buffer Point of data buffer which need to be write= d. + @param NumberOfBytes Number of output bytes which are cached in = Buffer. + @param WaitUntilBufferFull When TRUE, function waits until whole buffe= r is filled. When FALSE, function returns as soon as no new characters are = available. + + @retval Actual number of bytes raed to serial devic= e. + +**/ +UINTN +EFIAPI +PchSerialIoUartIn ( + IN UINT8 UartNumber, + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes, + IN BOOLEAN WaitUntilBufferFull + ) +{ + UINTN BytesReceived; + UINTN Base; + UART_ACCESS_MODE AccessMode; + UINT8 Lsr; + UINT8 Byte; + + if (NULL =3D=3D Buffer) { + return 0; + } + + Base =3D FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uni= nitialized UART + // + if ((Base & 0xFFFFFF00) =3D=3D 0x0 || (Base & 0xFFFFF000) =3D=3D 0xFFFFF= 000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode =3D DetectAccessMode (Base); + + BytesReceived =3D 0; + + while (BytesReceived !=3D NumberOfBytes) { + // + // Read the line status register + // + Lsr =3D ReadRegister(AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LSR); + + // + // If there is data in the RX buffer, read it. + // + if ((Lsr & B_PCH_SERIAL_IO_UART_LSR_RXDA) !=3D 0) { + Byte =3D ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_R= XBUF); + // + // Check if the break interrupt bit is set. If set, the byte read fr= om the + // RX buffer is invalid and should be ignored. If not set, copy the = byte into + // the receive buffer. + // + if ((Lsr & B_PCH_SERIAL_IO_UART_LSR_BI) =3D=3D 0) { + *Buffer =3D Byte; + Buffer++; + BytesReceived++; + } + } else { + if (!WaitUntilBufferFull) { + // + // If there's no data and function shouldn't wait, exit early + // + return BytesReceived; + } + } + } + return BytesReceived; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls a serial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is= returned. + If there is no data waiting to be read from the serial device, then FALS= E is returned. + + @param UartNumber Selects Serial IO UART device (0-2) + + @retval TRUE Data is waiting to be read from the serial devi= ce. + @retval FALSE There is no data waiting to be read from the se= rial device. + +**/ +BOOLEAN +EFIAPI +PchSerialIoUartPoll ( + IN UINT8 UartNumber + ) +{ + UINTN Base; + UART_ACCESS_MODE AccessMode; + + Base =3D FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uni= nitialized UART + // + if ((Base & 0xFFFFFF00) =3D=3D 0x0 || (Base & 0xFFFFF000) =3D=3D 0xFFFFF= 000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode =3D DetectAccessMode (Base); + + // + // Read the serial port status + // + if ((ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LSR) & B_= PCH_SERIAL_IO_UART_LSR_RXDA) !=3D 0) { + return TRUE; + } + return FALSE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdt= CommonLib/WdtCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiD= xeSmmPchWdtCommonLib/WdtCommon.c new file mode 100644 index 0000000000..679dcae0ab --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonL= ib/WdtCommon.c @@ -0,0 +1,242 @@ +/** @file + Library that contains common parts of WdtPei and WdtDxe. Not a standalon= e module. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mAllowExpectedReset =3D 0; + +/** + Reads LPC bridge to get Watchdog Timer address + + + @retval UINT32 Watchdog's address +**/ +UINT32 +WdtGetAddress ( + VOID + ) +{ + return PmcGetAcpiBase () + R_ACPI_IO_OC_WDT_CTL; +} + +/** + Reloads WDT with new timeout value and starts it. Also sets Unexpected R= eset bit, which + causes the next reset to be treated as watchdog expiration - unless Allo= wKnownReset() + function was called too. + + @param[in] TimeoutValue Time in seconds before WDT times out. Su= pported range =3D 1 - 1024. + + @retval EFI_SUCCESS if everything's OK + @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong +**/ +EFI_STATUS +EFIAPI +WdtReloadAndStart ( + IN UINT32 TimeoutValue + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "\n(Wdt) ReloadAndStartTimer(%d)\n", TimeoutValue)); + + if ((TimeoutValue > B_ACPI_IO_OC_WDT_CTL_TOV_MASK) || (TimeoutValue =3D= =3D 0)) { + return EFI_INVALID_PARAMETER; + } + + Readback =3D IoRead32 (WdtGetAddress ()); + Readback |=3D (B_ACPI_IO_OC_WDT_CTL_EN | B_ACPI_IO_OC_WDT_CTL_FORCE_ALL = | B_ACPI_IO_OC_WDT_CTL_ICCSURV); + if (mAllowExpectedReset =3D=3D 0) { + Readback |=3D B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS; + } + + if (PcdGetBool (PcdOcEnableWdtforDebug) =3D=3D FALSE) { + /// + /// WDT will not be turned on. This is to prevent platform reboots tri= ggered + /// by WDT expiration, which can be expected when processor is halted = for debugging + /// + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_EN | B_ACPI_IO_OC_WDT_CTL_FORCE_A= LL | B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS); + DEBUG ((DEBUG_INFO, "(Wdt) Wdt disabled in Debug BIOS\n")); + } + + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_TOV_MASK); + Readback |=3D ((TimeoutValue - 1) & B_ACPI_IO_OC_WDT_CTL_TOV_MASK); + IoWrite32 (WdtGetAddress (), Readback); + Readback |=3D B_ACPI_IO_OC_WDT_CTL_RLD; + IoWrite32 (WdtGetAddress (), Readback); + return EFI_SUCCESS; +} + +/** + Disables WDT timer. + + +**/ +VOID +EFIAPI +WdtDisable ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) DisableTimer\n")); + + Readback =3D IoRead32 (WdtGetAddress ()); + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_EN | B_ACPI_IO_OC_WDT_CTL_FORCE_ALL= | B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS); + IoWrite32 (WdtGetAddress (), Readback); +} + +/** + Returns WDT failure status. + + + @retval V_ACPI_IO_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiratio= n or unexpected reset + @retval V_ACPI_IO_OC_WDT_CTL_STATUS_OK Otherwise +**/ +UINT8 +EFIAPI +WdtCheckStatus ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) CheckTimerStatus\n")); + + Readback =3D IoRead32 (WdtGetAddress ()); + + DEBUG ((DEBUG_INFO, "(Wdt) Readback =3D (%x)\n", Readback)); + + if (Readback & B_ACPI_IO_OC_WDT_CTL_FAILURE_STS) { + DEBUG ((DEBUG_INFO, "(Wdt) Status =3D FAILURE\n")); + return V_ACPI_IO_OC_WDT_CTL_STATUS_FAILURE; + } else { + return V_ACPI_IO_OC_WDT_CTL_STATUS_OK; + } +} + +/** + Normally, each reboot performed while watchdog runs is considered a fail= ure. + This function allows platform to perform expected reboots with WDT runni= ng, + without being interpreted as failures. + In DXE phase, it is enough to call this function any time before reset. + In PEI phase, between calling this function and performing reset, Reload= AndStart() + must not be called. + + +**/ +VOID +EFIAPI +WdtAllowKnownReset ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) AllowKnownReset\n")); + + mAllowExpectedReset =3D 1; + + Readback =3D IoRead32 (WdtGetAddress ()); + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS | B_ACPI_IO_OC_WDT_C= TL_FORCE_ALL); + IoWrite32 (WdtGetAddress (), Readback); +} + +/** + Returns information if WDT coverage for the duration of BIOS execution + was requested by an OS application + + + @retval TRUE if WDT was requested + @retval FALSE if WDT was not requested +**/ +UINT8 +EFIAPI +IsWdtRequired ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtRequired")); + + Readback =3D IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_AFTER_POST) !=3D 0) { + DEBUG ((DEBUG_INFO, " - yes\n")); + return TRUE; + } else { + DEBUG ((DEBUG_INFO, " - no\n")); + return FALSE; + } + +} + +/** + Returns WDT enabled/disabled status. + + + @retval TRUE if WDT is enabled + @retval FALSE if WDT is disabled +**/ +UINT8 +EFIAPI +IsWdtEnabled ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtEnabled")); + + Readback =3D IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_EN) !=3D 0) { + DEBUG ((DEBUG_INFO, " - yes\n")); + return TRUE; + } else { + DEBUG ((DEBUG_INFO, " - no\n")); + return FALSE; + } + +} + +/** + Returns WDT locked status. + + + @retval TRUE if WDT is locked + @retval FALSE if WDT is unlocked +**/ +UINT8 +EFIAPI +IsWdtLocked ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtLocked")); + + Readback =3D IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_LCK) !=3D 0) { + DEBUG ((DEBUG_INFO, " - yes\n")); + return TRUE; + } else { + DEBUG ((DEBUG_INFO, " - no\n")); + return FALSE; + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib= /PmcLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/= PmcLib.c new file mode 100644 index 0000000000..8e026b3ab6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib= .c @@ -0,0 +1,330 @@ +/** @file + PCH PMC Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Get PCH ACPI base address. + + @retval Address Address of PWRM base address. +**/ +UINT16 +PmcGetAcpiBase ( + VOID + ) +{ + return PcdGet16 (PcdAcpiBaseAddress); +} + +/** + Get PCH PWRM base address. + + @retval Address Address of PWRM base address. +**/ +UINT32 +PmcGetPwrmBase ( + VOID + ) +{ + return PCH_PWRM_BASE_ADDRESS; +} + +/** + This function enables Power Button SMI +**/ +VOID +PmcEnablePowerButtonSmi ( + VOID + ) +{ + IoOr16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN, B_ACPI_IO_PM1_EN_PWRBTN); +} + +/** + This function disables Power Button SMI +**/ +VOID +PmcDisablePowerButtonSmi ( + VOID + ) +{ + IoAnd16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN, (UINT16)~B_ACPI_IO_PM1_EN= _PWRBTN); +} + +/** + This function reads PM Timer Count driven by 3.579545 MHz clock + + @retval PM Timer Count +**/ +UINT32 +PmcGetTimerCount ( + VOID + ) +{ + return IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_PM1_TMR) & B_ACPI_IO_PM1_= TMR_VAL; +} + +/** + Get Sleep Type that platform has waken from + + @retval SleepType Sleep Type +**/ +PMC_SLEEP_STATE +PmcGetSleepTypeAfterWake ( + VOID + ) +{ + UINT16 AcpiBase; + UINT32 PmconA; + + AcpiBase =3D PmcGetAcpiBase (); + PmconA =3D MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A); + + DEBUG ((DEBUG_INFO, "PWRM_PMCON_A =3D 0x%x\n", PmconA)); + + // + // If Global Reset Status, Power Failure. Host Reset Status bits are set= , return S5 State + // + if ((PmconA & (B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS | B_PMC_PWRM_GEN_PMCON= _A_PWR_FLR | B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS)) !=3D 0) { + return PmcNotASleepState; + } + + if (IoRead16 (AcpiBase + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_WAK) { + switch (IoRead16 (AcpiBase + R_ACPI_IO_PM1_CNT) & B_ACPI_IO_PM1_CNT_SL= P_TYP) { + case V_ACPI_IO_PM1_CNT_S0: + return PmcInS0State; + + case V_ACPI_IO_PM1_CNT_S1: + return PmcS1SleepState; + + case V_ACPI_IO_PM1_CNT_S3: + return PmcS3SleepState; + + case V_ACPI_IO_PM1_CNT_S4: + return PmcS4SleepState; + + case V_ACPI_IO_PM1_CNT_S5: + return PmcS5SleepState; + + default: + ASSERT (FALSE); + return PmcUndefinedState; + } + } else { + return PmcNotASleepState; + } +} + +/** + Clear PMC Wake Status +**/ +VOID +PmcClearWakeStatus ( + VOID + ) +{ + IoWrite16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_WAK)= ; +} + +/** + Check if platform boots after shutdown caused by power button override e= vent + + @retval TRUE Power Button Override occurred in last system boot + @retval FALSE Power Button Override didn't occur +**/ +BOOLEAN +PmcIsPowerButtonOverrideDetected ( + VOID + ) +{ + return ((IoRead16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM= 1_STS_PRBTNOR) !=3D 0); +} + +/** + This function checks if RTC Power Failure occurred by + reading RTC_PWR_FLR bit + + @retval RTC Power Failure state: TRUE - Battery is always present. + FALSE - CMOS is cleared. +**/ +BOOLEAN +PmcIsRtcBatteryGood ( + VOID + ) +{ + return ((MmioRead8 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B) & B_PMC_= PWRM_GEN_PMCON_B_RTC_PWR_STS) =3D=3D 0); +} + +/** + This function checks if Power Failure occurred by + reading PWR_FLR bit + + @retval Power Failure state +**/ +BOOLEAN +PmcIsPowerFailureDetected ( + VOID + ) +{ + return ((MmioRead16 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A) & B_PMC= _PWRM_GEN_PMCON_A_PWR_FLR) !=3D 0); +} + +/** + This function checks if RTC Power Failure occurred by + reading SUS_PWR_FLR bit + + @retval SUS Power Failure state +**/ +BOOLEAN +PmcIsSusPowerFailureDetected ( + VOID + ) +{ + return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B) & B_PMC= _PWRM_GEN_PMCON_A_SUS_PWR_FLR) !=3D 0); +} + +/** + This function clears Power Failure status (PWR_FLR) +**/ +VOID +PmcClearPowerFailureStatus ( + VOID + ) +{ + // + // Write 1 to clear PWR_FLR + // Avoid clearing other W1C bits + // + MmioAndThenOr8 ( + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1, + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8), + B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8 + ); +} + +/** + This function clears Global Reset status (GBL_RST_STS) +**/ +VOID +PmcClearGlobalResetStatus ( + VOID + ) +{ + // + // Write 1 to clear GBL_RST_STS + // Avoid clearing other W1C bits + // + MmioAndThenOr8 ( + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 3, + (UINT8) ~0, + B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS >> 24 + ); +} + +/** + This function clears Host Reset status (HOST_RST_STS) +**/ +VOID +PmcClearHostResetStatus ( + VOID + ) +{ + // + // Write 1 to clear HOST_RST_STS + // Avoid clearing other W1C bits + // + MmioAndThenOr8 ( + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1, + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8), + B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8 + ); +} + +/** + This function clears SUS Power Failure status (SUS_PWR_FLR) +**/ +VOID +PmcClearSusPowerFailureStatus ( + VOID + ) +{ + // + // BIOS clears this bit by writing a '1' to it. + // Take care of other fields, so we don't clear them accidentally. + // + MmioAndThenOr8 ( + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 2, + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_MS4V >> 16), + B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR >> 16 + ); +} + +/** + This function sets state to which platform will get after power is reapp= lied + + @param[in] PowerStateAfterG3 0: S0 state (boot) + 1: S5/S4 State +**/ +VOID +PmcSetPlatformStateAfterPowerFailure ( + IN UINT8 PowerStateAfterG3 + ) +{ + UINT32 PchPwrmBase; + + PchPwrmBase =3D PmcGetPwrmBase (); + + if (PowerStateAfterG3) { + MmioOr8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A, B_PMC_PWRM_GEN_PMCON_A_= AFTERG3_EN); + } else { + MmioAnd8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A, (UINT8)~B_PMC_PWRM_GEN= _PMCON_A_AFTERG3_EN); + } +} + +/** + This function checks if SMI Lock is set + + @retval SMI Lock state +**/ +BOOLEAN +PmcIsSmiLockSet ( + VOID + ) +{ + return ((MmioRead8 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B)= ) & B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK) !=3D 0); +} + +/** + Check global SMI enable is set + + @retval TRUE Global SMI enable is set + FALSE Global SMI enable is not set +**/ +BOOLEAN +PmcIsGblSmiEn ( + VOID + ) +{ + return !!(IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_SMI_EN) & B_ACPI_IO_SM= I_EN_GBL_SMI); +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLi= b/SataLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataL= ib/SataLib.c new file mode 100644 index 0000000000..05557931c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataL= ib.c @@ -0,0 +1,41 @@ +/** @file + Pch SATA library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +/** + Get SATA controller address that can be passed to the PCI Segment Librar= y functions. + + @param[in] SataCtrlIndex SATA controller index + + @retval SATA controller address in PCI Segment Library representation +**/ +UINT64 +GetSataRegBase ( + IN UINT32 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + return PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + GetSataPcieDeviceNum (SataCtrlIndex), + GetSataPcieFunctionNum (SataCtrlIndex), + 0 + ); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLi= b/SataLibCdf.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSa= taLib/SataLibCdf.c new file mode 100644 index 0000000000..5cec818dd6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataL= ibCdf.c @@ -0,0 +1,101 @@ +/** @file + Pch SATA library for CedarFork SouthCluster. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +/** + Get Maximum Sata Controller Number + + @param[in] None + + @retval Maximum Sata Controller Number +**/ +UINT8 +GetPchMaxSataControllerNum ( + VOID + ) +{ + return 3; +} + +/** + Get Pch Maximum Sata Port Number + + @param[in] SataCtrlIndex SATA controller index + + @retval Pch Maximum Sata Port Number +**/ +UINT8 +GetPchMaxSataPortNum ( + IN UINT8 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + return 8; +} + +/** + Get SATA controller PCIe Device Number + + @param[in] SataCtrlIndex SATA controller index + + @retval SATA controller PCIe Device Number +**/ +UINT8 +GetSataPcieDeviceNum ( + IN UINT8 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + if (SataCtrlIndex =3D=3D SATA_1_CONTROLLER_INDEX) { + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_1; + } else if (SataCtrlIndex =3D=3D SATA_2_CONTROLLER_INDEX) { + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_2; + } else if (SataCtrlIndex =3D=3D SATA_3_CONTROLLER_INDEX) { + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_3; + } else { + ASSERT (FALSE); + return 0; + } +} + +/** + Get SATA controller PCIe Function Number + + @param[in] SataCtrlIndex SATA controller index + + @retval SATA controller PCIe Function Number +**/ +UINT8 +GetSataPcieFunctionNum ( + IN UINT8 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + if (SataCtrlIndex =3D=3D SATA_1_CONTROLLER_INDEX) { + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_1; + } else if (SataCtrlIndex =3D=3D SATA_2_CONTROLLER_INDEX) { + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_2; + } else if (SataCtrlIndex =3D=3D SATA_3_CONTROLLER_INDEX) { + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_3; + } else { + ASSERT (FALSE); + return 0; + } +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLi= b/SataLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSa= taLib/SataLibCnl.c new file mode 100644 index 0000000000..0eca692a74 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataL= ibCnl.c @@ -0,0 +1,88 @@ +/** @file + Pch SATA library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +/** + Get Maximum Sata Controller Number + + @param[in] None + + @retval Maximum Sata Controller Number +**/ +UINT8 +GetPchMaxSataControllerNum ( + VOID + ) +{ + return 1; +} + +/** + Get Pch Maximum Sata Port Number + + @param[in] SataCtrlIndex SATA controller index + + @retval Pch Maximum Sata Port Number +**/ +UINT8 +GetPchMaxSataPortNum ( + IN UINT32 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + if (IsPchLp ()) { + return 3; + } else { + return 8; + } +} + +/** + Get SATA controller PCIe Device Number + + @param[in] SataCtrlIndex SATA controller index + + @retval SATA controller PCIe Device Number +**/ +UINT8 +GetSataPcieDeviceNum ( + IN UINT32 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + return PCI_DEVICE_NUMBER_PCH_SATA; +} + +/** + Get SATA controller PCIe Function Number + + @param[in] SataCtrlIndex SATA controller index + + @retval SATA controller PCIe Function Number +**/ +UINT8 +GetSataPcieFunctionNum ( + IN UINT32 SataCtrlIndex + ) +{ + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + return PCI_FUNCTION_NUMBER_PCH_SATA; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/Pei= OcWdtLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/Pei= OcWdtLib.c new file mode 100644 index 0000000000..22f6fb215f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLi= b.c @@ -0,0 +1,130 @@ +/** @file + The PEI Library Implements OcWdt Support. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +static WDT_PPI mWdtPpi =3D { + WdtReloadAndStart, + WdtCheckStatus, + WdtDisable, + WdtAllowKnownReset, + IsWdtRequired, + IsWdtEnabled +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallWdtPpi =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gWdtPpiGuid, + &mWdtPpi +}; + +/** + Reads PCH registers to check if platform wakes from S3/S4 + + @retval TRUE if platfrom wakes from S3/S4 + @retval FALSE otherwise +**/ +BOOLEAN +IsWakeFromS3S4 ( + VOID + ) +{ + PMC_SLEEP_STATE SleepType; + + SleepType =3D PmcGetSleepTypeAfterWake (); + if ((SleepType =3D=3D PmcS3SleepState) || (SleepType =3D=3D PmcS4SleepSt= ate)) { + return TRUE; + } + + return FALSE; + +} + +/** + Check for unexpected reset. + If there was an unexpected reset, enforces WDT expiration. +**/ +VOID +OcWdtResetCheck ( + VOID + ) +{ + UINT32 Readback; + + Readback =3D IoRead32 (WdtGetAddress ()); + DEBUG ((DEBUG_INFO, "(WDT) OcWdtResetCheck()\n")); + + /// + /// If there was a WDT expiration, set Failure Status and clear timeout = status bits + /// Timeout status bits are cleared by writing '1' + /// + if (Readback & (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT_CTL_= NO_ICCSURV_STS)) { + DEBUG ((DEBUG_ERROR, "(WDT) Expiration detected.\n", Readback)); + Readback |=3D B_ACPI_IO_OC_WDT_CTL_FAILURE_STS; + Readback |=3D (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT_CTL= _NO_ICCSURV_STS); + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS); + } else { + /// + /// If there was unexpected reset but no WDT expiration and no resume = from S3/S4, + /// clear unexpected reset status and enforce expiration. This is to i= nform Firmware + /// which has no access to unexpected reset status bit, that something= went wrong. + /// + if ((Readback & B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS) && !IsWakeFromS3S= 4()) { + if (PcdGetBool (PcdOcEnableWdtforDebug)) { + DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected and ignored.= \n")); + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS | B_ACPI_IO_OC_WD= T_CTL_UNXP_RESET_STS); + Readback |=3D (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT= _CTL_NO_ICCSURV_STS); + } else { + DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected. Enforcing W= dt expiration.\n")); + WdtReloadAndStart (1); + /// + /// wait for reboot caused by WDT expiration + /// + CpuDeadLoop (); + } + } else { + /// + /// No WDT expiration and no unexpected reset - clear Failure status + /// + DEBUG ((DEBUG_INFO, "(WDT) Status OK.\n", Readback)); + Readback &=3D ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS); + Readback |=3D (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT_C= TL_NO_ICCSURV_STS); + } + } + + IoWrite32 (WdtGetAddress (), Readback); + + return; +} + +/** + This function install WDT PPI + + @retval EFI_STATUS Results of the installation of the WDT PPI +**/ +EFI_STATUS +EFIAPI +OcWdtInit ( + VOID + ) +{ + EFI_STATUS Status; + + Status =3D PeiServicesInstallPpi (&mInstallWdtPpi); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull= /PeiOcWdtLibNull.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWd= tLibNull/PeiOcWdtLibNull.c new file mode 100644 index 0000000000..182218ffcf --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcW= dtLibNull.c @@ -0,0 +1,23 @@ +/** @file + The Null PEI Library Implements OcWdt Support. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +/** + This function install WDT PPI + + @retval EFI_STATUS Results of the installation of the WDT PPI +**/ +EFI_STATUS +EFIAPI +OcWdtInit ( + VOID + ) +{ + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PchPreMemPrintPolicy.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pe= iPchPolicyLib/PchPreMemPrintPolicy.c new file mode 100644 index 0000000000..bd1e2711da --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPre= MemPrintPolicy.c @@ -0,0 +1,307 @@ +/** @file + Print whole PCH_PREMEM_POLICY_PPI + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PeiPchPolicyLibrary.h" + +/** + Print PCH_GENERAL_PREMEM_CONFIG and serial out. + + @param[in] PchGeneralPreMemConfig Pointer to a PCH_GENERAL_PREMEM_CO= NFIG that provides the platform setting + +**/ +VOID +PchPrintGeneralPreMemConfig ( + IN CONST PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH General PreMem Config ------= ------------\n")); + DEBUG ((DEBUG_INFO, " Port80Route=3D %x\n", PchGeneralPreMemConfig->Port= 80Route)); +} + +/** + Print PCH_DCI_PREMEM_CONFIG and serial out. + + @param[in] DciPreMemConfig Pointer to a PCH_DCI_PREMEM_CONFIG= that provides the platform setting + +**/ +VOID +PchPrintDciPreMemConfig ( + IN CONST PCH_DCI_PREMEM_CONFIG *DciPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH DCI PreMem Config ----------= --------\n")); + DEBUG ((DEBUG_INFO, "PlatformDebugConsent =3D %x\n", DciPreMemConfig->Pl= atformDebugConsent)); + DEBUG ((DEBUG_INFO, "DciUsb3TypecUfpDbg =3D %x\n", DciPreMemConfig->DciU= sb3TypecUfpDbg)); +} + +/** + Print PCH_WDT_PREMEM_CONFIG and serial out. + + @param[in] WdtPreMemConfig Pointer to a PCH_WDT_PREMEM_CONFIG= that provides the platform setting + +**/ +VOID +PchPrintWdtPreMemConfig ( + IN CONST PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH WDT PreMem Config ----------= --------\n")); + DEBUG ((DEBUG_INFO, "DisableAndLock=3D %x\n", WdtPreMemConfig->DisableAn= dLock)); +} + +/** + Print PCH_TRACE_HUB_CONFIG and serial out. + + @param[in] TraceHubConfig Pointer to a PCH_TRACE_HUB_CONFIG = that provides the platform setting + +**/ +VOID +PchPrintTraceHubPreMemConfig ( + IN CONST PCH_TRACE_HUB_PREMEM_CONFIG *PchTraceHubPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH TraceHub PreMem Config -----= -------------\n")); + DEBUG ((DEBUG_INFO, "EnableMode=3D %x\n", PchTraceHubPreMemConfig->Enabl= eMode)); + DEBUG ((DEBUG_INFO, "MemReg0Size=3D %x\n", PchTraceHubPreMemConfig->MemR= eg0Size)); + DEBUG ((DEBUG_INFO, "MemReg1Size=3D %x\n", PchTraceHubPreMemConfig->MemR= eg1Size)); +} + +/** + Print PCH_SMBUS_CONFIG and serial out. + + @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that provid= es the platform setting + +**/ +VOID +PchPrintSmbusPreMemConfig ( + IN CONST PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH SMBUS PreMem Config --------= ----------\n")); + DEBUG ((DEBUG_INFO, " Enable=3D %x\n", SmbusPreMemConfig->Enable)); + DEBUG ((DEBUG_INFO, " ArpEnable=3D %x\n", SmbusPreMemConfig->ArpEnable))= ; + DEBUG ((DEBUG_INFO, " DynamicPowerGating=3D %x\n", SmbusPreMemConfig->Dy= namicPowerGating)); + DEBUG ((DEBUG_INFO, " SpdWriteDisable=3D %x\n", SmbusPreMemConfig->SpdWr= iteDisable)); + DEBUG ((DEBUG_INFO, " SmbAlertEnable=3D %x\n", SmbusPreMemConfig->SmbAle= rtEnable)); + DEBUG ((DEBUG_INFO, " SmbusIoBase=3D %x\n", SmbusPreMemConfig->SmbusIoBa= se)); + DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses=3D %x\n", SmbusPreMemConfig-= >NumRsvdSmbusAddresses)); + DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable=3D {")); + for (Index =3D 0; Index < SmbusPreMemConfig->NumRsvdSmbusAddresses; ++In= dex) { + DEBUG ((DEBUG_INFO, " %02xh", SmbusPreMemConfig->RsvdSmbusAddressTable= [Index])); + } + DEBUG ((DEBUG_INFO, " }\n")); +} + +/** + Print PCH_LPC_PREMEM_CONFIG and serial out. + + @param[in] LpcPreMemConfig Pointer to a PCH_LPC_PREMEM_= CONFIG that provides the platform setting + +**/ +VOID +PchPrintLpcPreMemConfig ( + IN CONST PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH LPC PreMem Config ----------= --------\n")); + DEBUG ((DEBUG_INFO, "EnhancePort8xhDecoding=3D %x\n", LpcPreMemConfig->E= nhancePort8xhDecoding)); +} + +/** + Print PCH_HSIO_PCIE_PREMEM_CONFIG and serial out. + + @param[in] HsioPciePreMemConfig Pointer to a PCH_HSIO_PCIE_PREMEM_CO= NFIG that provides the platform setting + +**/ +VOID +PchPrintHsioPciePreMemConfig ( + IN CONST PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ HSIO PCIE PreMem Config --------= ----------\n")); + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtleEnable=3D %x\n", Index= , HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtle=3D %x\n", Index, Hsio= PciePreMemConfig->Lane[Index].HsioRxSetCtle)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmpEnable=3D %x\= n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable))= ; + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmp=3D %x\n", In= dex, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmpEnable=3D %x\= n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable))= ; + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmp=3D %x\n", In= dex, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmpEnable=3D %x\= n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable))= ; + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmp=3D %x\n", In= dex, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmphEnable=3D %x\n", In= dex, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmph=3D %x\n", Index, H= sioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5Enable=3D %x\n",= Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5=3D %x\n", Index= , HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0Enable=3D %x\n",= Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0=3D %x\n", Index= , HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0)); + } +} + +/** + Print PCH_HSIO_SATA_PREMEM_CONFIG and serial out. + + @param[in] SataCtrlIndex SATA controller index + @param[in] HsioSataPreMemConfig Pointer to a PCH_HSIO_SATA_PREMEM_CO= NFIG that provides the platform setting +**/ +VOID +PchPrintHsioSataPreMemConfig ( + IN UINT8 SataCtrlIndex, + IN CONST PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "---------------- HSIO SATA PreMem Config for contro= ller %d ----------------\n", SataCtrlIndex)); + for (Index =3D 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++)= { + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMagEnable=3D %= x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnab= le)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag=3D %x\n", = Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMagEnable=3D %= x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnab= le)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag=3D %x\n", = Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMagEnable=3D %= x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnab= le)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag=3D %x\n", = Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmpEnable=3D= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp= Enable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmpEnable=3D= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp= Enable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmpEnable=3D= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp= Enable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph=3D %x\n", Inde= x, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph=3D %x\n", Inde= x, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable=3D %x\n"= , Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph=3D %x\n", Inde= x, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph)); + } +} + +/** + Print PCH_PCIE_RP_PREMEM_CONFIG and serial out. + + @param[in] PcieRpPreMemConfig Pointer to a PCH_PCIE_RP_PREMEM_CON= FIG that provides the platform setting + +**/ +VOID +PchPrintPcieRpPreMemConfig ( + IN CONST PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig + ) +{ + UINT32 Index; + DEBUG ((DEBUG_INFO, "------------------ PCH PCIe RP PreMem Config ------= ------------\n")); + + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " Port[%d] RpEnabled=3D %x\n", Index, (PcieRpPreMe= mConfig->RpEnabledMask & (UINT32) (1 << Index)) !=3D 0 )); + } + DEBUG ((DEBUG_INFO, " PcieImrEnabled=3D %x\n", PcieRpPreMemConfig->PcieI= mrEnabled)); + DEBUG ((DEBUG_INFO, " PcieImrSize=3D %d MB\n", PcieRpPreMemConfig->PcieI= mrSize)); + DEBUG ((DEBUG_INFO, " ImrRpSelection=3D %d\n", PcieRpPreMemConfig->ImrRp= Selection)); +} + +/** + Print PCH_HDAUDIO_PREMEM_CONFIG and serial out. + + @param[in] LpcPreMemConfig Pointer to a PCH_HDAUDIO_PRE= MEM_CONFIG that provides the platform setting + +**/ +VOID +PchPrintHdAudioPreMemConfig ( + IN CONST PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ HD Audio PreMem Config ---------= ---------\n")); + DEBUG ((DEBUG_INFO, " Enable=3D %x\n", HdaPreMemConfig->Enable)); +} + +/** + Print PCH_ISH_PREMEM_CONFIG and serial out. + + @param[in] IshPreMemConfig Pointer to a PCH_ISH_PREMEM_= CONFIG that provides the platform setting + +**/ +VOID +PchPrintIshPreMemConfig ( + IN CONST PCH_ISH_PREMEM_CONFIG *IshPreMemConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ ISH PreMem Config --------------= ----\n")); + DEBUG ((DEBUG_INFO, " Enable=3D %x\n", IshPreMemConfig->Enable)); +} + + +/** + Print whole PCH_POLICY_PPI and serial out. + + @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance + +**/ +VOID +EFIAPI +PchPreMemPrintPolicyPpi ( + IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi + ) +{ + DEBUG_CODE_BEGIN (); + EFI_STATUS Status; + PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig; + PCH_DCI_PREMEM_CONFIG *DciPreMemConfig; + PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig; + PCH_TRACE_HUB_PREMEM_CONFIG *PchTraceHubPreMemConfig; + PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig; + PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig; + PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig; + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig; + PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig; + PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig; + PCH_ISH_PREMEM_CONFIG *IshPreMemConfig; + UINT8 SataCtrlIndex; + + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchGeneralPreMe= mConfigGuid, (VOID *) &PchGeneralPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gDciPreMemConfig= Guid, (VOID *) &DciPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gWatchDogPreMemC= onfigGuid, (VOID *) &WdtPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchTraceHubPreM= emConfigGuid, (VOID *) &PchTraceHubPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSmbusPreMemConf= igGuid, (VOID *) &SmbusPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gLpcPreMemConfig= Guid, (VOID *) &LpcPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPciePreMemC= onfigGuid, (VOID *) &HsioPciePreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPcieRpPreMemCon= figGuid, (VOID *) &PcieRpPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHdAudioPreMemCo= nfigGuid, (VOID *) &HdaPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gIshPreMemConfig= Guid, (VOID *) &IshPreMemConfig); + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy Sta= rt ------------------------\n")); + DEBUG ((DEBUG_INFO, " Revision=3D %x\n", SiPreMemPolicyPpi->TableHeader.= Header.Revision)); + + PchPrintGeneralPreMemConfig (PchGeneralPreMemConfig); + PchPrintDciPreMemConfig (DciPreMemConfig); + PchPrintWdtPreMemConfig (WdtPreMemConfig); + PchPrintTraceHubPreMemConfig (PchTraceHubPreMemConfig); + PchPrintSmbusPreMemConfig (SmbusPreMemConfig); + PchPrintLpcPreMemConfig (LpcPreMemConfig); + PchPrintHsioPciePreMemConfig (HsioPciePreMemConfig); + for (SataCtrlIndex =3D 0; SataCtrlIndex < GetPchMaxSataControllerNum ();= SataCtrlIndex++) { + HsioSataPreMemConfig =3D GetPchHsioSataPreMemConfig (SiPreMemPolicyPpi= , SataCtrlIndex); + PchPrintHsioSataPreMemConfig (SataCtrlIndex, HsioSataPreMemConfig); + } + PchPrintPcieRpPreMemConfig (PcieRpPreMemConfig); + PchPrintHdAudioPreMemConfig (HdaPreMemConfig); + PchPrintIshPreMemConfig (IshPreMemConfig); + + DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy End= --------------------------\n")); + DEBUG_CODE_END (); +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PchPrintPolicy.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPo= licyLib/PchPrintPolicy.c new file mode 100644 index 0000000000..d9005b50ef --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPri= ntPolicy.c @@ -0,0 +1,778 @@ +/** @file + Print whole PCH_POLICY_PPI + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PeiPchPolicyLibrary.h" +#include + +/** + Print USB_CONFIG and serial out. + + @param[in] UsbConfig Pointer to a USB_CONFIG that provides the p= latform setting + +**/ +VOID +PchPrintUsbConfig ( + IN CONST USB_CONFIG *UsbConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH USB Config -----------------= -\n")); + DEBUG ((DEBUG_INFO, " EnableComplianceMode =3D %x\n", UsbConfi= g->EnableComplianceMode)); + DEBUG ((DEBUG_INFO, " PdoProgramming =3D %x\n", UsbConfi= g->PdoProgramming)); + DEBUG ((DEBUG_INFO, " OverCurrentEnable =3D %x\n", UsbConfi= g->OverCurrentEnable)); + DEBUG ((DEBUG_INFO, " XhciOcLock =3D %x\n", UsbConfi= g->XhciOcLock)); + DEBUG ((DEBUG_INFO, " Usb2PhySusPgEnable =3D %x\n", UsbConfi= g->Usb2PhySusPgEnable)); + + for (Index =3D 0; Index < GetPchUsb2MaxPhysicalPortNum (); Index++) { + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled =3D %x\n", Index, U= sbConfig->PortUsb20[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin =3D OC%x\n", Index,= UsbConfig->PortUsb20[Index].OverCurrentPin)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset =3D %x\n", Index, U= sbConfig->PortUsb20[Index].Afe.Petxiset)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset =3D %x\n", Index, U= sbConfig->PortUsb20[Index].Afe.Txiset)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp =3D %x\n", Index, U= sbConfig->PortUsb20[Index].Afe.Predeemp)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit =3D %x\n", Index, U= sbConfig->PortUsb20[Index].Afe.Pehalfbit)); + } + + for (Index =3D 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) { + DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled =3D %x\n"= , Index, UsbConfig->PortUsb30[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin =3D OC%x\= n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable =3D %x\n"= , Index, UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph =3D %x\n"= , Index, UsbConfig->PortUsb30[Index].HsioTxDeEmph)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable =3D %x\n"= , Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp =3D %x\n"= , Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp)); + + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfgEnable= =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffset= CfgEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfg = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffset= Cfg)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelNEnable = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelNEnabl= e)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelN = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelN)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelPEnable = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelPEnabl= e)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelP = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelP)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnResEnab= le =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpD= wnResEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnRes = =3D %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpD= wnRes)); + } + + DEBUG ((DEBUG_INFO, " XdciConfig.Enable=3D %x\n", UsbConfig->XdciConfig.= Enable)); + +} + +/** + Print PCH_PCIE_CONFIG and serial out. + + @param[in] PcieConfig Pointer to a PCH_PCIE_CONFIG that provides= the platform setting + +**/ +VOID +PchPrintPcieConfig ( + IN CONST PCH_PCIE_CONFIG *PcieConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config ----------------= --\n")); + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug=3D %x\n", Index, PcieConfig= ->RootPort[Index].HotPlug)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci=3D %x\n", Index, PcieConfig->= RootPort[Index].PmSci)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync=3D %x\n", Index, PcieConfig= ->RootPort[Index].ExtSync)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect=3D %x\n", Index, PcieC= onfig->RootPort[Index].ClkReqDetect)); + DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport=3D %x\n", = Index, PcieConfig->RootPort[Index].UnsupportedRequestReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport=3D %x\n", Index, P= cieConfig->RootPort[Index].FatalErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport=3D %x\n", Index,= PcieConfig->RootPort[Index].NoFatalErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport=3D %x\n", In= dex, PcieConfig->RootPort[Index].CorrectableErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError=3D %x\n", I= ndex, PcieConfig->RootPort[Index].SystemErrorOnFatalError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError=3D %x\n"= , Index, PcieConfig->RootPort[Index].SystemErrorOnNonFatalError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError=3D %x= \n", Index, PcieConfig->RootPort[Index].SystemErrorOnCorrectableError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload=3D %x\n", Index, PcieCon= fig->RootPort[Index].MaxPayload)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotImplemented=3D %x\n", Index, Pc= ieConfig->RootPort[Index].SlotImplemented)); + DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled=3D %x\n", Index, PcieCon= fig->RootPort[Index].AcsEnabled)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PtmEnabled=3D %x\n", Index, PcieCon= fig->RootPort[Index].PtmEnabled)); + DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting=3D %x\n", In= dex, PcieConfig->RootPort[Index].AdvancedErrorReporting)); + DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing=3D %x\n", Inde= x, PcieConfig->RootPort[Index].TransmitterHalfSwing)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed=3D %x\n", Index, PcieConf= ig->RootPort[Index].PcieSpeed)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method=3D %x\n", Index, Pc= ieConfig->RootPort[Index].Gen3EqPh3Method)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber=3D %x\n", Index,= PcieConfig->RootPort[Index].PhysicalSlotNumber)); + DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout=3D %x\n", Index, = PcieConfig->RootPort[Index].CompletionTimeout)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm=3D %x\n", Index, PcieConfig->R= ootPort[Index].Aspm)); + DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates=3D %x\n", Index, PcieCo= nfig->RootPort[Index].L1Substates)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable=3D %x\n", Index, PcieConf= ig->RootPort[Index].LtrEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock=3D %x\n", Index, Pcie= Config->RootPort[Index].LtrConfigLock)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency=3D %x\n", Index,= PcieConfig->RootPort[Index].LtrMaxSnoopLatency)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency=3D %x\n", Inde= x, PcieConfig->RootPort[Index].LtrMaxNoSnoopLatency)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode=3D %x\n", = Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMode)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier=3D %= x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMultiplier)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue=3D %x\n",= Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode=3D %x\n= ", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMode)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier= =3D %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMultip= lier)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue=3D %x\= n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ForceLtrOverride=3D %x\n", Index, P= cieConfig->RootPort[Index].ForceLtrOverride)); + DEBUG ((DEBUG_INFO, " RootPort[%d] DetectTimeoutMs=3D %x\n", Index, Pc= ieConfig->RootPort[Index].DetectTimeoutMs)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale=3D %x\n", Index= , PcieConfig->RootPort[Index].SlotPowerLimitScale)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue=3D %x\n", Index= , PcieConfig->RootPort[Index].SlotPowerLimitValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp=3D %x\n", Index, PcieConfig->R= ootPort[Index].Uptp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp=3D %x\n", Index, PcieConfig->R= ootPort[Index].Dptp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] EnableCpm=3D %x\n", Index, PcieConf= ig->RootPort[Index].EnableCpm)); + + } + for (Index =3D 0; Index < GetPchMaxPcieClockNum (); Index++) { + DEBUG ((DEBUG_INFO, " Clock[%d] Usage=3D %x\n", Index, PcieConfig->Pci= eClock[Index].Usage)); + DEBUG ((DEBUG_INFO, " Clock[%d] ClkReq=3D %x\n", Index, PcieConfig->Pc= ieClock[Index].ClkReq)); + } + for (Index =3D 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) { + DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] =3D %x\n", Index, PcieConfig->Sw= EqCoeffList[Index].Cm)); + DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] =3D %x\n", Index, PcieConfig->Sw= EqCoeffList[Index].Cp)); + } + DEBUG ((DEBUG_INFO, " EnablePort8xhDecode=3D %x\n", PcieConfig->EnablePo= rt8xhDecode)); + DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex=3D %x\n", PcieConfig= ->PchPciePort8xhDecodePortIndex)); + DEBUG ((DEBUG_INFO, " DisableRootPortClockGating=3D %x\n", PcieConfig->D= isableRootPortClockGating)); + DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite=3D %x\n", PcieConfig->Enable= PeerMemoryWrite)); + DEBUG ((DEBUG_INFO, " ComplianceTestMode=3D %x\n", PcieConfig->Complianc= eTestMode)); + DEBUG ((DEBUG_INFO, " RpFunctionSwap=3D %x\n", PcieConfig->RpFunctionSwa= p)); + DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr=3D %x\n", PcieConfig->P= cieDeviceOverrideTablePtr)); +} + +/** + Print PCH_SATA_CONFIG and serial out. + + @param[in] SataCtrlIndex SATA controller index + @param[in] SataConfig Pointer to a PCH_SATA_CONFIG that provides= the platform setting + +**/ +VOID +PchPrintSataConfig ( + IN UINT32 SataCtrlIndex, + IN CONST PCH_SATA_CONFIG *SataConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "--------------- PCH SATA Config for controller %d -= ----------\n", SataCtrlIndex)); + DEBUG ((DEBUG_INFO, " Enable=3D %x\n", SataConfig->Enable)); + DEBUG ((DEBUG_INFO, " SataMode=3D %x\n", SataConfig->SataMode)); + + for (Index =3D 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++)= { + DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled=3D %x\n", Index, SataCo= nfig->PortSettings[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug=3D %x\n", Index, SataCo= nfig->PortSettings[Index].HotPlug)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw=3D %x\n", Index, Sa= taConfig->PortSettings[Index].InterlockSw)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] External=3D %x\n", Index, SataC= onfig->PortSettings[Index].External)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp=3D %x\n", Index, SataCon= fig->PortSettings[Index].SpinUp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive=3D %x\n", Index= , SataConfig->PortSettings[Index].SolidStateDrive)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp=3D %x\n", Index, SataCon= fig->PortSettings[Index].DevSlp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig=3D %x\n", Inde= x, SataConfig->PortSettings[Index].EnableDitoConfig)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal=3D %x\n", Index, SataConf= ig->PortSettings[Index].DmVal)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal=3D %x\n", Index, SataCo= nfig->PortSettings[Index].DitoVal)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd=3D %x\n", Index, SataConf= ig->PortSettings[Index].ZpOdd)); + } + + DEBUG ((DEBUG_INFO, " RaidDeviceId=3D %x\n", SataConfig->Rst.RaidDeviceI= d)); + DEBUG ((DEBUG_INFO, " Sata interrupt mode =3D %x\n", SataConfig->Rst.Sa= taRstInterrupt)); + DEBUG ((DEBUG_INFO, " Raid0=3D %x\n", SataConfig->Rst.Raid0)); + DEBUG ((DEBUG_INFO, " Raid1=3D %x\n", SataConfig->Rst.Raid1)); + DEBUG ((DEBUG_INFO, " Raid10=3D %x\n", SataConfig->Rst.Raid10)); + DEBUG ((DEBUG_INFO, " Raid5=3D %x\n", SataConfig->Rst.Raid5)); + DEBUG ((DEBUG_INFO, " Irrt=3D %x\n", SataConfig->Rst.Irrt)); + DEBUG ((DEBUG_INFO, " OromUiBanner=3D %x\n", SataConfig->Rst.OromUiBanne= r)); + DEBUG ((DEBUG_INFO, " OromUiDelay=3D %x\n", SataConfig->Rst.OromUiDelay)= ); + DEBUG ((DEBUG_INFO, " HddUnlock=3D %x\n", SataConfig->Rst.HddUnlock)); + DEBUG ((DEBUG_INFO, " LedLocate=3D %x\n", SataConfig->Rst.LedLocate)); + DEBUG ((DEBUG_INFO, " IrrtOnly=3D %x\n", SataConfig->Rst.IrrtOnly)); + DEBUG ((DEBUG_INFO, " SmartStorage=3D %x\n", SataConfig->Rst.SmartStorag= e)); + DEBUG ((DEBUG_INFO, " LegacyOrom=3D %x\n", SataConfig->Rst.LegacyOrom)); + DEBUG ((DEBUG_INFO, " OptaneMemory=3D %x\n", SataConfig->Rst.OptaneMemor= y)); + DEBUG ((DEBUG_INFO, " CpuAttachedStorage=3D %x\n", SataConfig->Rst.CpuAt= tachedStorage)); + + DEBUG ((DEBUG_INFO, " SpeedSupport=3D %x\n", SataConfig->SpeedLimit)); + DEBUG ((DEBUG_INFO, " EsataSpeedLimit=3D %x\n", SataConfig->EsataSpeedLi= mit)); + DEBUG ((DEBUG_INFO, " LedEnable=3D %x\n", SataConfig->LedEnable)); + DEBUG ((DEBUG_INFO, " TestMode=3D %x\n", SataConfig->TestMode)); + DEBUG ((DEBUG_INFO, " SalpSupport=3D %x\n", SataConfig->SalpSupport)); + DEBUG ((DEBUG_INFO, " PwrOptEnable=3D %x\n", SataConfig->PwrOptEnable)); + + for (Index =3D 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) { + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable = =3D %x\n", Index, SataConfig->RstPcieStorageRemap[Index].Enable)); + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort = =3D %x\n", Index, SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort= )); + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay = =3D %x\n", Index, SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay))= ; + } + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T1M %x\n", SataConfig->Thermal= Throttling.P0T1M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T2M %x\n", SataConfig->Thermal= Throttling.P0T2M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T3M %x\n", SataConfig->Thermal= Throttling.P0T3M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDisp %x\n", SataConfig->Therm= alThrottling.P0TDisp)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0Tinact %x\n", SataConfig->Ther= malThrottling.P0Tinact)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDispFinit %x\n", SataConfig->= ThermalThrottling.P0TDispFinit)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T1M %x\n", SataConfig->Thermal= Throttling.P1T1M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T2M %x\n", SataConfig->Thermal= Throttling.P1T2M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T3M %x\n", SataConfig->Thermal= Throttling.P1T3M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDisp %x\n", SataConfig->Therm= alThrottling.P1TDisp)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1Tinact %x\n", SataConfig->Ther= malThrottling.P1Tinact)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDispFinit %x\n", SataConfig->= ThermalThrottling.P1TDispFinit)); + DEBUG ((DEBUG_INFO, " ThermalThrottling SuggestedSetting %x\n", SataConf= ig->ThermalThrottling.SuggestedSetting)); +} + +/** + Print PCH_IOAPIC_CONFIG and serial out. + + @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that prov= ides the platform setting + +**/ +VOID +PchPrintIoApicConfig ( + IN CONST PCH_IOAPIC_CONFIG *IoApicConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config --------------= ----\n")); + DEBUG ((DEBUG_INFO, " IoApicEntry24_119=3D %x\n", IoApicConfig->IoApicEn= try24_119)); + DEBUG ((DEBUG_INFO, " Enable8254ClockGating=3D %x\n", IoApicConfig->Enab= le8254ClockGating)); + DEBUG ((DEBUG_INFO, " Enable8254ClockGatingOnS3=3D %x\n", IoApicConfig->= Enable8254ClockGatingOnS3)); + DEBUG ((DEBUG_INFO, " IoApicId=3D %x\n", IoApicConfig->IoApicId)); +} + +/** + Print PCH_LOCK_DOWN_CONFIG and serial out. + + @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG that= provides the platform setting + +**/ +VOID +PchPrintLockDownConfig ( + IN CONST PCH_LOCK_DOWN_CONFIG *LockDownConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH Lock Down Config -----------= -------\n")); + DEBUG ((DEBUG_INFO, " GlobalSmi=3D %x\n", LockDownConfig->GlobalSmi)); + DEBUG ((DEBUG_INFO, " BiosInterface=3D %x\n", LockDownConfig->BiosInterf= ace)); + DEBUG ((DEBUG_INFO, " RtcMemoryLock=3D %x\n", LockDownConfig->RtcMemoryL= ock)); + DEBUG ((DEBUG_INFO, " BiosLock=3D %x\n", LockDownConfig->BiosLock)); + DEBUG ((DEBUG_INFO, " UnlockGpioPads=3D %x\n", LockDownConfig->UnlockGpi= oPads)); +} + +/** + Print PCH_HDAUDIO_CONFIG and serial out. + + @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that provid= es the platform setting + +**/ +VOID +PchPrintHdAudioConfig ( + IN CONST PCH_HDAUDIO_CONFIG *HdaConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config ------------= ------\n")); + DEBUG ((DEBUG_INFO, " DSP Enable =3D %x\n", HdaConfig->Dsp= Enable)); + DEBUG ((DEBUG_INFO, " DSP UAA Compliance =3D %x\n", HdaConfig->Dsp= UaaCompliance)); + DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect =3D %x\n", HdaConfig->IDi= spCodecDisconnect)); + DEBUG ((DEBUG_INFO, " Pme =3D %x\n", HdaConfig->Pme= )); + DEBUG ((DEBUG_INFO, " Codec Sx Wake Capability =3D %x\n", HdaConfig->Cod= ecSxWakeCapability)); + DEBUG ((DEBUG_INFO, " VC Type =3D %x\n", HdaConfig->VcT= ype)); + DEBUG ((DEBUG_INFO, " HD-A Link Frequency =3D %x\n", HdaConfig->HdA= udioLinkFrequency)); + DEBUG ((DEBUG_INFO, " iDisp Link Frequency =3D %x\n", HdaConfig->IDi= spLinkFrequency)); + DEBUG ((DEBUG_INFO, " iDisp Link T-Mode =3D %x\n", HdaConfig->IDi= spLinkTmode)); + DEBUG ((DEBUG_INFO, " Audio Link: HDA Link =3D %x\n", HdaConfig->Aud= ioLinkHda)); + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#0 =3D %x\n", HdaConfig->Aud= ioLinkDmic0)); + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#1 =3D %x\n", HdaConfig->Aud= ioLinkDmic1)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#0 =3D %x\n", HdaConfig->Aud= ioLinkSsp0)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#1 =3D %x\n", HdaConfig->Aud= ioLinkSsp1)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#2 =3D %x\n", HdaConfig->Aud= ioLinkSsp1)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#1 =3D %x\n", HdaConfig->Aud= ioLinkSndw1)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#2 =3D %x\n", HdaConfig->Aud= ioLinkSndw2)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#3 =3D %x\n", HdaConfig->Aud= ioLinkSndw3)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#4 =3D %x\n", HdaConfig->Aud= ioLinkSndw4)); + DEBUG ((DEBUG_INFO, " SoundWire Buffer RCOMP =3D %x\n", HdaConfig->Snd= wBufferRcomp)); + DEBUG ((DEBUG_INFO, " ResetWaitTimer =3D %x\n", HdaConfig->Res= etWaitTimer)); + DEBUG ((DEBUG_INFO, " VerbTableEntryNum =3D %x\n", HdaConfig->Ver= bTableEntryNum)); + DEBUG ((DEBUG_INFO, " VerbTablePtr =3D %x\n", HdaConfig->Ver= bTablePtr)); +} + +/** + Print PCH_PM_CONFIG and serial out. + + @param[in] PmConfig Pointer to a PCH_PM_CONFIG that provides the= platform setting + +**/ +VOID +PchPrintPmConfig ( + IN CONST PCH_PM_CONFIG *PmConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH PM Config ------------------= \n")); + + DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis =3D %x\n", PmC= onfig->WakeConfig.PmeB0S5Dis)); + DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride =3D %x\n", PmC= onfig->WakeConfig.WolEnableOverride)); + DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx =3D %x\n", PmC= onfig->WakeConfig.LanWakeFromDeepSx)); + DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx =3D %x\n", PmC= onfig->WakeConfig.PcieWakeFromDeepSx)); + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable =3D %x\n", PmC= onfig->WakeConfig.WoWlanEnable)); + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable =3D %x\n", PmC= onfig->WakeConfig.WoWlanDeepSxEnable)); + + DEBUG ((DEBUG_INFO, " PchDeepSxPol =3D %x\n", PmC= onfig->PchDeepSxPol)); + DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert =3D %x\n", PmC= onfig->PchSlpS3MinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert =3D %x\n", PmC= onfig->PchSlpS4MinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert =3D %x\n", PmC= onfig->PchSlpSusMinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpAMinAssert =3D %x\n", PmC= onfig->PchSlpAMinAssert)); + DEBUG ((DEBUG_INFO, " LpcClockRun =3D %x\n", PmC= onfig->LpcClockRun)); + DEBUG ((DEBUG_INFO, " SlpStrchSusUp =3D %x\n", PmC= onfig->SlpStrchSusUp)); + DEBUG ((DEBUG_INFO, " SlpLanLowDc =3D %x\n", PmC= onfig->SlpLanLowDc)); + DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod =3D %x\n", PmC= onfig->PwrBtnOverridePeriod)); + DEBUG ((DEBUG_INFO, " DisableEnergyReport =3D %x\n", PmC= onfig->DisableEnergyReport)); + DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown =3D %x\n", PmC= onfig->DisableDsxAcPresentPulldown)); + DEBUG ((DEBUG_INFO, " PchPwrCycDur =3D %x\n", PmC= onfig->PchPwrCycDur)); + DEBUG ((DEBUG_INFO, " PciePllSsc =3D %x\n", PmC= onfig->PciePllSsc)); + DEBUG ((DEBUG_INFO, " DisableNativePowerButton =3D %x\n", PmC= onfig->DisableNativePowerButton)); + DEBUG ((DEBUG_INFO, " SlpS0Enabled =3D %x\n", PmC= onfig->SlpS0Enable)); + DEBUG ((DEBUG_INFO, " MeWakeSts =3D %x\n", PmC= onfig->MeWakeSts)); + DEBUG ((DEBUG_INFO, " WolOvrWkSts =3D %x\n", PmC= onfig->WolOvrWkSts)); + DEBUG ((DEBUG_INFO, " EnableTcoTimer =3D %x\n", PmC= onfig->EnableTcoTimer)); + DEBUG ((DEBUG_INFO, " VrAlert =3D %x\n", PmC= onfig->VrAlert)); + DEBUG ((DEBUG_INFO, " PowerButtonDebounce =3D %x\n", PmC= onfig->PowerButtonDebounce)); + DEBUG ((DEBUG_INFO, " SlpS0VmRuntimeControl =3D %x\n", PmC= onfig->SlpS0VmRuntimeControl)); + DEBUG ((DEBUG_INFO, " SlpS0Vm070VSupport =3D %x\n", PmC= onfig->SlpS0Vm070VSupport)); + DEBUG ((DEBUG_INFO, " SlpS0Vm075VSupport =3D %x\n", PmC= onfig->SlpS0Vm075VSupport)); + DEBUG ((DEBUG_INFO, " SlpS0Override =3D %x\n", PmC= onfig->SlpS0Override)); + DEBUG ((DEBUG_INFO, " SlpS0DisQForDebug =3D %x\n", PmC= onfig->SlpS0DisQForDebug)); + DEBUG ((DEBUG_INFO, " PsOnEnable =3D %x\n", PmC= onfig->PsOnEnable)); + DEBUG ((DEBUG_INFO, " CpuC10GatePinEnable =3D %x\n", PmC= onfig->CpuC10GatePinEnable)); + DEBUG ((DEBUG_INFO, " PmcDbgMsgEn =3D %x\n", PmC= onfig->PmcDbgMsgEn)); + DEBUG ((DEBUG_INFO, " ModPhySusPgEnable =3D %x\n", PmC= onfig->ModPhySusPgEnable)); + DEBUG ((DEBUG_INFO, " SlpS0WithGbeSupport =3D %x\n", PmC= onfig->SlpS0WithGbeSupport)); +} + +/** + Print PCH_DMI_CONFIG and serial out. + + @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides t= he platform setting + +**/ +VOID +PchPrintDmiConfig ( + IN CONST PCH_DMI_CONFIG *DmiConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config -----------------= -\n")); + DEBUG ((DEBUG_INFO, " PwrOptEnable=3D %x\n", DmiConfig->PwrOptEnable)); + DEBUG ((DEBUG_INFO, " DmiAspmCtrl=3D %x\n", DmiConfig->DmiAspmCtrl)); +} +/** + Print PCH_LPC_SIRQ_CONFIG and serial out. + + @param[in] SerialIrqConfig Pointer to a PCH_LPC_SIRQ_CONFIG that= provides the platform setting + +**/ +VOID +PchPrintSerialIrqConfig ( + IN CONST PCH_LPC_SIRQ_CONFIG *SerialIrqConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH LPC SIRQ Config ------------= ------\n")); + DEBUG ((DEBUG_INFO, " SirqEnable=3D %x\n", SerialIrqConfig->SirqEnable))= ; + DEBUG ((DEBUG_INFO, " SirqMode=3D %x\n", SerialIrqConfig->SirqMode)); + DEBUG ((DEBUG_INFO, " StartFramePulse=3D %x\n", SerialIrqConfig->StartFr= amePulse)); +} +/** + Print PCH_THERMAL_CONFIG and serial out. + + @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that pr= ovides the platform setting + +**/ +VOID +PchPrintThermalConfig ( + IN CONST PCH_THERMAL_CONFIG *ThermalConfig + ) +{ + UINTN Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config -------------= -----\n")); + DEBUG ((DEBUG_INFO, " TsmicLock=3D %x\n", ThermalConfig->TsmicLock)); + DEBUG ((DEBUG_INFO, " TTLevels T0Level %x centigrade degree\n", ThermalC= onfig->TTLevels.T0Level)); + DEBUG ((DEBUG_INFO, " TTLevels T1Level %x centigrade degree\n", ThermalC= onfig->TTLevels.T1Level)); + DEBUG ((DEBUG_INFO, " TTLevels T2Level %x centigrade degree\n", ThermalC= onfig->TTLevels.T2Level)); + DEBUG ((DEBUG_INFO, " TTLevels TTEnable %x\n", ThermalConfig->TTLevels.T= TEnable)); + DEBUG ((DEBUG_INFO, " TTLevels TTState13Enable %x\n", ThermalConfig->TTL= evels.TTState13Enable)); + DEBUG ((DEBUG_INFO, " TTLevels TTLock %x\n", ThermalConfig->TTLevels.TTL= ock)); + DEBUG ((DEBUG_INFO, " TTLevels SuggestedSetting %x\n", ThermalConfig->TT= Levels.SuggestedSetting)); + DEBUG ((DEBUG_INFO, " TTLevels PchCrossThrottling %x\n", ThermalConfig->= TTLevels.PchCrossThrottling)); + + DEBUG ((DEBUG_INFO, " DmiHaAWC DmiTsawEn %x\n", ThermalConfig->DmiHaAWC.= DmiTsawEn)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS0TW %x\n", ThermalConfig->DmiHaAWC.TS0T= W)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS1TW %x\n", ThermalConfig->DmiHaAWC.TS1T= W)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS2TW %x\n", ThermalConfig->DmiHaAWC.TS2T= W)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS3TW %x\n", ThermalConfig->DmiHaAWC.TS3T= W)); + DEBUG ((DEBUG_INFO, " DmiHaAWC SuggestedSetting %x\n", ThermalConfig->Dm= iHaAWC.SuggestedSetting)); + + DEBUG ((DEBUG_INFO, " MemoryThrottling Enable=3D %x\n", ThermalConfig->M= emoryThrottling.Enable)); + for (Index =3D 0; Index < MaxTsGpioPin; Index++) { + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PmsyncEnable= =3D %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PmsyncEn= able)); + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting C0TransmitEnab= le=3D %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].C0Tran= smitEnable)); + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PinSelection= =3D %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PinSelec= tion)); + } + DEBUG ((DEBUG_INFO, " PchHotEnable =3D %x\n", ThermalConfig->PchHotEnabl= e)); + DEBUG ((DEBUG_INFO, " PchHotLevel =3D %x\n", ThermalConfig->PchHotLevel)= ); +} + +/** + Print PCH_GENERAL_CONFIG and serial out. + + @param[in] PchGeneralConfig Pointer to a PCH_GENERAL_CONFIG that provi= des the platform setting + +**/ +VOID +PchPrintGeneralConfig ( + IN CONST PCH_GENERAL_CONFIG *PchGeneralConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH General Config -------------= -----\n")); + DEBUG ((DEBUG_INFO, " Crid=3D %x\n", PchGeneralConfig->Crid)); + DEBUG ((DEBUG_INFO, " LegacyIoLowLatency =3D %x\n", PchGeneralConfig->Le= gacyIoLowLatency)); +} + +/** + Print PCH_LAN_CONFIG and serial out. + + @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides t= he platform setting + +**/ +VOID +PchPrintLanConfig ( + IN CONST PCH_LAN_CONFIG *LanConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config -----------------= -\n")); + DEBUG ((DEBUG_INFO, " Enable=3D %x\n", LanConfig->Enable)); + DEBUG ((DEBUG_INFO, " LtrEnable=3D %x\n", LanConfig->LtrEnable)); +} + +/** + Print PCH_SERIAL_IO_CONFIG and serial out. + + @param[in] SerialIoConfig Pointer to a PCH_SERIAL_IO_CONFIG that= provides the platform setting + +**/ +VOID +PchPrintSerialIoConfig ( + IN CONST PCH_SERIAL_IO_CONFIG *SerialIoConfig + ) +{ + UINTN Index; +#ifndef MDEPKG_NDEBUG + static UINT8 DeviceName[PCH_MAX_SERIALIO_CONTROLLERS][5] =3D {"I2C0","I2= C1","I2C2","I2C3","I2C4","I2C5","SPI0","SPI1","SPI2","UA00","UA01","UA02"}; +#endif + + DEBUG ((DEBUG_INFO, "------------------ PCH Serial IO Config -----------= -------\n")); + DEBUG_CODE_BEGIN (); + for (Index =3D 0; Index < GetPchMaxSerialIoControllersNum (); Index++) { + DEBUG ((DEBUG_INFO, " SerialIoController %a: Mode 0x%x\n", DeviceName[= Index], SerialIoConfig->DevMode[Index])); + } + DEBUG_CODE_END (); + for (Index =3D 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++= ) { + DEBUG ((DEBUG_INFO, " SpiCsPolarity[%d] =3D 0x%x\n", Index, SerialIoCo= nfig->SpiCsPolarity[Index])); + } + for (Index =3D 0; Index < GetPchMaxSerialIoUartControllersNum (); Index+= +) { + DEBUG ((DEBUG_INFO, " UartHwFlowCtrl[%d] =3D 0x%x\n", Index, SerialIoC= onfig->UartHwFlowCtrl[Index])); + } + for (Index =3D 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index += +) { + DEBUG ((DEBUG_INFO, " I2cPadsTermination[%d] =3D 0x%x\n", Index, Seria= lIoConfig->I2cPadsTermination[Index])); + } + DEBUG ((DEBUG_INFO, " DebugUartNumber =3D 0x%x\n", SerialIoConfig->Debug= UartNumber)); + DEBUG ((DEBUG_INFO, " EnableDebugUartAfterPost =3D 0x%x\n", SerialIoConf= ig->EnableDebugUartAfterPost)); + DEBUG ((DEBUG_INFO, " Uart0PinMuxing =3D 0x%x\n", SerialIoConfig->Uart0P= inMuxing)); +} + +/** + Print PCH_INTERRUPT_CONFIG and serial out + + @param[in] InterruptConfig Pointer to Interrupt Configuration str= ucture + +**/ +VOID +PchPrintInterruptConfig ( + IN CONST PCH_INTERRUPT_CONFIG *InterruptConfig + ) +{ + UINTN Index; + // + // Print interrupt information + // + DEBUG ((DEBUG_INFO, "------------------ PCH Interrupt Config -----------= -------\n")); + DEBUG ((DEBUG_INFO, " Interrupt assignment:\n")); + DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n")); + for (Index =3D 0; Index < InterruptConfig->NumOfDevIntConfig; Index++) { + DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n", + InterruptConfig->DevIntConfig[Index].Device, + InterruptConfig->DevIntConfig[Index].Function, + InterruptConfig->DevIntConfig[Index].IntX, + InterruptConfig->DevIntConfig[Index].Irq)); + } + DEBUG ((DEBUG_INFO, " Legacy PIC interrupt routing:\n")); + DEBUG ((DEBUG_INFO, " PIRQx IRQx\n")); + for (Index =3D 0; Index < PCH_MAX_PXRC_CONFIG; Index++) { + DEBUG ((DEBUG_INFO, " PIRQ%c -> IRQ%d\n", Index + 65, InterruptConfig= ->PxRcConfig[Index])); + } + DEBUG ((DEBUG_INFO, " Other interrupt configuration:\n")); + DEBUG ((DEBUG_INFO, " GpioIrqRoute=3D %d\n", InterruptConfig->GpioIrqRo= ute)); + DEBUG ((DEBUG_INFO, " SciIrqSelect=3D %d\n", InterruptConfig->SciIrqSel= ect)); + DEBUG ((DEBUG_INFO, " TcoIrqEnable=3D %d\n", InterruptConfig->TcoIrqEna= ble)); + DEBUG ((DEBUG_INFO, " TcoIrqSelect=3D %d\n", InterruptConfig->TcoIrqSel= ect)); +} + +/** + Print PCH_SCS_CONFIG and serial out. + + @param[in] ScsConfig Pointer to a PCH_SCS_CONFIG that provides t= he platform setting + +**/ +VOID +PchPrintScsConfig ( + IN CONST PCH_SCS_CONFIG *ScsConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH SCS Config -----------------= -\n")); + DEBUG ((DEBUG_INFO, " ScsEmmcEnabled =3D %x\n", ScsConfig->ScsEmmcEnable= d)); + DEBUG ((DEBUG_INFO, " ScsSdcardEnabled =3D %x\n", ScsConfig->ScsSdcardEn= abled)); + DEBUG ((DEBUG_INFO, " SdCardPowerEnableActiveHigh =3D %x\n", ScsConfig->= SdCardPowerEnableActiveHigh)); + DEBUG ((DEBUG_INFO, " ScsUfsEnabled =3D %x\n", ScsConfig->ScsUfsEnabled)= ); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400Enabled =3D %x\n", ScsConfig->ScsEmmcH= s400Enabled)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TuningRequired =3D %x\n", ScsConfig->S= csEmmcHs400TuningRequired)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DllDataValid =3D %x\n", ScsConfig->Scs= EmmcHs400DllDataValid)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400RxStrobeDll1 =3D %x\n", ScsConfig->Scs= EmmcHs400RxStrobeDll1)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TxDataDll =3D %x\n", ScsConfig->ScsEmm= cHs400TxDataDll)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DriverStrength =3D %x\n", ScsConfig->S= csEmmcHs400DriverStrength)); +} + +/** + Print PCH_ISH_CONFIG and serial out. + + @param[in] IshConfig Pointer to a PCH_ISH_CONFIG that provides t= he platform setting + +**/ +VOID +PchPrintIshConfig ( + IN CONST PCH_ISH_CONFIG *IshConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH ISH Config -----------------= -\n")); + DEBUG ((DEBUG_INFO, " SPI GPIO Assigned =3D %x\n", IshConfig->SpiGpioA= ssign)); + DEBUG ((DEBUG_INFO, " UART0 GPIO Assigned =3D %x\n", IshConfig->Uart0Gpi= oAssign)); + DEBUG ((DEBUG_INFO, " UART1 GPIO Assigned =3D %x\n", IshConfig->Uart1Gpi= oAssign)); + DEBUG ((DEBUG_INFO, " I2C0 GPIO Assigned =3D %x\n", IshConfig->I2c0Gpio= Assign)); + DEBUG ((DEBUG_INFO, " I2C1 GPIO Assigned =3D %x\n", IshConfig->I2c1Gpio= Assign)); + DEBUG ((DEBUG_INFO, " I2C2 GPIO Assigned =3D %x\n", IshConfig->I2c2Gpio= Assign)); + DEBUG ((DEBUG_INFO, " GP_0 GPIO Assigned =3D %x\n", IshConfig->Gp0GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_1 GPIO Assigned =3D %x\n", IshConfig->Gp1GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_2 GPIO Assigned =3D %x\n", IshConfig->Gp2GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_3 GPIO Assigned =3D %x\n", IshConfig->Gp3GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_4 GPIO Assigned =3D %x\n", IshConfig->Gp4GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_5 GPIO Assigned =3D %x\n", IshConfig->Gp5GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_6 GPIO Assigned =3D %x\n", IshConfig->Gp6GpioA= ssign)); + DEBUG ((DEBUG_INFO, " GP_7 GPIO Assigned =3D %x\n", IshConfig->Gp7GpioA= ssign)); +} + +/** + Print PCH_FLASH_PROTECTION_CONFIG and serial out. + + @param[in] FlashProtectConfig Pointer to a PCH_FLASH_PROTECTION_CONFIG = that provides the platform setting + +**/ +VOID +PchPrintFlashProtectionConfig ( + IN CONST PCH_FLASH_PROTECTION_CONFIG *FlashProtectConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH Flash Protection Config ----= --------------\n")); + for (Index =3D 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) { + DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d] =3D %x\n", Index, Flas= hProtectConfig->ProtectRange[Index].WriteProtectionEnable)); + DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d] =3D %x\n", Index, Flas= hProtectConfig->ProtectRange[Index].ReadProtectionEnable)); + DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d] =3D %x\n", Index, Flas= hProtectConfig->ProtectRange[Index].ProtectedRangeLimit)); + DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d] =3D %x\n", Index, Flas= hProtectConfig->ProtectRange[Index].ProtectedRangeBase)); + } +} + +/** + Print PCH_P2SB_CONFIG and serial out. + + @param[in] P2sbConfig Pointer to a PCH_P2SB_CONFIG that = provides the platform setting + +**/ +VOID +PchPrintP2sbConfig ( + IN CONST PCH_P2SB_CONFIG *P2sbConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH P2SB Config ----------------= --\n")); + DEBUG ((DEBUG_INFO, "SbAccessUnlock=3D %x\n", P2sbConfig->SbAccessUnlock= )); +} + +/** + Print PCH_ESPI_CONFIG. + + @param[in] EspiConfig Pointer to a PCH_ESPI_CONFIG that provides= the eSPI setting + +**/ +VOID +PchPrintEspiConfig ( + IN CONST PCH_ESPI_CONFIG *EspiConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH eSPI Config ----------------= --\n")); + DEBUG ((DEBUG_INFO, " LGMR Enable %x\n", EspiConfig->LgmrEnable)); + DEBUG ((DEBUG_INFO, " BME for Master and Slave Enabled %x\n", EspiConfig= ->BmeMasterSlaveEnabled)); +} + +/** + Print PCH_CNVI_CONFIG. + + @param[in] CnviConfig Pointer to a PCH_CNVI_CONFIG that provides= the CNVi settings + +**/ +VOID +PchPrintCnviConfig ( + IN CONST PCH_CNVI_CONFIG *CnviConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH CNVi Config ----------------= --\n")); + DEBUG ((DEBUG_INFO, "CNVi Mode =3D %x\n", CnviConfig->Mode)); + DEBUG ((DEBUG_INFO, "CNVi MfUart1 type =3D %x\n", CnviConfig->MfUart1Typ= e)); +} + +/** + Print PCH_HSIO_CONFIG. + + @param[in] HsioConfig Pointer to a PCH_HSIO_CONFIG that provides= the eSPI setting + +**/ +VOID +PchPrintHsioConfig ( + IN CONST PCH_HSIO_CONFIG *HsioConfig + ) +{ + PCH_HSIO_VER_INFO *BiosChipsetInitVerInfoPtr; + DEBUG ((DEBUG_INFO, "------------------ PCH HSIO Config ----------------= --\n")); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Pointer =3D %x\n", H= sioConfig->ChipsetInitBinPtr)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Length =3D %x\n", H= sioConfig->ChipsetInitBinLen)); + BiosChipsetInitVerInfoPtr =3D (PCH_HSIO_VER_INFO *) HsioConfig->ChipsetI= nitBinPtr; + if (HsioConfig->ChipsetInitBinPtr && HsioConfig->ChipsetInitBinLen) { + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC =3D %x\n",= BiosChipsetInitVerInfoPtr->BaseCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC =3D %x\n",= BiosChipsetInitVerInfoPtr->OemCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC =3D %x\n",= BiosChipsetInitVerInfoPtr->SusCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Version =3D %x\n",= BiosChipsetInitVerInfoPtr->Version)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Product =3D %x\n",= BiosChipsetInitVerInfoPtr->Product)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Metal Layer =3D %x\n",= BiosChipsetInitVerInfoPtr->MetalLayer)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base Layer =3D %x\n",= BiosChipsetInitVerInfoPtr->BaseLayer)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM Version =3D %x\n",= BiosChipsetInitVerInfoPtr->OemVersion)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Debug Mode =3D %x\n",= BiosChipsetInitVerInfoPtr->DebugMode)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC Valid =3D %x\n",= BiosChipsetInitVerInfoPtr->OemCrcValid)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC Valid =3D %x\n",= BiosChipsetInitVerInfoPtr->SusCrcValid)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC Valid =3D %x\n",= BiosChipsetInitVerInfoPtr->BaseCrcValid)); + } +} + +/** + Print whole PCH config blocks and serial out. + + @param[in] SiPolicyPpi The RC Policy PPI instance + +**/ +VOID +EFIAPI +PchPrintPolicyPpi ( + IN SI_POLICY_PPI *SiPolicyPpi + ) +{ +DEBUG_CODE_BEGIN(); + EFI_STATUS Status; + PCH_GENERAL_CONFIG *PchGeneralConfig; + PCH_PCIE_CONFIG *PcieRpConfig; + PCH_SATA_CONFIG *SataConfig; + PCH_IOAPIC_CONFIG *IoApicConfig; + PCH_DMI_CONFIG *DmiConfig; + PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig; + PCH_HDAUDIO_CONFIG *HdAudioConfig; + PCH_INTERRUPT_CONFIG *InterruptConfig; + PCH_ISH_CONFIG *IshConfig; + PCH_LAN_CONFIG *LanConfig; + PCH_P2SB_CONFIG *P2sbConfig; + PCH_LOCK_DOWN_CONFIG *LockDownConfig; + PCH_PM_CONFIG *PmConfig; + PCH_SCS_CONFIG *ScsConfig; + PCH_SERIAL_IO_CONFIG *SerialIoConfig; + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig; + PCH_THERMAL_CONFIG *ThermalConfig; + USB_CONFIG *UsbConfig; + PCH_ESPI_CONFIG *EspiConfig; + PCH_CNVI_CONFIG *CnviConfig; + PCH_HSIO_CONFIG *HsioConfig; + UINT32 SataCtrlIndex; + + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gPchGeneralConfigGuid,= (VOID *) &PchGeneralConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gPcieRpConfigGuid, (VO= ID *) &PcieRpConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gIoApicConfigGuid, (VO= ID *) &IoApicConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gDmiConfigGuid, (VOID = *) &DmiConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gFlashProtectionConfig= Guid, (VOID *) &FlashProtectionConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gHdAudioConfigGuid, (V= OID *) &HdAudioConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gInterruptConfigGuid, = (VOID *) &InterruptConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gIshConfigGuid, (VOID = *) &IshConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gLanConfigGuid, (VOID = *) &LanConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gLockDownConfigGuid, (= VOID *) &LockDownConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gP2sbConfigGuid, (VOID= *) &P2sbConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gPmConfigGuid, (VOID *= ) &PmConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gScsConfigGuid, (VOID = *) &ScsConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIoConfigGuid, (= VOID *) &SerialIoConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIrqConfigGuid, = (VOID *) &SerialIrqConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gThermalConfigGuid, (V= OID *) &ThermalConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gUsbConfigGuid, (VOID = *) &UsbConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gEspiConfigGuid, (VOID= *) &EspiConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gCnviConfigGuid, (VOID= *) &CnviConfig); + ASSERT_EFI_ERROR (Status); + Status =3D GetConfigBlock ((VOID *) SiPolicyPpi, &gHsioConfigGuid, (VOID= *) &HsioConfig); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy Start ---= ---------------------\n")); + DEBUG ((DEBUG_INFO, " Revision=3D %x\n", SiPolicyPpi->TableHeader.Header= .Revision)); + + PchPrintGeneralConfig (PchGeneralConfig); + PchPrintPcieConfig (PcieRpConfig); + for (SataCtrlIndex =3D 0; SataCtrlIndex < GetPchMaxSataControllerNum ();= SataCtrlIndex++) { + SataConfig =3D GetPchSataConfig (SiPolicyPpi, SataCtrlIndex); + PchPrintSataConfig (SataCtrlIndex, SataConfig); + } + PchPrintUsbConfig (UsbConfig); + PchPrintIoApicConfig (IoApicConfig); + PchPrintHdAudioConfig (HdAudioConfig); + PchPrintLanConfig (LanConfig); + PchPrintLockDownConfig (LockDownConfig); + PchPrintThermalConfig (ThermalConfig); + PchPrintPmConfig (PmConfig); + PchPrintDmiConfig (DmiConfig); + PchPrintSerialIrqConfig (SerialIrqConfig); + PchPrintSerialIoConfig (SerialIoConfig); + PchPrintInterruptConfig (InterruptConfig); + PchPrintScsConfig (ScsConfig); + PchPrintIshConfig (IshConfig); + PchPrintFlashProtectionConfig (FlashProtectionConfig); + PchPrintP2sbConfig (P2sbConfig); + PchPrintEspiConfig (EspiConfig); + PchPrintCnviConfig (CnviConfig); + PchPrintHsioConfig (HsioConfig); + + DEBUG ((DEBUG_INFO, "------------------------ PCH Print Platform Protoco= l End --------------------------\n")); +DEBUG_CODE_END(); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PeiPchPolicyLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchP= olicyLib/PeiPchPolicyLib.c new file mode 100644 index 0000000000..2a1da20667 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPch= PolicyLib.c @@ -0,0 +1,739 @@ +/** @file + This file is PeiPchPolicy library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PeiPchPolicyLibrary.h" +#include +#include +#include + +/** + mPxRcConfig[] table contains data for 8259 routing (how PIRQx is mapped = to IRQy). + This information is used by systems which choose to use legacy PIC + interrupt controller. Only IRQ3-7,9-12,14,15 are valid. Values from this= table + will be programmed into ITSS.PxRC registers. +**/ +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPxRcConfig[] =3D { + 11, // PARC: PIRQA -> IRQ11 + 10, // PBRC: PIRQB -> IRQ10 + 11, // PCRC: PIRQC -> IRQ11 + 11, // PDRC: PIRQD -> IRQ11 + 11, // PERC: PIRQE -> IRQ11 + 11, // PFRC: PIRQF -> IRQ11 + 11, // PGRC: PIRQG -> IRQ11 + 11 // PHRC: PIRQH -> IRQ11 +}; + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPchGeneralConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_GENERAL_CONFIG *PchGeneralConfig; + PchGeneralConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Name =3D %g\n", &P= chGeneralConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", PchGeneralConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + PCH general configuration + ********************************/ +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPcieRpConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + UINTN Index; + PCH_PCIE_CONFIG *PcieRpConfig; + + PcieRpConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Name =3D %g\n", &PcieR= pConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Header.HobLength =3D 0= x%x\n", PcieRpConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + PCI Express related settings + ********************************/ + PcieRpConfig->RpFunctionSwap =3D TRUE; + + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + PcieRpConfig->RootPort[Index].Aspm =3D PchPcieAspmAu= toConfig; + PcieRpConfig->RootPort[Index].PmSci =3D TRUE; + PcieRpConfig->RootPort[Index].AcsEnabled =3D TRUE; + PcieRpConfig->RootPort[Index].PtmEnabled =3D TRUE; + PcieRpConfig->RootPort[Index].DpcEnabled =3D TRUE; + PcieRpConfig->RootPort[Index].RpDpcExtensionsEnabled =3D TRUE; + PcieRpConfig->RootPort[Index].MaxPayload =3D PchPcieMaxPay= load256; + PcieRpConfig->RootPort[Index].SlotImplemented =3D TRUE; + PcieRpConfig->RootPort[Index].PhysicalSlotNumber =3D (UINT8) Index= ; + PcieRpConfig->RootPort[Index].L1Substates =3D PchPcieL1Subs= tatesL1_1_2; + PcieRpConfig->RootPort[Index].EnableCpm =3D TRUE; + PcieRpConfig->RootPort[Index].Gen3EqPh3Method =3D PchPcieEqHard= ware; + + // + // PCIe LTR Configuration. + // + PcieRpConfig->RootPort[Index].LtrEnable =3D TRUE; + + PcieRpConfig->RootPort[Index].LtrMaxSnoopLatency =3D 0x1= 003; + PcieRpConfig->RootPort[Index].LtrMaxNoSnoopLatency =3D 0x1= 003; + + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMode =3D 2= ; + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMultiplier =3D 2= ; + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideValue =3D 6= 0; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMode =3D 2= ; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier =3D 2= ; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideValue =3D 6= 0; + + PcieRpConfig->RootPort[Index].Uptp =3D 5= ; + PcieRpConfig->RootPort[Index].Dptp =3D 7= ; + + PcieRpConfig->EqPh3LaneParam[Index].Cm =3D 6= ; + PcieRpConfig->EqPh3LaneParam[Index].Cp =3D 2= ; + } + + PcieRpConfig->SwEqCoeffList[0].Cm =3D 4; + PcieRpConfig->SwEqCoeffList[0].Cp =3D 8; + PcieRpConfig->SwEqCoeffList[1].Cm =3D 6; + PcieRpConfig->SwEqCoeffList[1].Cp =3D 2; + PcieRpConfig->SwEqCoeffList[2].Cm =3D 8; + PcieRpConfig->SwEqCoeffList[2].Cp =3D 6; + PcieRpConfig->SwEqCoeffList[3].Cm =3D 10; + PcieRpConfig->SwEqCoeffList[3].Cp =3D 8; + PcieRpConfig->SwEqCoeffList[4].Cm =3D 12; + PcieRpConfig->SwEqCoeffList[4].Cp =3D 2; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadSataConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + UINTN PortIndex; + UINTN Index; + UINT32 SataCtrlIndex; + PCH_SATA_CONFIG *SataConfig; + + SataConfig =3D (PCH_SATA_CONFIG *)ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Name =3D %g\n", &SataCon= fig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Header.HobLength =3D 0x%= x\n", SataConfig->Header.GuidHob.Header.HobLength)); + + for (SataCtrlIndex =3D 0; SataCtrlIndex < GetPchMaxSataControllerNum ();= SataCtrlIndex++, SataConfig++) { + /******************************** + SATA related settings + ********************************/ + SataConfig->Enable =3D TRUE; + SataConfig->SalpSupport =3D TRUE; + SataConfig->SataMode =3D PchSataModeAhci; + + for (PortIndex =3D 0; PortIndex < GetPchMaxSataPortNum (SataCtrlIndex)= ; PortIndex++) { + SataConfig->PortSettings[PortIndex].Enable =3D TRUE; + SataConfig->PortSettings[PortIndex].DmVal =3D 15; + SataConfig->PortSettings[PortIndex].DitoVal =3D 625; + } + + SataConfig->Rst.Raid0 =3D TRUE; + SataConfig->Rst.Raid1 =3D TRUE; + SataConfig->Rst.Raid10 =3D TRUE; + SataConfig->Rst.Raid5 =3D TRUE; + SataConfig->Rst.Irrt =3D TRUE; + SataConfig->Rst.OromUiBanner =3D TRUE; + SataConfig->Rst.OromUiDelay =3D PchSataOromDelay2sec; + SataConfig->Rst.HddUnlock =3D TRUE; + SataConfig->Rst.LedLocate =3D TRUE; + SataConfig->Rst.IrrtOnly =3D TRUE; + SataConfig->Rst.SmartStorage =3D TRUE; + SataConfig->Rst.OptaneMemory =3D TRUE; + SataConfig->Rst.CpuAttachedStorage =3D TRUE; + + for (Index =3D 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) { + SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay = =3D 100; + } + + SataConfig->PwrOptEnable =3D TRUE; + SataConfig->ThermalThrottling.SuggestedSetting =3D TRUE; + } +} + +/** + Get Sata Config Policy + + @param[in] SiPolicy The RC Policy PPI instance + @param[in] SataCtrlIndex SATA controller index + + @retval SataConfig Pointer to Sata Config Policy +**/ +PCH_SATA_CONFIG * +GetPchSataConfig ( + IN SI_POLICY_PPI *SiPolicy, + IN UINT32 SataCtrlIndex + ) +{ + PCH_SATA_CONFIG *SataConfig; + EFI_STATUS Status; + + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + Status =3D GetConfigBlock ((VOID *) SiPolicy, &gSataConfigGuid, (VOID *)= &SataConfig); + ASSERT_EFI_ERROR (Status); + + SataConfig +=3D SataCtrlIndex; + + return SataConfig; +} + +/** + Load Config block default + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIoApicConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_IOAPIC_CONFIG *IoApicConfig; + IoApicConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Name =3D %g\n", &IoApi= cConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Header.HobLength =3D 0= x%x\n", IoApicConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Io Apic configuration + ********************************/ + IoApicConfig->IoApicId =3D 0x02; + IoApicConfig->IoApicEntry24_119 =3D TRUE; + IoApicConfig->Enable8254ClockGating =3D TRUE; + IoApicConfig->Enable8254ClockGatingOnS3 =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadDmiConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_DMI_CONFIG *DmiConfig; + DmiConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Name =3D %g\n", &DmiConfi= g->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Header.HobLength =3D 0x%x= \n", DmiConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + DMI related settings + ********************************/ + DmiConfig->DmiAspmCtrl =3D PchPcieAspmAutoConfig; +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadFlashProtectionConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig; + FlashProtectionConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Name =3D %g\n= ", &FlashProtectionConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Header.HobLen= gth =3D 0x%x\n", FlashProtectionConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHdAudioConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HDAUDIO_CONFIG *HdAudioConfig; + HdAudioConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HdAudioConfig->Header.GuidHob.Name =3D %g\n", &HdAu= dioConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HdAudioConfig->Header.GuidHob.Header.HobLength =3D = 0x%x\n", HdAudioConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + HD-Audio configuration + ********************************/ + HdAudioConfig->DspEnable =3D TRUE; + HdAudioConfig->HdAudioLinkFrequency =3D PchHdaLinkFreq24MHz; + HdAudioConfig->IDispLinkFrequency =3D PchHdaLinkFreq96MHz; + HdAudioConfig->IDispLinkTmode =3D PchHdaIDispMode2T; + HdAudioConfig->ResetWaitTimer =3D 600; // Must be at least 521us (= 25 frames) + HdAudioConfig->AudioLinkHda =3D TRUE; + HdAudioConfig->AudioLinkDmic0 =3D TRUE; + HdAudioConfig->AudioLinkDmic1 =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadInterruptConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_INTERRUPT_CONFIG *InterruptConfig; + InterruptConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Name =3D %g\n", &In= terruptConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", InterruptConfig->Header.GuidHob.Header.HobLength)); + + LoadDeviceInterruptConfig (InterruptConfig); + + ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <=3D PCH_MAX_PXRC_CONFIG= ); + CopyMem ( + InterruptConfig->PxRcConfig, + mPxRcConfig, + sizeof (mPxRcConfig) + ); + + InterruptConfig->GpioIrqRoute =3D 14; + InterruptConfig->SciIrqSelect =3D 9; + InterruptConfig->TcoIrqSelect =3D 9; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIshConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ISH_CONFIG *IshConfig; + IshConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Name =3D %g\n", &IshConfi= g->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Header.HobLength =3D 0x%x= \n", IshConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadLanConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LAN_CONFIG *LanConfig; + UINT16 LpcDid; + + LanConfig =3D ConfigBlockPointer; + LpcDid =3D PchGetLpcDid (); + + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Name =3D %g\n", &LanConfi= g->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Header.HobLength =3D 0x%x= \n", LanConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Lan configuration + ********************************/ + LanConfig->Enable =3D TRUE; + LanConfig->LtrEnable =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadLockDownConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LOCK_DOWN_CONFIG *LockDownConfig; + LockDownConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Name =3D %g\n", &Loc= kDownConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Header.HobLength =3D= 0x%x\n", LockDownConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Lockdown configuration + ********************************/ + LockDownConfig->GlobalSmi =3D TRUE; + LockDownConfig->BiosInterface =3D TRUE; + LockDownConfig->RtcMemoryLock =3D TRUE; + LockDownConfig->BiosLock =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadP2sbConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_P2SB_CONFIG *P2sbConfig; + P2sbConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Name =3D %g\n", &P2sbCon= fig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Header.HobLength =3D 0x%= x\n", P2sbConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPmConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_PM_CONFIG *PmConfig; + PmConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Name =3D %g\n", &PmConfig-= >Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Header.HobLength =3D 0x%x\= n", PmConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + MiscPm Configuration + ********************************/ + PmConfig->MeWakeSts =3D TRUE; + PmConfig->WolOvrWkSts =3D TRUE; + + PmConfig->WakeConfig.WolEnableOverride =3D TRUE; + PmConfig->WakeConfig.LanWakeFromDeepSx =3D TRUE; + + PmConfig->PchSlpS3MinAssert =3D PchSlpS350ms; + PmConfig->PchSlpS4MinAssert =3D PchSlpS41s; + PmConfig->PchSlpSusMinAssert =3D PchSlpSus4s; + PmConfig->PchSlpAMinAssert =3D PchSlpA2s; + + PmConfig->SlpLanLowDc =3D TRUE; + PmConfig->PciePllSsc =3D 0xFF; + PmConfig->LpcClockRun =3D TRUE; + PmConfig->SlpS0Enable =3D TRUE; + PmConfig->CpuC10GatePinEnable =3D TRUE; + if (IsWhlCpu () && (GetCpuStepping () =3D=3D EnumCflV0)) { + PmConfig->SlpS0WithGbeSupport =3D FALSE; + } else { + PmConfig->SlpS0WithGbeSupport =3D TRUE; + } + + if (IsPchLp ()) { + PmConfig->ModPhySusPgEnable =3D TRUE; + } +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadScsConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_SCS_CONFIG *ScsConfig; + ScsConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Name =3D %g\n", &ScsConfi= g->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Header.HobLength =3D 0x%x= \n", ScsConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SCS Configuration + ********************************/ + ScsConfig->ScsEmmcEnabled =3D IsPchLp () ? TRUE : FALSE; // eMMC prese= nt on PCH-LP only + ScsConfig->ScsEmmcHs400DriverStrength =3D DriverStrength40Ohm; + //Enable Sd Card controller for Non-Desktop sku platforms + if (GetCpuSku () !=3D EnumCpuTrad) { + ScsConfig->ScsSdcardEnabled =3D TRUE; + } + ScsConfig->SdCardPowerEnableActiveHigh =3D TRUE; + ScsConfig->ScsUfsEnabled =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadSerialIoConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + UINTN Index; + PCH_SERIAL_IO_CONFIG *SerialIoConfig; + SerialIoConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Name =3D %g\n", &Ser= ialIoConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Header.HobLength =3D= 0x%x\n", SerialIoConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SerialIo Configuration + ********************************/ + for (Index =3D 0; Index < GetPchMaxSerialIoControllersNum (); Index++) { + SerialIoConfig->DevMode[Index] =3D PchSerialIoPci; + } + SerialIoConfig->DebugUartNumber =3D PcdGet8 (PcdSerialIoUartNum= ber); +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadSerialIrqConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig; + SerialIrqConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Name =3D %g\n", &Se= rialIrqConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", SerialIrqConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Serial IRQ Configuration + ********************************/ + SerialIrqConfig->SirqEnable =3D TRUE; + SerialIrqConfig->SirqMode =3D PchQuietMode; + SerialIrqConfig->StartFramePulse =3D PchSfpw4Clk; +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadThermalConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_THERMAL_CONFIG *ThermalConfig; + ThermalConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Name =3D %g\n", &Ther= malConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Header.HobLength =3D = 0x%x\n", ThermalConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Thermal configuration. + ********************************/ + ThermalConfig->TsmicLock =3D TRUE; + ThermalConfig->PchHotLevel =3D 0x154; + ThermalConfig->TTLevels.SuggestedSetting =3D TRUE; + ThermalConfig->TTLevels.PchCrossThrottling =3D TRUE; + ThermalConfig->DmiHaAWC.SuggestedSetting =3D TRUE; + + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable = =3D TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnab= le =3D TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable = =3D TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnab= le =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadUsbConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + UINTN PortIndex; + USB_CONFIG *UsbConfig; + UsbConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Name =3D %g\n", &UsbConfi= g->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Header.HobLength =3D 0x%x= \n", UsbConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + USB related configuration + ********************************/ + for (PortIndex =3D 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex= ++) { + UsbConfig->PortUsb20[PortIndex].Enable =3D TRUE; + } + + for (PortIndex =3D 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex= ++) { + UsbConfig->PortUsb30[PortIndex].Enable =3D TRUE; + } + + // + // BIOS should program PDO in PEI phase by default + // + UsbConfig->PdoProgramming =3D TRUE; + + // + // Default values of USB2 AFE settings. + // + UsbConfig->Usb2PhySusPgEnable =3D TRUE; + for (PortIndex =3D 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex= ++) { + UsbConfig->PortUsb20[PortIndex].Afe.Petxiset =3D 3; + UsbConfig->PortUsb20[PortIndex].Afe.Txiset =3D 2; + UsbConfig->PortUsb20[PortIndex].Afe.Predeemp =3D 1; + UsbConfig->PortUsb20[PortIndex].Afe.Pehalfbit =3D 1; + } + + for (PortIndex =3D 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex= ++) { + UsbConfig->PortUsb30HsioRx[PortIndex].HsioOlfpsCfgPullUpDwnRes =3D 3; + } + + UsbConfig->XhciOcLock =3D TRUE; + + // + // xDCI configuration + // + UsbConfig->XdciConfig.Enable =3D FALSE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadEspiConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ESPI_CONFIG *EspiConfig; + EspiConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Name =3D %g\n", &EspiCon= fig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Header.HobLength =3D 0x%= x\n", EspiConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Espi configuration. + ********************************/ + EspiConfig->BmeMasterSlaveEnabled =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadCnviConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_CNVI_CONFIG *CnviConfig; + CnviConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Name =3D %g\n", &CnviCon= fig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Header.HobLength =3D 0x%= x\n", CnviConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Cnvi configuration. + ********************************/ + CnviConfig->Mode =3D CnviModeAuto; // Automatic detection +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHsioConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HSIO_CONFIG *HsioConfig; + HsioConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Name =3D %g\n", &HsioCon= fig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Header.HobLength =3D 0x%= x\n", HsioConfig->Header.GuidHob.Header.HobLength)); +} + +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mPchIpBlocks [] =3D { + {&gPchGeneralConfigGuid, sizeof (PCH_GENERAL_CONFIG), PC= H_GENERAL_CONFIG_REVISION, LoadPchGeneralConfigDefault}, + {&gPcieRpConfigGuid, sizeof (PCH_PCIE_CONFIG), PC= IE_RP_CONFIG_REVISION, LoadPcieRpConfigDefault}, + {&gSataConfigGuid, sizeof (PCH_SATA_CONFIG), SA= TA_CONFIG_REVISION, LoadSataConfigDefault}, + {&gIoApicConfigGuid, sizeof (PCH_IOAPIC_CONFIG), IO= APIC_CONFIG_REVISION, LoadIoApicConfigDefault}, + {&gDmiConfigGuid, sizeof (PCH_DMI_CONFIG), DM= I_CONFIG_REVISION, LoadDmiConfigDefault}, + {&gFlashProtectionConfigGuid, sizeof (PCH_FLASH_PROTECTION_CONFIG), FL= ASH_PROTECTION_CONFIG_REVISION, LoadFlashProtectionConfigDefault}, + {&gHdAudioConfigGuid, sizeof (PCH_HDAUDIO_CONFIG), HD= AUDIO_CONFIG_REVISION, LoadHdAudioConfigDefault}, + {&gInterruptConfigGuid, sizeof (PCH_INTERRUPT_CONFIG), IN= TERRUPT_CONFIG_REVISION, LoadInterruptConfigDefault}, + {&gIshConfigGuid, sizeof (PCH_ISH_CONFIG), IS= H_CONFIG_REVISION, LoadIshConfigDefault}, + {&gLanConfigGuid, sizeof (PCH_LAN_CONFIG), LA= N_CONFIG_REVISION, LoadLanConfigDefault}, + {&gLockDownConfigGuid, sizeof (PCH_LOCK_DOWN_CONFIG), LO= CK_DOWN_CONFIG_REVISION, LoadLockDownConfigDefault}, + {&gP2sbConfigGuid, sizeof (PCH_P2SB_CONFIG), P2= SB_CONFIG_REVISION, LoadP2sbConfigDefault}, + {&gPmConfigGuid, sizeof (PCH_PM_CONFIG), PM= _CONFIG_REVISION, LoadPmConfigDefault}, + {&gScsConfigGuid, sizeof (PCH_SCS_CONFIG), SC= S_CONFIG_REVISION, LoadScsConfigDefault}, + {&gSerialIoConfigGuid, sizeof (PCH_SERIAL_IO_CONFIG), SE= RIAL_IO_CONFIG_REVISION, LoadSerialIoConfigDefault}, + {&gSerialIrqConfigGuid, sizeof (PCH_LPC_SIRQ_CONFIG), SE= RIAL_IRQ_CONFIG_REVISION, LoadSerialIrqConfigDefault}, + {&gThermalConfigGuid, sizeof (PCH_THERMAL_CONFIG), TH= ERMAL_CONFIG_REVISION, LoadThermalConfigDefault}, + {&gUsbConfigGuid, sizeof (USB_CONFIG), US= B_CONFIG_REVISION, LoadUsbConfigDefault}, + {&gEspiConfigGuid, sizeof (PCH_ESPI_CONFIG), ES= PI_CONFIG_REVISION, LoadEspiConfigDefault}, + {&gCnviConfigGuid, sizeof (PCH_CNVI_CONFIG), CN= VI_CONFIG_REVISION, LoadCnviConfigDefault}, + {&gHsioConfigGuid, sizeof (PCH_HSIO_CONFIG), HS= IO_CONFIG_REVISION, LoadHsioConfigDefault}, +}; + +/** + Get PCH config block table total size. + + @retval Size of PCH config block table +**/ +UINT16 +EFIAPI +PchGetConfigBlockTotalSize ( + VOID + ) +{ + return GetComponentConfigBlockTotalSize (&mPchIpBlocks[0], sizeof (mPchI= pBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)); +} + +/** + PchAddConfigBlocks add all PCH config blocks. + + @param[in] ConfigBlockTableAddress The pointer to add PCH config bloc= ks + + @retval EFI_SUCCESS The policy default is initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create b= uffer +**/ +EFI_STATUS +EFIAPI +PchAddConfigBlocks ( + IN VOID *ConfigBlockTableAddress + ) +{ + DEBUG ((DEBUG_INFO, "PCH AddConfigBlocks\n")); + + return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocks[= 0], sizeof (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PeiPchPolicyLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiP= chPolicyLib/PeiPchPolicyLibCnl.c new file mode 100644 index 0000000000..d19692ff2c --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPch= PolicyLibCnl.c @@ -0,0 +1,169 @@ +/** @file + This file is PeiPchPolicy library Cannon Lake specific. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PeiPchPolicyLibrary.h" +#include +#include + +/** + mDevIntConfig[] table contains data on INTx and IRQ for each device. + IRQ value for devices which use ITSS INTx->PIRQx mapping need to be set = in a way + that for each multifunctional Dxx:Fy same interrupt pins must map to the= same IRQ. + Those IRQ values will be used to update ITSS.PIRx register. + In APIC relationship between PIRQs and IRQs is: + PIRQA -> IRQ16 + PIRQB -> IRQ17 + PIRQC -> IRQ18 + PIRQD -> IRQ19 + PIRQE -> IRQ20 + PIRQF -> IRQ21 + PIRQG -> IRQ22 + PIRQH -> IRQ23 + + Devices which use INTx->PIRQy mapping are: cAVS(in PCI mode), SMBus, GbE= , TraceHub, PCIe, + SATA, HECI, IDE-R, KT Redirection, xHCI, Thermal Subsystem, Camera IO Ho= st Controller + + PCI Express Root Ports mapping should be programmed only with values as = in below table (D27/28/29) + otherwise _PRT methods in ACPI for RootPorts would require additional pa= tching as + PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Map= ping + + Configured IRQ values are not used if an OS chooses to be in PIC instead= of APIC mode +**/ +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mDevIntConfig[] = =3D { +// {31, 0, PchNoInt, 0}, // LPC/eSPI Interface, doesn't use interrupts +// {31, 1, PchNoInt, 0}, // P2SB, doesn't use interrupts +// {31, 2, PchNoInt, 0}, // PMC , doesn't use interrupts + {31, 3, PchIntA, 16}, // cAVS(Audio, Voice, Speach), INTA is default, pr= ogrammed in PciCfgSpace 3Dh + {31, 4, PchIntA, 16}, // SMBus Controller, no default value, programmed = in PciCfgSpace 3Dh +// {31, 5, PchNoInt, 0}, // SPI , doesn't use interrupts + {31, 7, PchIntA, 16}, // TraceHub, INTA is default, RO register + {30, 0, PchIntA, 20}, // SerialIo: UART #0, INTA is default, programmed = in PCR[SERIALIO] + PCICFGCTRL[7] + {30, 1, PchIntB, 21}, // SerialIo: UART #1, INTA is default, programmed = in PCR[SERIALIO] + PCICFGCTRL[8] + {30, 2, PchIntC, 22}, // SerialIo: SPI #0, INTA is default, programmed i= n PCR[SERIALIO] + PCICFGCTRL[10] + {30, 3, PchIntD, 23}, // SerialIo: SPI #1, INTA is default, programmed i= n PCR[SERIALIO] + PCICFGCTRL[11] + {28, 0, PchIntA, 16}, // PCI Express Port 1, INT is default, programmed = in PciCfgSpace + FCh + {28, 1, PchIntB, 17}, // PCI Express Port 2, INT is default, programmed = in PciCfgSpace + FCh + {28, 2, PchIntC, 18}, // PCI Express Port 3, INT is default, programmed = in PciCfgSpace + FCh + {28, 3, PchIntD, 19}, // PCI Express Port 4, INT is default, programmed = in PciCfgSpace + FCh + {28, 4, PchIntA, 16}, // PCI Express Port 5, INT is default, programmed = in PciCfgSpace + FCh + {28, 5, PchIntB, 17}, // PCI Express Port 6, INT is default, programmed = in PciCfgSpace + FCh + {28, 6, PchIntC, 18}, // PCI Express Port 7, INT is default, programmed = in PciCfgSpace + FCh + {28, 7, PchIntD, 19}, // PCI Express Port 8, INT is default, programmed = in PciCfgSpace + FCh + {25, 2, PchIntC, 34}, // SerialIo UART Controller #2, INTA is default, p= rogrammed in PCR[SERIALIO] + PCICFGCTRL[9] +// {24, 0, 0, 0}, // Reserved (used by RST PCIe Storage Cycle Router) + {23, 0, PchIntA, 16}, // SATA Controller, INTA is default, programmed in= PciCfgSpace + 3Dh + {22, 0, PchIntA, 16}, // CSME: HECI #1 + {22, 1, PchIntB, 17}, // CSME: HECI #2 + {22, 4, PchIntA, 16}, // CSME: HECI #3 +// {22, 7, PchNoInt, 0}, // CSME: WLAN + {21, 0, PchIntA, 16}, // SerialIo I2C Controller #0, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[1] + {21, 1, PchIntB, 17}, // SerialIo I2C Controller #1, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[2] + {21, 2, PchIntC, 18}, // SerialIo I2C Controller #2, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[3] + {21, 3, PchIntD, 19}, // SerialIo I2C Controller #3, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[4] + {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value, prog= rammed in PciCfgSpace 3Dh + {20, 1, PchIntB, 17}, // USB Device Controller (OTG) + //{20, 2, PchNoInt, 0}, // Shared SRAM, no interrupts + {20, 3, PchIntA, 16}, // CNVi WiFir +// {20, 4, 0, 0}, // TraceHub Phantom (ACPI) Function + {20, 5, PchIntD, 19}, // SCS: SDCard +// {18, 0, PchNoInt, 0}, // CSME: KVMcc, doesn't use interrupts +// {18, 1, PchNoInt, 0}, // CSME: Clink, doesn't use interrupts +// {18, 2, PchNoInt, 0}, // CSME: PMT, doesn't use interrupts +// {18, 3, 0, 0}, // CSME: CSE UMA +// {18, 4, 0, 0} // CSME: fTPM DMA + {18, 5, PchIntA, 16} // SCS: UFS +}; + +// +// mCnlPchLpOnlyDevIntConfig[] table contains data on INTx and IRQ for dev= ices that exist on PCH-LP +// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mPchLpOnlyDevInt= Config[] =3D { + {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in = PciCfgSpace 3Dh + {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed = in PciCfgSpace + FCh + {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed= in PciCfgSpace + FCh + {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed= in PciCfgSpace + FCh + {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed= in PciCfgSpace + FCh + {29, 4, PchIntA, 16}, // PCI Express Port 13, INT is default, programmed= in PciCfgSpace + FCh + {29, 5, PchIntB, 17}, // PCI Express Port 14, INT is default, programmed= in PciCfgSpace + FCh + {29, 6, PchIntC, 18}, // PCI Express Port 15, INT is default, programmed= in PciCfgSpace + FCh + {29, 7, PchIntD, 19}, // PCI Express Port 16, INT is default, programmed= in PciCfgSpace + FCh + {26, 0, PchIntA, 16}, // SCS: eMMC + {25, 0, PchIntA, 32}, // SerialIo I2C Controller #4, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[5] + {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, pr= ogrammed in PCR[SERIALIO] + PCICFGCTRL[6] + {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R) + {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection + {19, 0, PchIntA, 20}, // Integrated Sensor Hub + {18, 0, PchIntA, 16}, // Thermal Subsystem + {18, 6, PchIntB, 24} // SerialIo: SPI #2, INTA is default, programmed i= n PCR[SERIALIO] + PCICFGCTRL[12] +}; + +// +// mPchHOnlyDevIntConfig[] table contains data on INTx and IRQ for devices= that exist on PCH-H +// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mPchHOnlyDevIntC= onfig[] =3D { + {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in = PciCfgSpace 3Dh + {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed = in PciCfgSpace + FCh + {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed= in PciCfgSpace + FCh + {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed= in PciCfgSpace + FCh + {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed= in PciCfgSpace + FCh + {29, 4, PchIntA, 16}, // PCI Express Port 13, INT is default, programmed= in PciCfgSpace + FCh + {29, 5, PchIntB, 17}, // PCI Express Port 14, INT is default, programmed= in PciCfgSpace + FCh + {29, 6, PchIntC, 18}, // PCI Express Port 15, INT is default, programmed= in PciCfgSpace + FCh + {29, 7, PchIntD, 19}, // PCI Express Port 16, INT is default, programmed= in PciCfgSpace + FCh + {27, 0, PchIntA, 16}, // PCI Express Port 17, INT is default, programmed= in PciCfgSpace + FCh + {27, 1, PchIntB, 17}, // PCI Express Port 18, INT is default, programmed= in PciCfgSpace + FCh + {27, 2, PchIntC, 18}, // PCI Express Port 19, INT is default, programmed= in PciCfgSpace + FCh + {27, 3, PchIntD, 19}, // PCI Express Port 20, INT is default, programmed= in PciCfgSpace + FCh + {27, 4, PchIntA, 16}, // PCI Express Port 21 + {27, 5, PchIntB, 17}, // PCI Express Port 22 + {27, 6, PchIntC, 18}, // PCI Express Port 23 + {27, 7, PchIntD, 19}, // PCI Express Port 24 + {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R) + {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection + {19, 0, PchIntA, 20}, // Integrated Sensor Hub + {18, 0, PchIntA, 16}, // Thermal Subsystem + {18, 6, PchIntB, 24} // SerialIo: SPI #2, INTA is default, programmed i= n PCR[SERIALIO] + PCICFGCTRL[12] +}; + +/** + Adds interrupt configuration for device + + @param[in/out] InterruptConfig Pointer to interrupt config +**/ +VOID +LoadDeviceInterruptConfig ( + IN OUT PCH_INTERRUPT_CONFIG *InterruptConfig + ) +{ + UINT8 IntConfigTableEntries; + + IntConfigTableEntries =3D ARRAY_SIZE (mDevIntConfig); + ASSERT (IntConfigTableEntries <=3D PCH_MAX_DEVICE_INTERRUPT_CONFIG); + InterruptConfig->NumOfDevIntConfig =3D IntConfigTableEntries; + CopyMem ( + InterruptConfig->DevIntConfig, + mDevIntConfig, + sizeof (mDevIntConfig) + ); + + if (IsPchLp ()) { + CopyMem ( + &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig])= , + mPchLpOnlyDevIntConfig, + sizeof (mPchLpOnlyDevIntConfig) + ); + InterruptConfig->NumOfDevIntConfig +=3D ARRAY_SIZE (mPchLpOnlyDevIntCo= nfig); + } else if (IsPchH ()) { + CopyMem ( + &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig])= , + mPchHOnlyDevIntConfig, + sizeof (mPchHOnlyDevIntConfig) + ); + InterruptConfig->NumOfDevIntConfig +=3D ARRAY_SIZE (mPchHOnlyDevIntCon= fig); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib= /PeiPchPreMemPolicyLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/P= eiPchPolicyLib/PeiPchPreMemPolicyLib.c new file mode 100644 index 0000000000..dfab5d29c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPch= PreMemPolicyLib.c @@ -0,0 +1,318 @@ +/** @file + This file is PeiPchPreMemPolicy library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PeiPchPolicyLibrary.h" +#include + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPchGeneralPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig; + PchGeneralPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Name =3D %g\= n", &PchGeneralPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Header.HobLe= ngth =3D 0x%x\n", PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength))= ; + + /******************************** + PCH general premem configuration + ********************************/ +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadDciPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_DCI_PREMEM_CONFIG *DciPreMemConfig; + DciPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Name =3D %g\n", &Dc= iPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", DciPreMemConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + DCI Configuration + ********************************/ +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadWatchDogPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig; + WdtPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Name =3D %g\n", &Wd= tPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", WdtPreMemConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPchTraceHubPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_TRACE_HUB_PREMEM_CONFIG *PchTraceHubPreMemConfig; + PchTraceHubPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchTraceHubPreMemConfig->Header.GuidHob.Name =3D %g= \n", &PchTraceHubPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchTraceHubPreMemConfig->Header.GuidHob.Header.HobL= ength =3D 0x%x\n", PchTraceHubPreMemConfig->Header.GuidHob.Header.HobLength= )); +} + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] =3D { + 0xA0, + 0xA2, + 0xA4, + 0xA6 +}; + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadSmbusPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig; + SmbusPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Name =3D %g\n", &= SmbusPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", SmbusPreMemConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SMBus configuration + ********************************/ + SmbusPreMemConfig->Enable =3D TRUE; + SmbusPreMemConfig->DynamicPowerGating =3D TRUE; + SmbusPreMemConfig->SpdWriteDisable =3D TRUE; + SmbusPreMemConfig->SmbusIoBase =3D PcdGet16 (PcdSmbusBaseAddre= ss); + ASSERT (sizeof (mSmbusRsvdAddresses) <=3D PCH_MAX_SMBUS_RESERVED_ADDRESS= ); + SmbusPreMemConfig->NumRsvdSmbusAddresses =3D sizeof (mSmbusRsvdAddresses= ); + CopyMem ( + SmbusPreMemConfig->RsvdSmbusAddressTable, + mSmbusRsvdAddresses, + sizeof (mSmbusRsvdAddresses) + ); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadLpcPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig; + LpcPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Name =3D %g\n", &Lp= cPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Header.HobLength = =3D 0x%x\n", LpcPreMemConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + LPC Configuration + ********************************/ + LpcPreMemConfig->EnhancePort8xhDecoding =3D TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHsioPciePreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig; + HsioPciePreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Name =3D %g\n"= , &HsioPciePreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Header.HobLeng= th =3D 0x%x\n", HsioPciePreMemConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHsioSataPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig; + HsioSataPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Name =3D %g\n"= , &HsioSataPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Header.HobLeng= th =3D 0x%x\n", HsioSataPreMemConfig->Header.GuidHob.Header.HobLength)); +} + +/** + Get Hsio Sata Pre Mem Config Policy + + @param[in] SiPolicy The RC Policy PPI instance + @param[in] SataCtrlIndex SATA controller index + + @retval Pointer to Hsio Sata Pre Mem Config Policy +**/ +PCH_HSIO_SATA_PREMEM_CONFIG * +GetPchHsioSataPreMemConfig ( + IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy, + IN UINT32 SataCtrlIndex + ) +{ + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig; + EFI_STATUS Status; + + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + Status =3D GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioSataPreMemConf= igGuid, (VOID *) &HsioSataPreMemConfig); + ASSERT_EFI_ERROR (Status); + + HsioSataPreMemConfig +=3D SataCtrlIndex; + + return HsioSataPreMemConfig; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadPcieRpPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig; + UINT32 RpIndex; + + PcieRpPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =3D %g\n", = &PcieRpPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength= =3D 0x%x\n", PcieRpPreMemConfig->Header.GuidHob.Header.HobLength)); + + for (RpIndex =3D 0; RpIndex < GetPchMaxPciePortNum (); RpIndex ++) { + PcieRpPreMemConfig->RpEnabledMask |=3D (UINT32) (1 << RpIndex); + } +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHdAudioPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig; + HdaPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =3D %g\n", = &HdaPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength= =3D 0x%x\n", HdaPreMemConfig->Header.GuidHob.Header.HobLength)); + HdaPreMemConfig->Enable =3D 1; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIshPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ISH_PREMEM_CONFIG *IshPreMemConfig; + IshPreMemConfig =3D ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =3D %g\n", = &IshPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength= =3D 0x%x\n", IshPreMemConfig->Header.GuidHob.Header.HobLength)); + //Enable ISH controller for Non-Desktop sku platforms + if (GetCpuSku () !=3D EnumCpuTrad) { + IshPreMemConfig->Enable =3D TRUE; + } +} + + +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mPchIpBlocksPreMem []= =3D { + {&gPchGeneralPreMemConfigGuid, sizeof (PCH_GENERAL_PREMEM_CONFIG), = PCH_GENERAL_PREMEM_CONFIG_REVISION, LoadPchGeneralPreMemConfigDefa= ult}, + {&gDciPreMemConfigGuid, sizeof (PCH_DCI_PREMEM_CONFIG), = DCI_PREMEM_CONFIG_REVISION, LoadDciPreMemConfigDefault}, + {&gWatchDogPreMemConfigGuid, sizeof (PCH_WDT_PREMEM_CONFIG), = WATCH_DOG_PREMEM_CONFIG_REVISION, LoadWatchDogPreMemConfigDefaul= t}, + {&gPchTraceHubPreMemConfigGuid, sizeof (PCH_TRACE_HUB_PREMEM_CONFIG),= PCH_TRACEHUB_PREMEM_CONFIG_REVISION, LoadPchTraceHubPreMemConfigDef= ault}, + {&gSmbusPreMemConfigGuid, sizeof (PCH_SMBUS_PREMEM_CONFIG), = SMBUS_PREMEM_CONFIG_REVISION, LoadSmbusPreMemConfigDefault}, + {&gLpcPreMemConfigGuid, sizeof (PCH_LPC_PREMEM_CONFIG), = LPC_PREMEM_CONFIG_REVISION, LoadLpcPreMemConfigDefault}, + {&gHsioPciePreMemConfigGuid, sizeof (PCH_HSIO_PCIE_PREMEM_CONFIG),= HSIO_PCIE_PREMEM_CONFIG_REVISION, LoadHsioPciePreMemConfigDefaul= t}, + {&gHsioSataPreMemConfigGuid, sizeof (PCH_HSIO_SATA_PREMEM_CONFIG),= HSIO_SATA_PREMEM_CONFIG_REVISION, LoadHsioSataPreMemConfigDefaul= t}, + {&gPcieRpPreMemConfigGuid, sizeof (PCH_PCIE_RP_PREMEM_CONFIG), = PCIE_RP_PREMEM_CONFIG_REVISION, LoadPcieRpPreMemConfigDefault}= , + {&gHdAudioPreMemConfigGuid, sizeof (PCH_HDAUDIO_PREMEM_CONFIG), = HDAUDIO_PREMEM_CONFIG_REVISION, LoadHdAudioPreMemConfigDefault= }, + {&gIshPreMemConfigGuid, sizeof (PCH_ISH_PREMEM_CONFIG), = ISH_PREMEM_CONFIG_REVISION, LoadIshPreMemConfigDefault}, +}; + +/** + Get PCH PREMEM config block table total size. + + @retval Size of PCH PREMEM config block ta= ble +**/ +UINT16 +EFIAPI +PchGetPreMemConfigBlockTotalSize ( + VOID + ) +{ + return GetComponentConfigBlockTotalSize (&mPchIpBlocksPreMem[0], sizeof = (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY)); +} + +/** + PchAddPreMemConfigBlocks add all PCH PREMEM config blocks. + + @param[in] ConfigBlockTableAddress The pointer to add PCH PREMEM conf= ig blocks + + @retval EFI_SUCCESS The policy default is initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create b= uffer +**/ +EFI_STATUS +EFIAPI +PchAddPreMemConfigBlocks ( + IN VOID *ConfigBlockTableAddress + ) +{ + DEBUG ((DEBUG_INFO, "PCH AddPreMemConfigBlocks\n")); + + return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocksP= reMem[0], sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY)); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/= PchReset.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/= PchReset.c new file mode 100644 index 0000000000..2210344462 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchRese= t.c @@ -0,0 +1,109 @@ +/** @file + PCH RESET PEIM DRIVER. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + + +/** + Resets the entire platform. + + @param[in] ResetType UEFI defined reset type. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size of ResetData in bytes. + @param[in] ResetData Optional element used to introduce a pla= tform specific reset. + The exact type of the reset is defined b= y the EFI_GUID that follows + the Null-terminated Unicode string. + +**/ +VOID +EFIAPI +ResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + switch (ResetType) { + case EfiResetWarm: + ResetWarm (); + break; + + case EfiResetCold: + ResetCold (); + break; + + case EfiResetShutdown: + ResetShutdown (); + return; + + case EfiResetPlatformSpecific: + ResetPlatformSpecific (DataSize, ResetData); + return; + + default: + return; + } + + // + // Given we should have reset getting here would be bad + // + ASSERT (FALSE); + CpuDeadLoop(); +} + +/** + Initialize PCH Reset APIs + + @retval EFI_SUCCESS APIs are installed successfully + @retval EFI_OUT_OF_RESOURCES Can't allocate pool +**/ +EFI_STATUS +EFIAPI +PchInitializeReset ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_RESET2_PPI *EfiPeiReset2Ppi; + EFI_PEI_PPI_DESCRIPTOR *EfiPeiReset2Descriptor; + + DEBUG ((DEBUG_INFO, "PchInitializeReset() Start\n")); + + + EfiPeiReset2Descriptor =3D (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (= sizeof (EFI_PEI_PPI_DESCRIPTOR)); + EfiPeiReset2Ppi =3D (EFI_PEI_RESET2_PPI *) AllocateZeroPool (sizeof (EFI= _PEI_RESET2_PPI)); + if ((EfiPeiReset2Descriptor =3D=3D NULL) || + (EfiPeiReset2Ppi =3D=3D NULL)) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + /// + /// Initialize the EFI Reset2 ppi instance + /// + EfiPeiReset2Ppi->ResetSystem =3D ResetSystem; + + EfiPeiReset2Descriptor->Flags =3D EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_P= PI_DESCRIPTOR_TERMINATE_LIST; + EfiPeiReset2Descriptor->Guid =3D &gEfiPeiReset2PpiGuid; + EfiPeiReset2Descriptor->Ppi =3D EfiPeiReset2Ppi; + + Status =3D PeiServicesInstallPpi (EfiPeiReset2Descriptor); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "PchInitializeReset() End\n")); + + return Status; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemL= ib/PeiResetSystemLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pei= ResetSystemLib/PeiResetSystemLib.c new file mode 100644 index 0000000000..58f2d86103 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiR= esetSystemLib.c @@ -0,0 +1,257 @@ +/** @file + System reset library services. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Dump reset message for debug build readability +**/ +VOID +DumpResetMessage ( + VOID + ) +{ + DEBUG_CODE_BEGIN (); + UINTN Index; + // + // ****************************** + // ** SYSTEM REBOOT !!! ** + // ****************************** + // + for (Index =3D 0; Index < 30; Index++) { + DEBUG ((DEBUG_INFO, "*")); + } + DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n")); + for (Index =3D 0; Index < 30; Index++) { + DEBUG ((DEBUG_INFO, "*")); + } + DEBUG ((DEBUG_INFO, "\n")); + DEBUG_CODE_END (); +} +/** + Execute call back function for Pch Reset. + + @param[in] ResetType Reset Types which includes GlobalReset. + @param[in] ResetTypeGuid Pointer to an EFI_GUID, which is the Res= et Type Guid. +**/ +VOID +PchResetCallback ( + IN EFI_RESET_TYPE ResetType, + IN EFI_GUID *ResetTypeGuid + ) +{ + EFI_STATUS Status; + UINTN Instance; + PCH_RESET_CALLBACK_PPI *PchResetCallbackPpi; + + Instance =3D 0; + do { + Status =3D PeiServicesLocatePpi ( + &gPchResetCallbackPpiGuid, + Instance, + NULL, + (VOID **) &PchResetCallbackPpi + ); + + switch (Status) { + case EFI_SUCCESS: + PchResetCallbackPpi->ResetCallback (ResetType, ResetTypeGuid); + break; + case EFI_NOT_FOUND: + break; + default: + ASSERT_EFI_ERROR (Status); + break; + } + ++Instance; + } while (Status =3D=3D EFI_SUCCESS); +} + +/** + Calling this function causes a system-wide reset. This sets + all circuitry within the system to its initial state. This type of reset + is asynchronous to system operation and operates without regard to + cycle boundaries. + + System reset should not return, if it returns, it means the system does + not support cold reset. +**/ +VOID +EFIAPI +ResetCold ( + VOID + ) +{ + // + // Loop through callback functions of PchResetCallback PPI + // + PchResetCallback (EfiResetCold, NULL); + DumpResetMessage (); + + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET); +} + +/** + Calling this function causes a system-wide initialization. The processor= s + are set to their initial state, and pending cycles are not corrupted. + + System reset should not return, if it returns, it means the system does + not support warm reset. +**/ +VOID +EFIAPI +ResetWarm ( + VOID + ) +{ + // + // Loop through callback functions of PchResetCallback PPI + // + PchResetCallback (EfiResetWarm, NULL); + DumpResetMessage (); + + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_HARDRESET); +} + +/** + Calling this function causes the system to enter a power state equivalen= t + to the ACPI G2/S5 or G3 states. + + System shutdown should not return, if it returns, it means the system do= es + not support shut down reset. +**/ +VOID +EFIAPI +ResetShutdown ( + VOID + ) +{ + UINT16 ABase; + UINT32 Data32; + + // + // Loop through callback functions of PchResetCallback PPI + // + PchResetCallback (EfiResetShutdown, NULL); + + ABase =3D PmcGetAcpiBase (); + /// + /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the s= ystem from S5 + /// + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_GPE0_EN_127_96), 0); + + /// + /// Secondly, PwrSts register must be cleared + /// + /// Write a "1" to bit[8] of power button status register at + /// (PM_BASE + PM1_STS_OFFSET) to clear this bit + /// + IoWrite16 ((UINTN) (ABase + R_ACPI_IO_PM1_STS), B_ACPI_IO_PM1_STS_PWRBTN= ); + + /// + /// Finally, transform system into S5 sleep state + /// + Data32 =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT)); + + Data32 =3D (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP + B_ACPI_IO_PM= 1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5); + + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT), Data32); + + Data32 =3D Data32 | B_ACPI_IO_PM1_CNT_SLP_EN; + + DumpResetMessage (); + + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT), Data32); + + return; +} + +/** + Internal function to execute the required HECI command for GlobalReset, + if failed will use PCH Reest. + +**/ +STATIC +VOID +PchGlobalReset ( + VOID + ) +{ + // + // Loop through callback functions of PchResetCallback PPI + // + PchResetCallback (EfiResetPlatformSpecific, &gPchGlobalResetGuid); + + // + // PCH BIOS Spec Section 4.6 GPIO Reset Requirement + // + PmcEnableCf9GlobalReset (); + + DumpResetMessage (); + + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET); +} + +/** + Calling this function causes the system to enter a power state for platf= orm specific. + + @param[in] DataSize The size of ResetData in bytes. + @param[in] ResetData Optional element used to introduce a pla= tform specific reset. + The exact type of the reset is defined b= y the EFI_GUID that follows + the Null-terminated Unicode string. + +**/ +VOID +EFIAPI +ResetPlatformSpecific ( + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + EFI_GUID *GuidPtr; + + if (ResetData =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "[PeiResetSystemLib] ResetData is not available.\= n")); + return; + } + GuidPtr =3D (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_G= UID)); + if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) { + PchGlobalReset(); + } else { + return; + } +} + +/** + Calling this function causes the system to enter a power state for capsu= le update. + + Reset update should not return, if it returns, it means the system does + not support capsule update. + +**/ +VOID +EFIAPI +EnterS3WithImmediateWake ( + VOID + ) +{ + ASSERT (FALSE); +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSp= i.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c new file mode 100644 index 0000000000..1a5db7f24a --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c @@ -0,0 +1,217 @@ +/** @file + PCH SPI PEI Library implements the SPI Host Controller Compatibility Int= erface. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + SPI_INSTANCE SpiInstance; +} PEI_SPI_INSTANCE; + +/** + PCI Enumeratuion is not done till later in DXE + Initlialize SPI BAR0 to a default value till enumeration is done + also enable memory space decoding for SPI + +**/ +VOID +InitSpiBar0 ( + VOID + ) +{ + UINT64 PchSpiBase; + PchSpiBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + PciSegmentAnd8 (PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAN= D_MEMORY_SPACE); + PciSegmentWrite32 (PchSpiBase + R_SPI_CFG_BAR0, PCH_SPI_BASE_ADDRESS); + PciSegmentOr8 (PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_S= PACE); +} + +/** + This function Initial SPI services + + @retval EFI_STATUS Results of the installation of the SPI services +**/ +EFI_STATUS +EFIAPI +SpiServiceInit ( + VOID + ) +{ + EFI_STATUS Status; + PEI_SPI_INSTANCE *PeiSpiInstance; + SPI_INSTANCE *SpiInstance; + PCH_SPI_PPI *SpiPpi; + + Status =3D PeiServicesLocatePpi ( + &gPchSpiPpiGuid, + 0, + NULL, + (VOID **)&SpiPpi + ); + + if (Status !=3D EFI_SUCCESS) { + DEBUG ((DEBUG_INFO, "SpiServiceInit() Start\n")); + + // + // PCI Enumeratuion is not done till later in DXE + // Initlialize SPI BAR0 to a default value till enumeration is done + // also enable memory space decoding for SPI + // + InitSpiBar0 (); + + PeiSpiInstance =3D (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_= SPI_INSTANCE)); + if (NULL =3D=3D PeiSpiInstance) { + return EFI_OUT_OF_RESOURCES; + } + + SpiInstance =3D &(PeiSpiInstance->SpiInstance); + SpiProtocolConstructor (SpiInstance); + + PeiSpiInstance->PpiDescriptor.Flags =3D EFI_PEI_PPI_DESCRIPTOR_PPI | E= FI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PeiSpiInstance->PpiDescriptor.Guid =3D &gPchSpiPpiGuid; + PeiSpiInstance->PpiDescriptor.Ppi =3D &(SpiInstance->SpiProtocol); + + /// + /// Install the SPI PPI + /// + DEBUG ((DEBUG_INFO, "SPI PPI Installed\n")); + Status =3D PeiServicesInstallPpi (&PeiSpiInstance->PpiDescriptor); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "SpiServiceInit() End\n")); + } + else { + DEBUG ((DEBUG_INFO, "SPI PPI already installed\n")); + } + return Status; +} + +/** + Acquire pch spi mmio address. + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval PchSpiBar0 return SPI MMIO address +**/ +UINTN +AcquireSpiBar0 ( + IN SPI_INSTANCE *SpiInstance + ) +{ + return PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B= _SPI_CFG_BAR0_MASK); +} + +/** + Release pch spi mmio address. Do nothing. + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval None +**/ +VOID +ReleaseSpiBar0 ( + IN SPI_INSTANCE *SpiInstance + ) +{ +} + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @retval EFI_SUCCESS The protocol instance was properly initi= alized + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in S= MM phase + +**/ +EFI_STATUS +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + UINT64 SpiBaseAddress; + + SpiBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS= ) !=3D 0) { + return EFI_ACCESS_DENIED; + } + /// + /// Enable the access to the BIOS space for both read and write cycles + /// + PciSegmentOr8 ( + SpiBaseAddress + R_SPI_CFG_BC, + B_SPI_CFG_BC_WPD + ); + + return EFI_SUCCESS; +} + +/** + This function is a hook for Spi to enable BIOS Write Protect + + +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + UINT64 SpiBaseAddress; + + SpiBaseAddress =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + /// + /// Disable the access to the BIOS space for write cycles + /// + PciSegmentAnd8 ( + SpiBaseAddress + R_SPI_CFG_BC, + (UINT8) (~B_SPI_CFG_BC_WPD) + ); +} + +/** + Check if it's granted to do flash write. + + @retval TRUE It's secure to do flash write. + @retval FALSE It's not secure to do flash write. +**/ +BOOLEAN +IsSpiFlashWriteGranted ( + VOID + ) +{ + return TRUE; +} --=20 2.16.2.windows.1