From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.120, mailfrom: michael.a.kubacki@intel.com) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by groups.io with SMTP; Fri, 16 Aug 2019 17:16:54 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Aug 2019 17:16:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,395,1559545200"; d="scan'208";a="182319290" Received: from makuback-desk1.amr.corp.intel.com ([10.7.159.162]) by orsmga006.jf.intel.com with ESMTP; 16 Aug 2019 17:16:52 -0700 From: "Kubacki, Michael A" To: devel@edk2.groups.io Cc: Sai Chaganty , Chasel Chiu , Nate DeSimone , Liming Gao , Michael D Kinney , Ankit Sinha Subject: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances Date: Fri, 16 Aug 2019 17:15:45 -0700 Message-Id: <20190817001603.30632-20-michael.a.kubacki@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20190817001603.30632-1-michael.a.kubacki@intel.com> References: <20190817001603.30632-1-michael.a.kubacki@intel.com> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082 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/PeiDxeSmmBiosLockLib.inf | 40 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf | 48 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiDxeSmmPchEspiLib.inf | 38 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf | 38 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf | 37 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibCnl.inf | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf | 37 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf | 36 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLibCnl.inf | 39 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf | 31 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf | 43 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibCnl.inf | 32 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf | 39 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf | 24 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibCnl.inf | 86 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf | 41 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf | 49 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf | 42 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h | 117 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h | 45 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLibInternal.h | 16 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h | 35 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/BiosLockLib.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/GpioNativeLib.c | 234 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c | 1136 ++++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEspiLib.c | 505 ++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c | 82 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c | 127 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c | 272 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibClient.c | 87 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibCnl.c | 386 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c | 183 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c | 279 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c | 101 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c | 270 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLib.c | 516 ++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLibCnl.c | 181 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c | 372 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.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/PeiOcWdtLibNull.c | 23 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c | 307 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c | 778 ++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c | 739 ++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibCnl.c | 169 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c | 318 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c | 109 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c | 257 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c | 217 ++ 60 files changed, 13130 insertions(+) diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/PeiDxeSmmBiosLockLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/PeiDxeSmmBiosLockLib.inf new file mode 100644 index 0000000000..6db81f6cf3 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/PeiDxeSmmBiosLockLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmBiosLockLib +FILE_GUID = 64EBA6B1-CC36-4C2E-A0F5-D90199432E6C +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf new file mode 100644 index 0000000000..00d06591fc --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmGpioLib +FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = GpioLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf new file mode 100644 index 0000000000..2a53f42004 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchCycleDecodingLib +FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchEspiLib/PeiDxeSmmPchEspiLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiDxeSmmPchEspiLib.inf new file mode 100644 index 0000000000..a775210984 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiDxeSmmPchEspiLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchEspiLib +FILE_GUID = 7F25F990-7989-4413-B414-1EDE557E9389 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = PchEspiLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/PeiDxeSmmPchGbeLib/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/PeiDxeSmmPchGbeLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchGbeLib +FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf new file mode 100644 index 0000000000..7c67e0fa20 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchHsioLib +FILE_GUID = 6B2D3D0D-9A04-4E7C-AE84-1C2EF2E00E2E +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibCnl.inf new file mode 100644 index 0000000000..b9781de810 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibCnl.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchInfoLibCnl +FILE_GUID = 455CD363-0E78-46B7-8DD3-634003F1614F +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchPcieRpLib +FILE_GUID = B4129C2C-E0C5-4E04-A82A-C61D4F0B2C75 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchPcrLib/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/PeiDxeSmmPchPcrLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchPcrLib +FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = PchPcrLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PchInfoLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchPcrLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/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/PeiDxeSmmPchPmcLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchPmcLib +FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchSbiAccessLib/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/PeiDxeSmmPchSbiAccessLib/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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchSbiAccessLib +FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = PchSbiAccessLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PchSbiAccessLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLibCnl.inf new file mode 100644 index 0000000000..3bfada0b22 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchSerialIoLibCnl +FILE_GUID = 613A22A2-5736-40f8-909B-DF10EA389C72 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf new file mode 100644 index 0000000000..1becfc7a96 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchSerialIoUartLib +FILE_GUID = 55463A54-FD0D-4e8e-8D57-D54FAAEFDC2F +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = PchSerialIoUartLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PchSerialIoLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +PeiDxeSmmPchSerialIoUartLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/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/PeiDxeSmmPchWdtCommonLib/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 = 0x00010005 + BASE_NAME = PeiDxeSmmPchWdtCommonLib + FILE_GUID = 171F78D2-0A52-4692-8830-AB693791EA23 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = 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/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf new file mode 100644 index 0000000000..78e212eeb0 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPmcLib +FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiDxeSmmSataLib/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/PeiDxeSmmSataLibCnl.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 = 0x00010017 +BASE_NAME = PeiDxeSmmPchSataLibCnl +FILE_GUID = 5163ECE3-5372-47E1-B057-2282E753DD55 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = 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/PeiOcWdtLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf new file mode 100644 index 0000000000..37d0c80ea4 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.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 = 0x00010017 +BASE_NAME = PeiOcWdtLib +FILE_GUID = D5207C23-3632-4078-A671-3B5C364B2BDB +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +LIBRARY_CLASS = 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/PeiOcWdtLibNull/PeiOcWdtLibNull.inf new file mode 100644 index 0000000000..68ff41ef7f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.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 = 0x00010017 +BASE_NAME = PeiOcWdtLib +FILE_GUID = DB65B36B-E276-4A2b-AB20-61764889E483 +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +LIBRARY_CLASS = 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/PeiPchPolicyLib/PeiPchPolicyLibCnl.inf new file mode 100644 index 0000000000..49e63cfc51 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibCnl.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 = 0x00010017 +BASE_NAME = PeiPchPolicyLibCnl +FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5 +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +LIBRARY_CLASS = 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/PeiPchResetLib/PeiPchResetLib.inf new file mode 100644 index 0000000000..41e339a2e8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.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 = 0x00010017 +BASE_NAME = PeiPchResetLib +FILE_GUID = DB91FFF0-5B99-4A88-9EC8-183A2106DCA2 +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +LIBRARY_CLASS = PchResetLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/PeiResetSystemLib/PeiResetSystemLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf new file mode 100644 index 0000000000..f8f8bf1b66 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.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 = 0x00010017 +BASE_NAME = PeiResetSystemLib +FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732 +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +UEFI_SPECIFICATION_VERSION = 2.00 +LIBRARY_CLASS = ResetSystemLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/PeiSpiLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf new file mode 100644 index 0000000000..fb2fad78d3 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf @@ -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 = 0x00010017 +BASE_NAME = PeiSpiLib +FILE_GUID = 4998447D-7948-448F-AB75-96E24E18FF23 +VERSION_STRING = 1.0 +MODULE_TYPE = PEIM +LIBRARY_CLASS = SpiLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h new file mode 100644 index 0000000000..7a480b6cad --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.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 type) + 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 successfully + @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/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h new file mode 100644 index 0000000000..79e03fef44 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.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/PeiDxeSmmPchSerialIoLib/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/PeiDxeSmmPchSerialIoLib/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/PeiPchPolicyLib/PeiPchPolicyLibrary.h new file mode 100644 index 0000000000..abd7e63365 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.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/PeiDxeSmmBiosLockLib/BiosLockLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/BiosLockLib.c new file mode 100644 index 0000000000..20c024e893 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/BiosLockLib.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 from a valid source. + + Bios should always enable LockDownConfig.BiosLock policy to set Bios Lock bit in FRC. + If capsule udpate is enabled, it's expected to not do BiosLock by setting BiosLock policy disable + so it can udpate BIOS region. + After flash update, it should utilize this lib to do BiosLock for security. +**/ +VOID +BiosLockEnable ( + VOID + ) +{ + UINT64 LpcBaseAddress; + UINT64 SpiBaseAddress; + + LpcBaseAddress = 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 = 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 by setting + /// SPI/eSPI/LPC PCI offset DCh[1] = 1b. + /// When this bit is set, attempts to write the Write Protect Disable (WPD) 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] = 0b to enable + /// BIOS region protection before exiting the SMI handler. + /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 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 PCH by setting + /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 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 BWG 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] = 1b for SPI or setting eSPI PCI offset DCh[1] = 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/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c new file mode 100644 index 0000000000..76eb3a9b81 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.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 = GPIO_GET_PAD_POSITION (PadNumber); + DwNum = GPIO_GET_DW_NUM (PadNumber); + + if (DwNum >= GPIO_GROUP_DW_NUMBER) { + ASSERT (FALSE); + return; + } + // + // Update value to be programmed in HOSTSW_OWN register + // + GroupDwData[DwNum].HostSoftOwnRegMask |= (GpioConfig->HostSoftPadOwn & 0x1) << PadBitPosition; + GroupDwData[DwNum].HostSoftOwnReg |= (GpioConfig->HostSoftPadOwn >> 0x1) << PadBitPosition; + + // + // Update value to be programmed in GPI_GPE_EN register + // + GroupDwData[DwNum].GpiGpeEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition; + GroupDwData[DwNum].GpiGpeEnReg |= ((GpioConfig->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition; + + // + // Update value to be programmed in GPI_NMI_EN register + // + GroupDwData[DwNum].GpiNmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition; + GroupDwData[DwNum].GpiNmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition; + + // + // Update value to be programmed in GPI_SMI_EN register + GroupDwData[DwNum].GpiSmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition; + GroupDwData[DwNum].GpiSmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntSmi) >> 2) << PadBitPosition; + if ((GpioConfig->InterruptConfig & GpioIntSmi) == GpioIntSmi) { + GroupDwData[DwNum].HostSoftOwnRegMask |= 1 << PadBitPosition; + GroupDwData[DwNum].HostSoftOwnReg |= 1 << PadBitPosition; + } + + // + // Update information on Pad Configuration Lock + // + GroupDwData[DwNum].ConfigUnlockMask |= ((GpioConfig->LockConfig >> 1) & 0x1) << PadBitPosition; + + // + // Update information on Pad Configuration Lock Tx + // + GroupDwData[DwNum].OutputUnlockMask |= ((GpioConfig->LockConfig >> 3) & 0x1) << PadBitPosition; + + // + // if pad in GpioMode is an output default action should be to leave output unlocked + // + if ((GpioConfig->PadMode == GpioPadModeGpio) && + (GpioConfig->Direction == GpioDirOut) && + ((GpioConfig->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioLockDefault)) { + GroupDwData[DwNum].OutputUnlockMask |= 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 table + @param[in] GpioInitTableAddress GPIO initialization table + @param[in] Index Index of GPIO Initialization table record + + @retval EFI_SUCCESS The function completed successfully + @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 = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GpioData = &GpioInitTableAddress[Index]; + Group = GpioGetGroupFromGpioPad (GpioData->GpioPad); + GroupIndex = 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 = &GpioInitTableAddress[Index]; + if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) { + //if next pad is from different group then break loop + break; + } + + PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad); + // + // Check if legal pin number + // + if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for group %d\n", PadNumber, GroupIndex)); + return EFI_INVALID_PARAMETER; + } + + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber); + DwNum = GPIO_GET_DW_NUM (PadNumber); + + if (DwNum >= GPIO_GROUP_DW_NUMBER) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + // + // Update pads which need to be unlocked + // + PadsToUnlock[DwNum] |= 0x1 << PadBitPosition; + + //Move to next item + Index++; + } + + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + // + // Unlock pads + // + if (PadsToUnlock[DwNum] != 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 successfully + @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 = GpioPadOwnHost; + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + Index = 0; + while (Index < NumberOfItems) { + + GpioData = &GpioInitTableAddress[Index]; + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad); + GpioCom = 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 - PadRstCfg. This means that if + // PadRstCfg != Powergood GpioPad will have its configuration locked despite it being not the + // one desired by BIOS. Before reconfiguring all pads they will get unlocked. + // + GpioUnlockPadsForAGroup (NumberOfItems, GpioInitTableAddress, Index); + + ZeroMem (GroupDwData, sizeof (GroupDwData)); + // + // Loop through pads for one group. If pad belongs to a different group then + // break and move to register programming. + // + while (Index < NumberOfItems) { + + GpioData = &GpioInitTableAddress[Index]; + if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) { + //if next pad is from different group then break loop + break; + } + + PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad); + + DEBUG_CODE_BEGIN (); + // + // Check if legal pin number + // + if (PadNumber >= 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 != GpioPadOwnHost) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber)); + DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync between 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) == GpioIntSci) && + ((GpioData->GpioConfig.LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != 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 = S_GPIO_PCR_PADCFG * PadNumber + GpioGroupInfo[GroupIndex].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 = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + // + // Write HOSTSW_OWN registers + // + if (GpioGroupInfo[GroupIndex].HostOwnOffset != NO_REGISTER_FOR_PROPERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4), + ~GroupDwData[DwNum].HostSoftOwnRegMask, + GroupDwData[DwNum].HostSoftOwnReg + ); + } + + // + // Write GPI_GPE_EN registers + // + if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4), + ~GroupDwData[DwNum].GpiGpeEnRegMask, + GroupDwData[DwNum].GpiGpeEnReg + ); + } + + // + // Write GPI_NMI_EN registers + // + if (GpioGroupInfo[GroupIndex].NmiEnOffset != NO_REGISTER_FOR_PROPERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].NmiEnOffset + DwNum * 0x4), + ~GroupDwData[DwNum].GpiNmiEnRegMask, + GroupDwData[DwNum].GpiNmiEnReg + ); + } else if (GroupDwData[DwNum].GpiNmiEnReg != 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 != NO_REGISTER_FOR_PROPERTY) { + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].SmiEnOffset + DwNum * 0x4), + ~GroupDwData[DwNum].GpiSmiEnRegMask, + GroupDwData[DwNum].GpiSmiEnReg + ); + } else if (GroupDwData[DwNum].GpiSmiEnReg != 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, GroupDwData[DwNum].ConfigUnlockMask); + } + + // + // Update Pad Output unlock data + // + if (GroupDwData[DwNum].OutputUnlockMask) { + GpioStoreGroupDwUnlockOutputData (GroupIndex, DwNum, GroupDwData[DwNum].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 = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GpioGroupLowest = GpioGetLowestGroup (); + GpioGroupHighest = GpioGetHighestGroup (); + + for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) { + GroupIndex = GpioGetGroupIndexFromGroup (Group); + // + // Check if group has GPI IS register + // + if (GpioGroupInfo[GroupIndex].GpiIsOffset != NO_REGISTER_FOR_PROPERTY) { + // + // Clear all GPI_IS Status bits by writing '1' + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has GPI_GPE_STS register + // + if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset != NO_REGISTER_FOR_PROPERTY) { + // + // Clear all GPI_GPE_STS Status bits by writing '1' + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has SMI_STS register + // + if (GpioGroupInfo[GroupIndex].SmiStsOffset != NO_REGISTER_FOR_PROPERTY) { + // + // Clear all SMI_STS Status bits by writing '1' + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4), + 0xFFFFFFFF + ); + } + } + + // + // Check if group has NMI_STS register + // + if (GpioGroupInfo[GroupIndex].NmiStsOffset != NO_REGISTER_FOR_PROPERTY) { + // + // Clear all NMI_STS Status bits by writing '1' + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) { + MmioWrite32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[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 default 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 same group are + placed in adjacent records of the table. + Although function can enable pads for Native mode, such programming is done + 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 successfully + @retval EFI_INVALID_PARAMETER Invalid group or pad number +**/ +EFI_STATUS +GpioConfigurePads ( + IN UINT32 NumberOfItems, + IN GPIO_INIT_CONFIG *GpioInitTableAddress + ) +{ + EFI_STATUS Status; + Status = GpioConfigurePch (NumberOfItems, GpioInitTableAddress); + GpioClearAllGpioInterrupts (); + return Status; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c new file mode 100644 index 0000000000..0be50f75df --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.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 applicable 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 = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + GroupIndex = GpioGetGroupIndexFromGroup (Group); + + if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ()) || (GroupIndex >= GpioGroupInfoLength)) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range 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() functions +// +typedef enum { + GpioHostOwnershipRegister = 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 (parameter applicable in accessing whole register). + For group which has less then 32 pads per 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 = NO_REGISTER_FOR_PROPERTY; + GroupIndex = GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioHostOwnershipRegister: + RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset; + break; + case GpioGpeEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset; + break; + case GpioGpeStatusRegister: + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset; + break; + case GpioSmiEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset; + break; + case GpioSmiStatusRegister: + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset; + break; + case GpioNmiEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset; + break; + case GpioPadConfigLockRegister: + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset; + break; + case GpioPadLockOutputRegister: + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset; + break; + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset == NO_REGISTER_FOR_PROPERTY) { + *ReadVal = 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 == GpioPadConfigLockRegister) || (RegType == GpioPadLockOutputRegister)) { + // + // 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 += DwNum * 0x8; + } else { + RegOffset += DwNum * 0x4; + } + + *ReadVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset)); +} + +/** + This function determines if the group is SMI capable. + + @param[in] Group GPIO group + @param[in] DwNum Register number for current group (parameter applicable in accessing whole register). + For group which has less then 32 pads per 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 = GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset; + + // + // Check if selected register exists + // + if (RegOffset == 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 (parameter applicable in accessing whole register). + For group which has less then 32 pads per 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 = GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset; + + // + // Check if selected register exists + // + if (RegOffset == 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 (parameter applicable in accessing whole register). + For group which has less then 32 pads per 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 value +**/ +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 = FALSE; + PadCfgLock = 0; + RegOffset = NO_REGISTER_FOR_PROPERTY; + GroupIndex = GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioHostOwnershipRegister: + RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset; + break; + case GpioGpeEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset; + Lockable = TRUE; + break; + case GpioGpeStatusRegister: + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset; + break; + case GpioSmiEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset; + Lockable = TRUE; + break; + case GpioSmiStatusRegister: + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset; + break; + case GpioNmiEnableRegister: + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset; + Lockable = TRUE; + break; + case GpioPadConfigLockRegister: + case GpioPadLockOutputRegister: + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset == 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 reprogrammed + // + Status = 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 reconfigured + // are not in locked state + // + PadCfgLock = 0; + } + } + } + + // + // If there are more then 32 pads per group then certain + // group information would be split into more then one DWord register. + // + RegOffset += DwNum * 0x4; + + MmioAndThenOr32 ( + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset), + RegAndMask, + RegOrMask + ); + + if (Lockable && PadCfgLock) { + // + // Lock previously unlocked pads + // + Status = 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 per group DwNum must be 0. + @param[in] LockRegAndMask Mask which will be AND'ed with Lock register value + @param[in] LockRegOrMask Mask which will be Or'ed with Lock register 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 = 0; + NewLockVal = 0; + + RegOffset = NO_REGISTER_FOR_PROPERTY; + GroupIndex = GpioGetGroupIndexFromGroup (Group); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + switch (RegType) { + case GpioPadConfigLockRegister: + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset; + GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldLockVal); + break; + case GpioPadLockOutputRegister: + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset; + GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldLockVal); + break; + default: + break; + } + + // + // Check if selected register exists + // + if (RegOffset == 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 += DwNum *0x8; + + NewLockVal = (OldLockVal & LockRegAndMask) | LockRegOrMask; + + Status = 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 type) + 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[] = { + GpioResumeReset, + GpioHostDeepReset, + GpioPlatformReset}; + static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] = { + GpioDswReset, + GpioHostDeepReset, + GpioPlatformReset, + GpioResumeReset}; + + Group = 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 successfully + @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 = GpioGetGroupFromGpioPad (GpioPad); + + switch (GpioResetConfig) { + case GpioResetDefault: + *PadRstCfg = 0x0; + break; + case GpioHostDeepReset: + *PadRstCfg = V_GPIO_PCR_RST_CONF_DEEP_RST; + break; + case GpioPlatformReset: + *PadRstCfg = V_GPIO_PCR_RST_CONF_GPIO_RST; + break; + case GpioResumeReset: + if (GpioIsDswGroup (Group)) { + *PadRstCfg = V_GPIO_PCR_RST_CONF_RESUME_RST; + } else { + *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD; + } + break; + case GpioDswReset: + if (GpioIsDswGroup (Group)) { + *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioDswReset: %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 = (PadCfgDwReg[0] & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_CONF; + + GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg ( + GpioPad, + PadRstCfg + ); + + // + // Get how interrupt is triggered (RxEvCfg) + // + GpioConfig->InterruptConfig = ((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 |= ((PadCfgDwReg[0] & (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_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 = ((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) == 0) { + GpioConfig->Direction |= ((PadCfgDwReg[0] & B_GPIO_PCR_RXINV) >> (N_GPIO_PCR_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_INV_BIT_POS); + } + + // + // Get GPIO output state (GPIOTxState) + // + GpioConfig->OutputState = ((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 = ((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 = ((PadCfgDwReg[0] & B_GPIO_PCR_PAD_MODE) >> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS); + + // + // Get GPIO termination (Term) + // + GpioConfig->ElectricalConfig = ((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 successfully + @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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + if (!GpioIsPadHostOwned (GpioPad)) { + return EFI_UNSUPPORTED; + } + + // + // Read PADCFG DW0 register + // + PadCfgDwReg[0] = GpioReadPadCfgReg (GpioPad, 0); + + // + // Read PADCFG DW1 register + // + PadCfgDwReg[1] = GpioReadPadCfgReg (GpioPad, 1); + + // + // Read PADCFG DW2 register + // + PadCfgDwReg[2] = 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 = (((RegVal >> PadBitPosition) & 0x1) << (N_GPIO_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 = ((!((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 |= ((!((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 = GpioPadRstCfgFromResetConfig ( + GpioPad, + GpioConfig->PowerConfig, + &PadRstCfg + ); + if (EFI_ERROR (Status)) { + return; + } + + PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RST_CONF); + PadCfgDwReg[0] |= PadRstCfg << N_GPIO_PCR_RST_CONF; + + // + // Configure how interrupt is triggered (RxEvCfg) + // + PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RX_LVL_EDG); + PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_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] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) == GpioHardwareDefault) ? 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] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_GPIO_PCR_RX_NMI_ROUTE); + + // + // Configure GPIO direction (GPIORxDis and GPIOTxDis) + // + PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_GPIO_PCR_RXDIS | B_GPIO_PCR_TXDIS)); + PadCfgDwReg[0] |= (((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] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RXINV); + PadCfgDwReg[0] |= (((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] |= ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TX_STATE); + PadCfgDwReg[0] |= (((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] |= ((((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RX_RAW1); + PadCfgDwReg[0] |= (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_GPIO_PCR_RX_RAW1); + + // + // Configure GPIO Pad Mode (PMode) + // + PadCfgDwRegMask[0] |= ((((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> N_GPIO_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_PAD_MODE); + PadCfgDwReg[0] |= (((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] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TERM); + PadCfgDwReg[1] |= (((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 successfully + @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 = EFI_SUCCESS; + ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg)); + ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask)); + + Group = GpioGetGroupFromGpioPad (GpioPad); + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber); + DwNum = 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) == GpioIntSci) && + ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != GpioPadConfigUnlock)){ + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a for SCI is not unlocked!\n", GpioName (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) == GpioIntSmi) { + HostSoftOwnRegMask = 1 << PadBitPosition; + HostSoftOwnReg = 1 << PadBitPosition; + } else { + HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadBitPosition; + HostSoftOwnReg = (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 = (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition; + + // + // Write GPI_GPE_EN registers + // + GpioWriteReg ( + GpioGpeEnableRegister, + Group, + DwNum, + ~GpiGpeEnRegMask, + GpiGpeEnReg + ); + + // + // Update value to be programmed in GPI_NMI_EN register + // + GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition; + + if (GpioIsNmiSupportedByGroupDw (Group, DwNum)) { + GpioWriteReg ( + GpioNmiEnableRegister, + Group, + DwNum, + ~GpiNmiEnRegMask, + GpiNmiEnReg + ); + } else { + if (GpiNmiEnReg == 0) { + // + // Not all GPIO have NMI capabilities. Since we always try to program this register, + // even when not enabling NMI for a pad so do not report such access as an error + // + Status = EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting NMI\n", GpioGetGroupName (GroupIndex))); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } + + // + // Update value to be programmed in GPI_SMI_EN register + // + GpiSmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition; + GpiSmiEnReg = ((GpioData->InterruptConfig & GpioIntSmi) >> 2) << PadBitPosition; + + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) { + GpioWriteReg ( + GpioSmiEnableRegister, + Group, + DwNum, + ~GpiSmiEnRegMask, + GpiSmiEnReg + ); + } else { + if (GpiSmiEnReg == 0) { + // + // Not all GPIO have SMI capabilities. Since we always try to program this register, + // even when not enabling SMI for a pad so do not report such access as an error + // + Status = EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting SMI\n", GpioGetGroupName (GroupIndex))); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } + + // + // Store unlock data + // + if (GpioData->LockConfig != GpioLockDefault) { + LockConfig = GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK; + // + // If pad in GpioMode is an output default action should be to leave output unlocked + // + if ((GpioData->PadMode == GpioPadModeGpio) && + (GpioData->Direction == GpioDirOut) && + ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioLockDefault)) { + LockConfig |= GpioOutputStateUnlock; + } else { + LockConfig |= GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK; + } + Status = 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 = GpioReadPadCfgReg (GpioPad, 0); + + *OutputVal = (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 = GpioReadPadCfgReg (GpioPad, 0); + + *InputVal = (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 = GpioReadPadCfgReg (GpioPad, 1); + + *IrqNum = (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 = GpioReadPadCfgReg (GpioPad, 0); + + *InvertState = (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 = EFI_SUCCESS; + + if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) { + RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_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_INT_SOURCE_BIT_POS) != GpioHardwareDefault) { + + IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_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) == GpioIntSci) { + GpeEnable = 0x1; + } else { + GpeEnable = 0x0; + } + + PadNumber = 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) == GpioIntNmi) { + NmiEnable = 0x1; + } else { + NmiEnable = 0x0; + } + + IsNmiSupported = 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 == 0) { + // + // Not all GPIO have NMI capabilities. Since we always try to program this register, + // even when not enabling NMI for a pad so do not report such access 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_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) != GpioHardwareDefault) { + TermValue = ((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_RESET_BIT_POS) != GpioHardwareDefault) { + + // + // Reset configuration depends on group type. + // This field requires support for new and deprecated settings. + // + Status = 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 = GpioReadPadCfgReg (GpioPad, 0); + + // + // Get Reset Type (PadRstCfg) + // + PadRstCfg = (PadCfgDw0Reg & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_CONF; + + *Value = GpioResetConfigFromPadRstCfg ( + GpioPad, + PadRstCfg + ); + + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO Host Software Pad Ownership for certain group + + @param[in] Group GPIO group + @param[in] DwNum Host Ownership register number for current group. + For group which has less then 32 pads per group DwNum must be 0. + @param[out] HostSwRegVal Value of Host Software Pad Ownership register + 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 group + + @param[in] Group GPIO group + @param[in] DwNum Host Ownership register number for current group + For group which has less then 32 pads per group DwNum must be 0. + @param[in] HostSwRegVal Value of Host Software Pad Ownership register + 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 = GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioHostOwnershipRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &HostSwRegVal + ); + + *PadHostSwOwn = (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 = 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 = GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Calculate RegOffset using Pad Ownership offset and GPIO Pad number. + // One DWord register contains information for 8 pads. + // + RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4; + + // + // Calculate pad bit position within DWord register + // + PadNumber %= 8; + Mask = (BIT1 | BIT0) << (PadNumber * 4); + + PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset)); + + *PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4)); + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Lock for pads within one group + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLock register number for current group. + For group which has less then 32 pads per 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 = GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioPadConfigLockRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &PadCfgLockRegVal + ); + + *PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1; + + return EFI_SUCCESS; +} + +/** + This procedure will check state of Pad Config Tx Lock for pads within one group + + @param[in] Group GPIO group + @param[in] DwNum PadCfgLockTx register number for current group. + For group which has less then 32 pads per 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 = GpioGetPadNumberFromGpioPad (GpioPad); + + GpioReadReg ( + GpioPadLockOutputRegister, + GpioGetGroupFromGpioPad (GpioPad), + GPIO_GET_DW_NUM (PadNumber), + &PadCfgLockTxRegVal + ); + + *PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 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 group. + For group which has less then 32 pads per group DwNum must be 0. + @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked, + 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = 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 group. + For group which has less then 32 pads per group DwNum must be 0. + @param[in] PadsToLock Bitmask for pads which are going to be locked + 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = 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 group. + 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 per group DwNum must be 0. + @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked, + 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = 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 group. + For group which has less then 32 pads per group DwNum must be 0. + @param[in] PadsToLockTx Bitmask for pads which are going to be locked, + 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = 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 group + 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 = GpioGetGroupDwToGpeDwX ( + GroupToGpeDw0, + &GroupDw[0], + GroupToGpeDw1, + &GroupDw[1], + GroupToGpeDw2, + &GroupDw[2] + ); + + for (Index = 0; Index < ARRAY_SIZE (GroupDw); Index++) { + if (GroupDw[Index] != 0) { + Status = 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 = 0; GpeDwXIndex < 3; GpeDwXIndex++) { + for (Index = 0; Index < GpioGpeMapLength; Index++) { + + if (GpioGpeMap[Index].PmcGpeDwxVal == PmcGpeDwXValue[GpeDwXIndex]) { + GroupToGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].Group; + GroupDwForGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].GroupDw; + break; + } + } + } + + if ((GroupToGpeDwX[0] == 0) || + (GroupToGpeDwX[1] == 0) || + (GroupToGpeDwX[2] == 0)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + *GroupToGpeDw0 = GroupToGpeDwX[0]; + *GroupDwForGpeDw0 = GroupDwForGpeDwX[0]; + *GroupToGpeDw1 = GroupToGpeDwX[1]; + *GroupDwForGpeDw1 = GroupDwForGpeDwX[1]; + *GroupToGpeDw2 = GroupToGpeDwX[2]; + *GroupDwForGpeDw2 = 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 group + 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 == GroupToGpeDw1) || + (GroupToGpeDw0 == GroupToGpeDw2) || + (GroupToGpeDw1 == GroupToGpeDw2)) { + return EFI_INVALID_PARAMETER; + } + + GroupToGpeDwX[0] = GroupToGpeDw0; + GroupDwForGpeDwX[0] = GroupDwForGpeDw0; + GroupToGpeDwX[1] = GroupToGpeDw1; + GroupDwForGpeDwX[1] = GroupDwForGpeDw1; + GroupToGpeDwX[2] = GroupToGpeDw2; + GroupDwForGpeDwX[2] = GroupDwForGpeDw2; + + GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength); + + for (GpeDwXIndex = 0; GpeDwXIndex < 3; GpeDwXIndex++) { + for (Index = 0; Index < GpioGpeMapLength; Index++) { + + if ((GpioGpeMap[Index].Group == GroupToGpeDwX[GpeDwXIndex]) && + (GpioGpeMap[Index].GroupDw == GroupDwForGpeDwX[GpeDwXIndex])) { + PmcGpeDwx[GpeDwXIndex] = GpioGpeMap[Index].PmcGpeDwxVal; + GpioGpeDwx[GpeDwXIndex] = GpioGpeMap[Index].GpioGpeDwxVal; + break; + } + } + + if (Index == 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 = (UINT32) ~(B_GPIO_PCR_MISCCFG_GPE0_DW2 | B_GPIO_PCR_MISCCFG_GPE0_DW1 | B_GPIO_PCR_MISCCFG_GPE0_DW0); + Data32Or = (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 = GpioGetComSbiPortIds (&GpioComSbiIds); + + // + // Program MISCCFG register for each community + // + for (GpioComIndex = 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 (GpioSetGroupToGpeDwX()) + what results in the fact that certain Pad can cause different General Purpose Event. Only three + GPIO groups can be mapped to cause unique GPE (1-tier), all others groups 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = 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 = 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 = 0; Index < 3; Index++) { + if ((Group == GroupToGpeDwX[Index]) && (PadNumber >= (32 * GroupDw[Index])) && (PadNumber < (32 * (GroupDw[Index] + 1)))) { + *GpeNumber = 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 = 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + DwNum = GPIO_GET_DW_NUM (PadNumber); + PadBitPosition = 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 = GpioGetLowestGroup (); + GroupMax = GpioGetHighestGroup (); + + for (Group = GroupMin; Group <= GroupMax; Group++) { + // + // Clear all GPI SMI STS + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); 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 = GpioGetLowestGroup (); + GroupMax = GpioGetHighestGroup (); + + for (Group = GroupMin; Group <= GroupMax; Group++) { + // + // Disable all GPI SMI + // + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) { + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) { + SmiEnRegVal = 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 = GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + + if (!GpioIsPadValid (GpioPad)) { + return EFI_UNSUPPORTED; + } + + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); + + *GpiNum = 0; + + for (Index = 0; Index < GroupIndex; Index++) { + *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup); + } + *GpiNum += (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 = GpioGetGpeNumber (GpioPad, &Data32); + if (EFI_ERROR (Status)) { + DEBUG (( DEBUG_ERROR, "GpioCheckFor2Tier: Failed to get GPE number. Status: %r\n", Status )); + return FALSE; + } + + if (Data32 == 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + DwNum = GPIO_GET_DW_NUM (PadNumber); + PadBitPosition = 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 = GpioGetGroupFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + DwNum = GPIO_GET_DW_NUM (PadNumber); + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber); + + // + // Read GPI GPE Status bits + // + GpioReadReg ( + GpioGpeStatusRegister, + Group, + DwNum, + &GpeStsRegVal + ); + + *Data = (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 enabled. + 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 = GpioGetLowestGroup (); + GroupMax = GpioGetHighestGroup (); + + for (Group = GroupMin; Group <= GroupMax; Group++) { + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) { + + UnlockedPads = GpioGetGroupDwUnlockPadConfigMask (GpioGetGroupIndexFromGroup (Group), DwNum); + + Status = GpioLockPadCfgForGroupDw (Group, DwNum, (UINT32)~UnlockedPads); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + UnlockedPads = GpioGetGroupDwUnlockOutputMask (GpioGetGroupIndexFromGroup (Group), DwNum); + + Status = GpioLockPadCfgTxForGroupDw (Group, DwNum, (UINT32)~UnlockedPads); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + } + } + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNames.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNames.c new file mode 100644 index 0000000000..ec33d06156 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNames.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 = GpioGetGroupNameInfo (GroupIndex); + if (GroupNameInfo == 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_LENGTH_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 == NULL) { + ASSERT (FALSE); + return NULL; + } + if ((GpioNameBufferSize < GPIO_NAME_LENGTH_MAX) || !GpioIsPadValid (GpioPad)) { + ASSERT (FALSE); + *GpioNameBuffer = 0; + return NULL; + } + + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); + GroupNameInfo = GpioGetGroupNameInfo (GroupIndex); + if (GroupNameInfo == NULL) { + return NULL; + } + + FirstUniquePadNumber = GpioGetPadNumberFromGpioPad (GroupNameInfo->FirstUniqueGpio); + if ((PadNumber < FirstUniquePadNumber) || (GroupNameInfo->GroupUniqueNames == NULL)) { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a%d", GpioGetGroupName (GroupIndex), PadNumber); + } else { + if (PadNumber - FirstUniquePadNumber < GroupNameInfo->UniqueNamesTableSize) { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a", GroupNameInfo->GroupUniqueNames[PadNumber - FirstUniquePadNumber]); + } else { + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%08X", GpioPad); + ASSERT (FALSE); + } + } + + return GpioNameBuffer; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c new file mode 100644 index 0000000000..9b71cb1d95 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.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 = GpioGetGroupInfoTable (&GpioGroupInfoLength); + GroupIndex = GpioGetGroupIndexFromGroup (Group); + + if ((UINTN) GroupIndex >= 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 = 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 = GpioGetPadMode (SataGpGpio.Pad, &GpioMode); + if ((EFI_ERROR (Status)) || (GpioMode != SataGpGpio.Mode)) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c new file mode 100644 index 0000000000..24afbbf712 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/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) != 0) { + DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n", Address)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Status = PchDmiSetTcoBase (Address); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + SmbusBase = 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) == 0xFFFF) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + // + // Verify TCO base is not locked. + // + if ((PciSegmentRead8 (SmbusBase + R_SMBUS_CFG_TCOCTL) & B_SMBUS_CFG_TCOCTL_TCO_BASE_LOCK) != 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 == 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 = 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 requirements. + + @param[in] Address Address for generic IO range decoding. + @param[in] Length Length of generic IO range. + + @retval TRUE Passed IO range meets requirements + @retval FALSE Passed IO range does not meets requirements. +**/ +STATIC +BOOLEAN +IsLpcIoRangeValid ( + IN UINT32 Address, + IN UINT32 Length + ) +{ + UINT32 Index; + UINT32 NumRanges; + + STATIC struct EXCEPT_RANGE { + UINT8 Start; + UINT8 Length; + } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08}, {0x80, 0x10}, {0xC0, 0x40} }; + + NumRanges = 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 ranges: + // 0x00-0x1F, + // 0x44-0x4B, + // 0x54-0x5F, + // 0x68-0x6F, + // 0x80-0x8F, + // 0xC0-0xFF + // + if (((Length & (Length - 1)) != 0) || + ((Address & (UINT16) ~B_LPC_CFG_GENX_DEC_IOBAR) != 0) || + (Length > 256)) { + return FALSE; + } + if (Address < 0x100) { + for (Index = 0; Index < NumRanges; Index++) { + if ((Address >= ExceptRanges[Index].Start) && + ((Address + Length) <= ((UINTN) ExceptRanges[Index].Start + (UINTN) ExceptRanges[Index].Length))) { + break; + } + } + if (Index >= NumRanges) { + return FALSE; + } + } + + return TRUE; +} + +/** + Function checks if passed Generic LPC IO Range is already in Gen IO Range list + + @param[in] Address Address for generic IO range decoding. + @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 = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + CurrentBaseAddr = GenIoRangeList->Range[Index].BaseAddr; + CurrentLength = GenIoRangeList->Range[Index].Length; + if (GenIoRangeList->Range[Index].Enable == 0) { + continue; + } + if ((Address >= CurrentBaseAddr) && ((Address + Length) <= (CurrentBaseAddr + CurrentLength))) { + return TRUE; + } + } + + return FALSE; +} + +/** + Function checks if passed Generic LPC IO Range overlaps with existing range + + @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 = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + CurrentBaseAddr = GenIoRangeList->Range[Index].BaseAddr; + CurrentLength = GenIoRangeList->Range[Index].Length; + if (GenIoRangeList->Range[Index].Enable == 0) { + continue; + } + + if ((Address >= CurrentBaseAddr) && + (Address <= (CurrentBaseAddr + CurrentLength))) { + return TRUE; + } else if (((Address + Length) >= CurrentBaseAddr) && + ((Address + Length) <= (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 = 0; Index < ListLength; Index++) { + if (GenIoRangeList->Range[Index].Enable == 0) { + *RangeIndex = 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 range 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 == NULL) || (SlaveId >= SlaveId_Max)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + LpcBase = LpcPciBase (); + + if (SlaveId == SlaveEspiCS1) { + GenIoReg = R_ESPI_CFG_CS1GIR1; + } else { + GenIoReg = R_LPC_CFG_GEN1_DEC; + } + + for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) { + if ((SlaveId == SlaveEspiCS1) && + (Index > 0)) { + // For eSPI CS1# we have only one range. Reset remaining entries to zero. + GenIoRangeList->Range[Index].BaseAddr = 0; + GenIoRangeList->Range[Index].Enable = 0; + GenIoRangeList->Range[Index].Length = 0; + continue; + } + Data32 = PciSegmentRead32 (LpcBase + GenIoReg + Index * 4); + GenIoRangeList->Range[Index].BaseAddr = Data32 & B_LPC_CFG_GENX_DEC_IOBAR; + GenIoRangeList->Range[Index].Length = ((Data32 & B_LPC_CFG_GENX_DEC_IODRA) >> 16) + 4; + GenIoRangeList->Range[Index].Enable = 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 == SlaveEspiCS1) { + Status = LpcEspiGenIoRangeGetHelper (SlaveLpcEspiCS0, &GenIoRangeList); + if (!EFI_ERROR (Status)) { + if (FindOverlappingGenIoRange (Address, Length, &GenIoRangeList) || + IsRangeInList (Address, Length, &GenIoRangeList)) { + return TRUE; + } + } + } else { + Status = 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 CS1#) of Mask, Address, and Enable. + 2. Program LPC/eSPI Generic IO Range in DMI + + @param[in] Address Address for generic IO range decoding. + @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 passed. + @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 >= SlaveId_Max)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Read current Generic IO configuration + // + Status = LpcEspiGenIoRangeGetHelper (SlaveId, &GenIoRangeList); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if passed Generic IO range is already covered in current configuration + // + if (IsRangeInList (Address, Length, &GenIoRangeList)) { + return EFI_SUCCESS; + } + + // + // Check if passed Generic IO range conflicting with other eSPI CS decoding + // + if (IsRangeColliding (Address, Length, SlaveId)) { + return EFI_UNSUPPORTED; + } + + if (SlaveId == SlaveEspiCS1) { + GenIoReg = R_ESPI_CFG_CS1GIR1; + ListLength = ESPI_CS1_GEN_IO_RANGE_MAX; + } else { + GenIoReg = R_LPC_CFG_GEN1_DEC; + ListLength = PCH_LPC_GEN_IO_RANGE_MAX; + } + + RangeIndex = ListLength; + // + // Check if there is an empty Generic IO range register + // + if (FindEmptyGenIoRange (&GenIoRangeList, ListLength, &RangeIndex) == FALSE) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Program decoding in DMI and LPC/eSPI registers + // + if (SlaveId == SlaveEspiCS1) { + ASSERT (RangeIndex == 0); + Status = PchDmiSetEspiCs1GenIoRange (Address, Length); + } else { + Status = PchDmiSetLpcGenIoRange (Address, Length, RangeIndex); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Program LPC/eSPI generic IO range register accordingly. + // + Data32 = (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA); + Data32 |= (UINT32) Address; + Data32 |= B_LPC_CFG_GENX_DEC_EN; + + // + // Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI CS1#) 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 0xFFFF, and the length must be power of 2 + and less than or equal to 256. Moreover, the address must be length aligned. + 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,RTC,LPC,PMC or terminated inside P2SB + but all predefined and can't be changed. IO range below 0x100 will be rejected 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 passed. + @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, SlaveLpcEspiCS0); +} + +/** + 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 decoding. + @param[in] Length Length of generic IO range. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER Invalid base address or length passed. + @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, SlaveEspiCS1); +} + +/** + 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 range 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 passed. +**/ +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)) != 0) || (SlaveId >= SlaveId_Max)) { + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeSet Error. Invalid Address: %x or invalid SlaveId\n", Address)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + LpcBase = LpcPciBase (); + + MemRangeAddr = ~Address; + if (SlaveId == SlaveEspiCS1) { + GenMemReg = R_ESPI_CFG_CS1GMR1; + // Memory Range already decoded for LPC/eSPI? + Status = PchLpcMemRangeGet (&MemRangeAddr); + if (MemRangeAddr != Address) { + Status = PchDmiSetEspiCs1MemRange (Address); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } else { + GenMemReg = R_LPC_CFG_LGMR; + // Memory Range already decoded for eSPI CS1? + Status = PchEspiCs1MemRangeGet (&MemRangeAddr); + if (MemRangeAddr != Address) { + Status = 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 first 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 passed. + @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 passed. + @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# memory 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 == NULL) || (SlaveId >= SlaveId_Max)) { + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeGet Error. Invalid pointer or SlaveId.\n")); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + if (SlaveId == SlaveEspiCS1) { + GenMemReg = R_ESPI_CFG_CS1GMR1; + } else { + GenMemReg = R_LPC_CFG_LGMR; + } + *Address = PciSegmentRead32 (LpcPciBase () + GenMemReg) & B_LPC_CFG_LGMR_MA; + return EFI_SUCCESS; +} + +/** + Get PCH LPC/eSPI memory range decoding address. + + @param[out] Address Address of LPC/eSPI memory decoding 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 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 +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 BiosDecodeEnable. + 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 = PchDmiSetBiosDecodeEnable (BiosDecodeEnable); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Check Boot BIOS Strap in DMI + // + if (PchDmiIsBootBiosStrapSetForSpi ()) { + BaseAddr = 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 = 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 in 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 settings. + + @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 used before debug print ready. + // + + LpcBaseAddr = LpcPciBase (); + + // + // check if setting is identical + // + if (LpcIoDecodeRanges == PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOD)) { + return EFI_SUCCESS; + } + + Status = 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 offset 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#). + Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field + in LPC/eSPI PCI offset 82h[13:10] or A0h[13:10] is always forwarded by DMI 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 settings. + @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 = LpcPciBase (); + + Cs0IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOE); + + if (IsEspiSecondSlaveSupported ()) { + Cs1IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE); + } else { + Cs1IoEnableDecodingOrg = 0; + } + + if (SlaveId == SlaveEspiCS1) { + if (IoEnableDecoding == Cs1IoEnableDecodingOrg) { + return EFI_SUCCESS; + } else { + IoEnableDecodingMerged = (Cs0IoEnableDecodingOrg | IoEnableDecoding); + } + } else { + if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) == Cs0IoEnableDecodingOrg) { + return EFI_SUCCESS; + } else { + IoEnableDecodingMerged = (Cs1IoEnableDecodingOrg | IoEnableDecoding); + } + } + + Status = 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 == 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 offset 82h. + Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field + in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling. + Please check EDS for detail of LPC/eSPI IO decode ranges bit definition. + + @param[in] LpcIoEnableDecoding LPC IO enable decoding bit settings. + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_UNSUPPORTED DMIC.SRL is set. +**/ +EFI_STATUS +PchLpcIoEnableDecodingSet ( + IN UINT16 LpcIoEnableDecoding + ) +{ + return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding, SlaveLpcEspiCS0); +} + +/** + Set PCH eSPI CS1# IO enable decoding. + Setup I/O Enables in DMI to the same value program in eSPI PCI offset A0h (eSPI CS1#). + Note: Bit[15:10] of the source decode register is Read-Only. The IO range 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 settings. + + @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 enumeration. + 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 = 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 = 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 == NULL) { + DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n")); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + *HpetBase = PcdGet32 (PcdSiHpetBaseAddress); + return EFI_SUCCESS; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEspiLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEspiLib.c new file mode 100644 index 0000000000..1bbecc71ed --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEspiLib.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 after which to report error +#define SLAVE_CHANNELS_MAX 7 ///< Max number of channels + +// +// eSPI Slave registers +// +#define R_ESPI_SLAVE_GENCAP 0x08 ///< General Capabilities and Configurations +#define B_ESPI_SLAVE_GENCAP_SUPPCHAN 0xFF ///< Channels supported 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 channel from base +#define B_ESPI_SLAVE_CHACAP_CHEN BIT0 ///< Slave Channel enable bit +#define B_ESPI_SLAVE_CHACAP_CHRDY BIT1 ///< Slave Channel ready 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) != 0)); +} + +/** + Checks in slave General Capabilities register if it supports channel with 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 device + @retval FALSE Channel with requested number is not supported by slave device +**/ +BOOLEAN +IsEspiSlaveChannelSupported ( + UINT8 SlaveId, + UINT8 ChannelNumber + ) +{ + EFI_STATUS Status; + UINT32 Data32; + UINT8 SupportedChannels; + + Status = PchEspiSlaveGetConfig (SlaveId, R_ESPI_SLAVE_GENCAP, &Data32); + if (EFI_ERROR (Status)) { + return FALSE; + } + SupportedChannels = (UINT8) (Data32 & B_ESPI_SLAVE_GENCAP_SUPPCHAN); + + DEBUG ((DEBUG_INFO, "Slave %d supported channels 0x%4X\n", SlaveId, SupportedChannels)); + + if (ChannelNumber > SLAVE_CHANNELS_MAX || !(SupportedChannels & (BIT0 << ChannelNumber))) { + // Incorrect channel number was specified. Either exceeded max or Slave 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) != 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 = PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SLV_CFG_REG_CTL); + } while ((ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE) != 0); + + ScrStat = (ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS) >> N_ESPI_PCR_SLV_CFG_REG_CTL_SCRS; + if (ScrStat != 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_SLV_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 exceed maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation +**/ +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 >= 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 == 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) != 0) { + DEBUG ((DEBUG_ERROR, "eSPI Slave address must be DWord aligned \n")); + return EFI_INVALID_PARAMETER; + } + + // + // Check if write is allowed + // + if ((SlaveOperation == EspiSlaveOperationConfigWrite) && + (SlaveAddress <= 0x7FF)) { + + // + // If the SLCRR is not set in corresponding slave, we will check the lock bit + // + Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) (R_ESPI_PCR_LNKERR_SLV0 + (SlaveId * S_ESPI_PCR_LNKERR_SLV0))); + if ((Data32 & B_ESPI_PCR_LNKERR_SLV0_SLCRR) == 0) { + + Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) R_ESPI_PCR_SLV_CFG_REG_CTL); + if ((Data32 & B_ESPI_PCR_SLV_CFG_REG_CTL_SBLCL) != 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 == 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 = EspiPollScreAndCheckScrs (); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((SlaveOperation == EspiSlaveOperationConfigRead) || (SlaveOperation == EspiSlaveOperationStatusRead)) { + Data32 = PchPcrRead32 ( + PID_ESPISPI, + (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA + ); + if (SlaveOperation == EspiSlaveOperationStatusRead) { + *Data = Data32 & 0xFFFF; + } else { + *Data = 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 exceed maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation +**/ +EFI_STATUS +PchEspiSlaveGetConfig ( + IN UINT32 SlaveId, + IN UINT32 SlaveAddress, + OUT UINT32 *OutData + ) +{ + // + // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=, Bit [17:16] = 00b, Bit[11:0] = . + // 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, EspiSlaveOperationConfigRead, 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 register 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 exceed maximum allowed + @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation +**/ +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 in 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]=01, Bit [20:19]=, Bit [17:16] = 01b, Bit[11:0] = . + // 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 = EspiSlaveOperationHelper (SlaveId, SlaveAddress, EspiSlaveOperationConfigWrite, &InData); + if (EFI_ERROR (Status)) { + return Status; + } + Status = 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 operation +**/ +EFI_STATUS +PchEspiSlaveGetStatus ( + IN UINT32 SlaveId, + OUT UINT16 *OutData + ) +{ + EFI_STATUS Status; + UINT32 TempOutData; + + TempOutData = 0; + + // + // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=, Bit [17:16] = 10b, Bit[11:0] = . + // 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 = EspiSlaveOperationHelper (SlaveId, 0, EspiSlaveOperationStatusRead, &TempOutData); + *OutData = (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 operation +**/ +EFI_STATUS +PchEspiSlaveInBandReset ( + IN UINT32 SlaveId + ) +{ + // + // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28] + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=, Bit [17:16] = 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, EspiSlaveOperationInBandReset, 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 invalid 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, ChannelNumber)); + + Timeout = CHANNEL_RESET_TIMEOUT; + SlaveBmeSet = FALSE; + + if (!IsEspiSlaveChannelSupported (SlaveId, ChannelNumber)) { + // Incorrect channel number was specified. Either exceeded max or Slave 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 = R_ESPI_SLAVE_CHACAP_BASE + (S_ESPI_SLAVE_CHACAP_OFFSET * ChannelNumber); + + // If we're resetting Peripheral Channel then we need to disable Bus Mastering first and reenable after reset + if (ChannelNumber == 0) { + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Data32 & B_ESPI_SLAVE_BME) != 0) { + Data32 &= ~(B_ESPI_SLAVE_BME); + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32); + if (EFI_ERROR (Status)) { + return Status; + } + SlaveBmeSet = TRUE; + } + } + + // Disable channel + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + Data32 &= ~(B_ESPI_SLAVE_CHACAP_CHEN); + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32); + if (EFI_ERROR (Status)) { + return Status; + } + // Enable channel + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + Data32 |= B_ESPI_SLAVE_CHACAP_CHEN; + Status = 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) == 0) && (Timeout > 0)) { + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + MicroSecondDelay (1); + --Timeout; + } + + if (Timeout == 0) { + // The waiting for channel to be ready has timed out + DEBUG ((DEBUG_ERROR, "The operation of channel %d reset for slave %d has timed out!\n", ChannelNumber, SlaveId)); + return EFI_TIMEOUT; + } + + if (ChannelNumber == 0 && SlaveBmeSet) { + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + Data32 |= B_ESPI_SLAVE_BME; + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c new file mode 100644 index 0000000000..652a47ebaf --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.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 = 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 != 0); + if (MmioRead32 (SpiBar + R_SPI_MEM_FREG3_GBE) != 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 () == FALSE) { + return FALSE; + } + return TRUE; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c new file mode 100644 index 0000000000..2be8e8ed49 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.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/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c new file mode 100644 index 0000000000..7c3ade49b6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.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 = 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 = PCH_UNKNOWN_SERIES; + + if (PchSeries != PCH_UNKNOWN_SERIES) { + return PchSeries; + } + + PchSer = PchSeriesFromLpcDid (PchGetLpcDid ()); + + PchSeries = 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 = PCH_STEPPING_MAX; + + if (PchStepping != PCH_STEPPING_MAX) { + return PchStepping; + } + + LpcBaseAddress = 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 = PciSegmentRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET); + + PchStepping = 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 = 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 = PciSegmentRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET); + LpcVendorId = PciSegmentRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET); + + /// + /// Verify that this is a supported chipset + /// + if ((LpcVendorId == V_LPC_CFG_VENDOR_ID) && (PchSeries () != PCH_UNKNOWN_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 () == 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 () == 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 () == 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 () == CNL_PCH); +} + +/** + Get PCH stepping ASCII string. + Function determines major and minor stepping versions and writes them into 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 = PchStepping (); + + if ((Buffer == NULL) || (BufferSize == 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' + (PchStep & 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 = PchGetLpcDid (); + + for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) { + if (LpcDid == 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/PeiDxeSmmPchInfoLib/PchInfoLibClient.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibClient.c new file mode 100644 index 0000000000..7b09a2dbb9 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibClient.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/PeiDxeSmmPchInfoLib/PchInfoLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibCnl.c new file mode 100644 index 0000000000..431b1470c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibCnl.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 = PchGetLpcDid (); + + if (LpcDid == 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[] = { + // + // 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/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/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 mPchPcieControllerInfo[] = { + { 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 = sizeof (mPchPcieControllerInfo) / sizeof (mPchPcieControllerInfo[0]); + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchLpRstPcieStorageSupportedPort[] = { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP5..RP8 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP9..RP12 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP13..RP16 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchHRstPcieStorageSupportedPort[] = { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP13..RP16 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, // RP17..RP20 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_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 function number. + + @retval EFI_SUCCESS Root port device and function is retrieved + @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 >= GetPchMaxPciePortNum ()) { + DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumber)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS; + FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase; + *RpDev = mPchPcieControllerInfo[Index].DevNum; + PciePcd = PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_SPX_PCR_PCD); + *RpFun = (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 Port 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 = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, RpDev, RpFun, 0); + *RpNumber = (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 hardware 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 port 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/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c new file mode 100644 index 0000000000..6f70733fe7 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.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)) != 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) | OrData); + 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/PeiDxeSmmPchPmcLib/PchPmcLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c new file mode 100644 index 0000000000..2654a76983 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.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 could 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 post. + For the ColdBoot case, this function only returns one case of the cold boot. Some cold boot case might + depends on the power cycle scenario and should check with different condtion. + + @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 = 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 = 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/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c new file mode 100644 index 0000000000..43690e2409 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/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 PchSbiExecution 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 after 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) != 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 PchSbiExecution 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 after 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 = 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) == 0xFFFF) { + ASSERT (FALSE); + return EFI_DEVICE_ERROR; + } + /// + /// BWG Section 2.2.1 + /// 1. Poll P2SB PCI offset D8h[0] = 0b + /// Make sure the previous opeartion is completed. + /// + Timeout = 0xFFFFFFF; + while (Timeout > 0) { + SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT); + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) { + break; + } + Timeout--; + } + if (Timeout == 0) { + return EFI_TIMEOUT; + } + // + // Initial Response status + // + *Response = SBI_INVALID_RESPONSE; + SbiStat = 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 expected to be 0 in PCH. + /// + PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16)); + /// + /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read + /// Set P2SB PCI offset D8h[15:8] = 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] = F000h + /// + // + // Set RID[15:0] = 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 accordingly + /// + 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] = 1b, Poll P2SB PCI offset D8h[0] = 0b + /// + // + // Set SBISTAT[0] = 1b, trigger the SBI operation + // + PciSegmentOr16 (P2sbBase + R_P2SB_CFG_SBISTAT, (UINT16) B_P2SB_CFG_SBISTAT_INITRDY); + // + // Poll SBISTAT[0] = 0b, Polling for Busy bit + // + Timeout = 0xFFFFFFF; + while (Timeout > 0) { + SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT); + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) { + break; + } + Timeout--; + } + if (Timeout == 0) { + // + // If timeout, it's fatal error. + // + return EFI_TIMEOUT; + } else { + /// + /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction + /// + *Response = (UINT8) ((SbiStat & B_P2SB_CFG_SBISTAT_RESPONSE) >> N_P2SB_CFG_SBISTAT_RESPONSE); + if (*Response == SBI_SUCCESSFUL) { + switch (Opcode) { + case MemoryRead: + case PciConfigRead: + case PrivateControlRead: + /// + /// 9. Read P2SB PCI offset D4h[31:0] for SBI data + /// + *Data32 = 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/PeiDxeSmmPchSerialIoLib/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/PeiDxeSmmPchSerialIoLib/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 mSerialIoAcpiAddress [PCH_MAX_SERIALIO_CONTROLLERS] = +{ + {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x3000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x5000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x7000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x9000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15000}, + {PCH_SERIAL_IO_BASE_ADDRESS + 0x16000, PCH_SERIAL_IO_BASE_ADDRESS + 0x17000} +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchSerialIoPciCfgCtrAddr [PCH_MAX_SERIALIO_CONTROLLERS] = +{ + 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 >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber ()) { + return SERIAL_IO_I2C; + } else if (Controller >= PchSerialIoIndexSpi0 && Controller < (PchSerialIoIndexSpi0 + GetPchMaxSerialIoSpiControllersNum ())) { + return SERIAL_IO_SPI; + } else if (Controller >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart2) { + 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_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, DeviceNumber, FunctionNumber, PCI_DEVICE_ID_OFFSET)) != 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 Number is equal to any of LPSS devices + FALSE Device/Function is not in Serial IO scope +**/ +BOOLEAN +IsSerialIoDevice ( + IN UINT8 DeviceNumber, + IN UINT8 FunctionNumber + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + PCH_SERIAL_IO_CONTROLLER ControllerMax; + + ControllerMax = GetPchMaxSerialIoControllersNum (); + + for (Controller = 0; Controller < ControllerMax; Controller++) { + if ((DeviceNumber == GetSerialIoDeviceNumber (Controller)) && + (FunctionNumber == 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 correspond to Serial IO +**/ +UINT16 +GetSerialIoConfigControlOffset ( + IN UINT8 DeviceNumber, + IN UINT8 FunctionNumber + ) +{ + PCH_SERIAL_IO_CONTROLLER Controller; + PCH_SERIAL_IO_CONTROLLER ControllerMax; + + ControllerMax = GetPchMaxSerialIoControllersNum (); + + for (Controller = 0; Controller < ControllerMax; Controller++) { + if ((DeviceNumber == GetSerialIoDeviceNumber (Controller)) && + (FunctionNumber == GetSerialIoFunctionNumber (Controller))) { + return mPchSerialIoPciCfgCtrAddr[Controller]; + } + } + + return 0; +} + +/** + Checks if Device with given AcpiHid string is one of SerialIo controllers + If yes, its number is returned through Number parameter, otherwise Number 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 = GetPchMaxSerialIoControllersNum (); + + for (Controller = 0; Controller < ControllerMax; Controller++) { + if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, GetSerialIoAcpiHid(Controller))) { + *Number = Controller; + return TRUE; + } + } + return FALSE; +} + +/** + Finds BAR values of SerialIo devices. + SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work. + If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG space instead + + @param[in] SerialIoDevice Serial IO device + @param[in] BarNumber 0=BAR0, 1=BAR1 + + @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 = GetSerialIoDeviceNumber (SerialIoDevice); + Function = GetSerialIoFunctionNumber (SerialIoDevice); + + PcieBase = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_PCIEXBAR)); // S0:B0:D0:F0:R60 + PcieBase = (PcieBase & PCIEX_BAR_ADDR_MASK) + LShiftU64 (DEFAULT_PCI_BUS_NUMBER_PCH, 20) + LShiftU64 (Device, 15) + LShiftU64 (Function, 12); + + PciSegBase = PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + Device, + Function, + 0 + ); + + VenId = PciSegmentRead16 (PciSegBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF; + if (VenId == V_PCH_INTEL_VENDOR_ID) { + if (BarNumber == 1) { + return ((UINTN) PcieBase); + } + Bar = 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) == B_PCI_BAR_MEMORY_TYPE_64) { + Bar = (Bar & 0xFFFFF000) + (UINTN) ((UINT64) LShiftU64 ((PciSegmentRead32 (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 == 0) { + Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar0; + } else { + Bar = 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 system hang (in Debug build). +*/ + + // + // This is to prevent from overflow of array access. + // + if (Controller >= PCH_MAX_SERIALIO_CONTROLLERS) { + return; + } + + if (GetSerialIoControllerType (Controller) == SERIAL_IO_UNKNOWN) { + return; + } + + PciCfgBase = 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) != V_PCH_INTEL_VENDOR_ID) { + return; + } + + /// + /// Step 0. set Bit 16,17,18. + /// + PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_D0I3MAXDEVPG, BIT18 | BIT17 | BIT16); + + SerialIoPciCfgCtrAddr = 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 | BIT0); + + 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, mSerialIoAcpiAddress[Controller].Bar0); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0); + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR1_LOW, mSerialIoAcpiAddress[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_MEMORY_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_PCICFGCTRL_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) & 0xFFFFF000) { + 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_PCR_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, mSerialIoAcpiAddress[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 >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart2) && (DeviceMode != PchSerialIoDisabled)) { + MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_PPR_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 = (UINT32) (~(B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0))); + Data32Or = 0x0; + if (DeviceMode == PchSerialIoHidden) { + Data32Or = (B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0)); + } + PchPcrAndThenOr32 (PID_SERIALIO, R_SERIAL_IO_PCR_GPPRVRW7,Data32And,Data32Or); + // + // 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_PPR_CLK); + // + // Loop until Uart has successfuly moved to 8 bit mode + // + if (DeviceMode == PchSerialIoHidden) { + Uart8BitLoop = 10; + while (Uart8BitLoop > 0) { + if (DetectAccessMode (mSerialIoAcpiAddress[Controller].Bar0) == AccessMode8bit) { + return; + } + Uart8BitLoop--; + } + } + } + + /// + /// Step Z. Program I2C SDA hold registers + /// + if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber ()) { + if (DeviceMode != PchSerialIoDisabled) { + MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_SERIAL_IO_MEM_I2C_SDA_HOLD, V_SERIAL_IO_MEM_I2C_SDA_HOLD_VALUE); + } + } + +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PchSerialIoLibCnl.c new file mode 100644 index 0000000000..28ccd626af --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/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_CONTROLLERS][SERIALIO_HID_LENGTH] = +{ + "INT34B2", + "INT34B3", + "INT34B4", + "INT34B5", + "INT34B6", + "INT34B7", + "INT34B0", + "INT34B1", + "INT34BC", + "INT34B8", + "INT34B9", + "INT34BA" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mCnlPchLpSerialIoId [PCH_MAX_SERIALIO_CONTROLLERS] = +{ + 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] = +{ + 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] = +{ + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1}, + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_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 Number 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 = 0; Controller < GetPchMaxSerialIoControllersNum (); Controller++) { + if ((IsPchLp () && (PciDevId == mCnlPchLpSerialIoId[Controller])) || + (IsPchH () && (PciDevId == mCnlPchHSerialIoId[Controller]))) + { + *Number = 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/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c new file mode 100644 index 0000000000..621a473cfa --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib/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 Register 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) == UART_COMPONENT_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 == 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 regardless of access mode +**/ +STATIC +UINT8 +ReadRegister ( + IN UART_ACCESS_MODE AccessMode, + IN UINTN BaseAddress, + IN UINTN Offset + ) +{ + if (AccessMode == 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 = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 1); + if (MmioRead16 (CfgSpace + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + return; + } + if ((MmioRead16 (CfgSpace + PCI_COMMAND_OFFSET) & EFI_PCI_COMMAND_MEMORY_SPACE) != EFI_PCI_COMMAND_MEMORY_SPACE) { + if ((MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000) != 0x0 && + (MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000) != 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 init serial io controller if platform is going use serialio UART as debug output. + + @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, hardware automatically checks CTS when sending data, and sets RTS when receiving data. +**/ +VOID +EFIAPI +PchSerialIoUartInit ( + UINT8 UartNumber, + BOOLEAN FifoEnable, + UINT32 BaudRate, + UINT8 LineControl, + BOOLEAN HardwareFlowControl + ) +{ + UINTN Base; + UINTN Divisor; + UART_ACCESS_MODE AccessMode; + + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) { + // + // Base is not programmed, skip it. + // + return; + } + EnablePciMse (UartNumber); + AccessMode = DetectAccessMode (Base); + + Divisor = MAX_BAUD_RATE / BaudRate; + + // + // Configure baud rate + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR, B_PCH_SERIAL_IO_UART_LCR_DLAB); + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH, (UINT8) (Divisor >> 8)); + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW, (UINT8) (Divisor & 0xff)); + // + // Configure Line control and switch back to bank 0 + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR, LineControl & 0x1F); + // + // Enable and reset FIFOs + // + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_FCR, FifoEnable?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_SERIAL_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 Buffer. + + @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 == Buffer) { + return 0; + } + + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uninitialized UART + // + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode = DetectAccessMode (Base); + + if (ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_USR) == 0xFF) { + return 0; + } + + BytesLeft = NumberOfBytes; + + while (BytesLeft != 0) { + // + // Write data while there's room in TXFIFO. If HW Flow Control was enabled, 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, *Buffer); + 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 writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + @param WaitUntilBufferFull When TRUE, function waits until whole buffer is filled. When FALSE, function returns as soon as no new characters are available. + + @retval Actual number of bytes raed to serial device. + +**/ +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 == Buffer) { + return 0; + } + + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uninitialized UART + // + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode = DetectAccessMode (Base); + + BytesReceived = 0; + + while (BytesReceived != NumberOfBytes) { + // + // Read the line status register + // + Lsr = 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) != 0) { + Byte = ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_RXBUF); + // + // Check if the break interrupt bit is set. If set, the byte read from 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) == 0) { + *Buffer = 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 FALSE is returned. + + @param UartNumber Selects Serial IO UART device (0-2) + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +PchSerialIoUartPoll ( + IN UINT8 UartNumber + ) +{ + UINTN Base; + UART_ACCESS_MODE AccessMode; + + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0); + // + // Sanity checks to avoid infinite loop when trying to print through uninitialized UART + // + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) { + return 0; + } + EnablePciMse (UartNumber); + AccessMode = 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) != 0) { + return TRUE; + } + return FALSE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c new file mode 100644 index 0000000000..679dcae0ab --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c @@ -0,0 +1,242 @@ +/** @file + Library that contains common parts of WdtPei and WdtDxe. Not a standalone 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 = 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 Reset bit, which + causes the next reset to be treated as watchdog expiration - unless AllowKnownReset() + function was called too. + + @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 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 == 0)) { + return EFI_INVALID_PARAMETER; + } + + Readback = IoRead32 (WdtGetAddress ()); + Readback |= (B_ACPI_IO_OC_WDT_CTL_EN | B_ACPI_IO_OC_WDT_CTL_FORCE_ALL | B_ACPI_IO_OC_WDT_CTL_ICCSURV); + if (mAllowExpectedReset == 0) { + Readback |= B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS; + } + + if (PcdGetBool (PcdOcEnableWdtforDebug) == FALSE) { + /// + /// WDT will not be turned on. This is to prevent platform reboots triggered + /// by WDT expiration, which can be expected when processor is halted for debugging + /// + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_EN | B_ACPI_IO_OC_WDT_CTL_FORCE_ALL | B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS); + DEBUG ((DEBUG_INFO, "(Wdt) Wdt disabled in Debug BIOS\n")); + } + + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_TOV_MASK); + Readback |= ((TimeoutValue - 1) & B_ACPI_IO_OC_WDT_CTL_TOV_MASK); + IoWrite32 (WdtGetAddress (), Readback); + Readback |= 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 = IoRead32 (WdtGetAddress ()); + Readback &= ~(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 expiration 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 = IoRead32 (WdtGetAddress ()); + + DEBUG ((DEBUG_INFO, "(Wdt) Readback = (%x)\n", Readback)); + + if (Readback & B_ACPI_IO_OC_WDT_CTL_FAILURE_STS) { + DEBUG ((DEBUG_INFO, "(Wdt) Status = 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 failure. + This function allows platform to perform expected reboots with WDT running, + 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, ReloadAndStart() + must not be called. + + +**/ +VOID +EFIAPI +WdtAllowKnownReset ( + VOID + ) +{ + UINT32 Readback; + + DEBUG ((DEBUG_INFO, "(Wdt) AllowKnownReset\n")); + + mAllowExpectedReset = 1; + + Readback = IoRead32 (WdtGetAddress ()); + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS | B_ACPI_IO_OC_WDT_CTL_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 = IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_AFTER_POST) != 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 = IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_EN) != 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 = IoRead32 (WdtGetAddress ()); + + + if ((Readback & B_ACPI_IO_OC_WDT_CTL_LCK) != 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 = PmcGetAcpiBase (); + PmconA = MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A); + + DEBUG ((DEBUG_INFO, "PWRM_PMCON_A = 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)) != 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_SLP_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 event + + @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_PM1_STS_PRBTNOR) != 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) == 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) != 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) != 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 reapplied + + @param[in] PowerStateAfterG3 0: S0 state (boot) + 1: S5/S4 State +**/ +VOID +PmcSetPlatformStateAfterPowerFailure ( + IN UINT8 PowerStateAfterG3 + ) +{ + UINT32 PchPwrmBase; + + PchPwrmBase = 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) != 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_SMI_EN_GBL_SMI); +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.c new file mode 100644 index 0000000000..05557931c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.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 Library 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/PeiDxeSmmSataLib/SataLibCdf.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCdf.c new file mode 100644 index 0000000000..5cec818dd6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCdf.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 == SATA_1_CONTROLLER_INDEX) { + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_1; + } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) { + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_2; + } else if (SataCtrlIndex == 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 == SATA_1_CONTROLLER_INDEX) { + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_1; + } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) { + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_2; + } else if (SataCtrlIndex == 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/PeiDxeSmmSataLib/SataLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCnl.c new file mode 100644 index 0000000000..0eca692a74 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCnl.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/PeiOcWdtLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c new file mode 100644 index 0000000000..22f6fb215f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.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 = { + WdtReloadAndStart, + WdtCheckStatus, + WdtDisable, + WdtAllowKnownReset, + IsWdtRequired, + IsWdtEnabled +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallWdtPpi = { + (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 = PmcGetSleepTypeAfterWake (); + if ((SleepType == PmcS3SleepState) || (SleepType == PmcS4SleepState)) { + return TRUE; + } + + return FALSE; + +} + +/** + Check for unexpected reset. + If there was an unexpected reset, enforces WDT expiration. +**/ +VOID +OcWdtResetCheck ( + VOID + ) +{ + UINT32 Readback; + + Readback = 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 |= B_ACPI_IO_OC_WDT_CTL_FAILURE_STS; + Readback |= (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT_CTL_NO_ICCSURV_STS); + Readback &= ~(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 inform 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) && !IsWakeFromS3S4()) { + if (PcdGetBool (PcdOcEnableWdtforDebug)) { + DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected and ignored.\n")); + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS | B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS); + Readback |= (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 Wdt 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 &= ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS); + Readback |= (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS | B_ACPI_IO_OC_WDT_CTL_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 = 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/PeiOcWdtLibNull/PeiOcWdtLibNull.c new file mode 100644 index 0000000000..182218ffcf --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.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/PeiPchPolicyLib/PchPreMemPrintPolicy.c new file mode 100644 index 0000000000..bd1e2711da --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.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_CONFIG 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= %x\n", PchGeneralPreMemConfig->Port80Route)); +} + +/** + 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 = %x\n", DciPreMemConfig->PlatformDebugConsent)); + DEBUG ((DEBUG_INFO, "DciUsb3TypecUfpDbg = %x\n", DciPreMemConfig->DciUsb3TypecUfpDbg)); +} + +/** + 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= %x\n", WdtPreMemConfig->DisableAndLock)); +} + +/** + 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= %x\n", PchTraceHubPreMemConfig->EnableMode)); + DEBUG ((DEBUG_INFO, "MemReg0Size= %x\n", PchTraceHubPreMemConfig->MemReg0Size)); + DEBUG ((DEBUG_INFO, "MemReg1Size= %x\n", PchTraceHubPreMemConfig->MemReg1Size)); +} + +/** + Print PCH_SMBUS_CONFIG and serial out. + + @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that provides 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= %x\n", SmbusPreMemConfig->Enable)); + DEBUG ((DEBUG_INFO, " ArpEnable= %x\n", SmbusPreMemConfig->ArpEnable)); + DEBUG ((DEBUG_INFO, " DynamicPowerGating= %x\n", SmbusPreMemConfig->DynamicPowerGating)); + DEBUG ((DEBUG_INFO, " SpdWriteDisable= %x\n", SmbusPreMemConfig->SpdWriteDisable)); + DEBUG ((DEBUG_INFO, " SmbAlertEnable= %x\n", SmbusPreMemConfig->SmbAlertEnable)); + DEBUG ((DEBUG_INFO, " SmbusIoBase= %x\n", SmbusPreMemConfig->SmbusIoBase)); + DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses= %x\n", SmbusPreMemConfig->NumRsvdSmbusAddresses)); + DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable= {")); + for (Index = 0; Index < SmbusPreMemConfig->NumRsvdSmbusAddresses; ++Index) { + 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= %x\n", LpcPreMemConfig->EnhancePort8xhDecoding)); +} + +/** + Print PCH_HSIO_PCIE_PREMEM_CONFIG and serial out. + + @param[in] HsioPciePreMemConfig Pointer to a PCH_HSIO_PCIE_PREMEM_CONFIG 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 = 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtleEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtle= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtle)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmph= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0= %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_CONFIG 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 controller %d ----------------\n", SataCtrlIndex)); + for (Index = 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++) { + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph)); + } +} + +/** + Print PCH_PCIE_RP_PREMEM_CONFIG and serial out. + + @param[in] PcieRpPreMemConfig Pointer to a PCH_PCIE_RP_PREMEM_CONFIG 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 = 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " Port[%d] RpEnabled= %x\n", Index, (PcieRpPreMemConfig->RpEnabledMask & (UINT32) (1 << Index)) != 0 )); + } + DEBUG ((DEBUG_INFO, " PcieImrEnabled= %x\n", PcieRpPreMemConfig->PcieImrEnabled)); + DEBUG ((DEBUG_INFO, " PcieImrSize= %d MB\n", PcieRpPreMemConfig->PcieImrSize)); + DEBUG ((DEBUG_INFO, " ImrRpSelection= %d\n", PcieRpPreMemConfig->ImrRpSelection)); +} + +/** + Print PCH_HDAUDIO_PREMEM_CONFIG and serial out. + + @param[in] LpcPreMemConfig Pointer to a PCH_HDAUDIO_PREMEM_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= %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= %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 = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gDciPreMemConfigGuid, (VOID *) &DciPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gWatchDogPreMemConfigGuid, (VOID *) &WdtPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchTraceHubPreMemConfigGuid, (VOID *) &PchTraceHubPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSmbusPreMemConfigGuid, (VOID *) &SmbusPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPcieRpPreMemConfigGuid, (VOID *) &PcieRpPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHdAudioPreMemConfigGuid, (VOID *) &HdaPreMemConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gIshPreMemConfigGuid, (VOID *) &IshPreMemConfig); + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy Start ------------------------\n")); + DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPreMemPolicyPpi->TableHeader.Header.Revision)); + + PchPrintGeneralPreMemConfig (PchGeneralPreMemConfig); + PchPrintDciPreMemConfig (DciPreMemConfig); + PchPrintWdtPreMemConfig (WdtPreMemConfig); + PchPrintTraceHubPreMemConfig (PchTraceHubPreMemConfig); + PchPrintSmbusPreMemConfig (SmbusPreMemConfig); + PchPrintLpcPreMemConfig (LpcPreMemConfig); + PchPrintHsioPciePreMemConfig (HsioPciePreMemConfig); + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum (); SataCtrlIndex++) { + HsioSataPreMemConfig = 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/PeiPchPolicyLib/PchPrintPolicy.c new file mode 100644 index 0000000000..d9005b50ef --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.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 platform setting + +**/ +VOID +PchPrintUsbConfig ( + IN CONST USB_CONFIG *UsbConfig + ) +{ + UINT32 Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH USB Config ------------------\n")); + DEBUG ((DEBUG_INFO, " EnableComplianceMode = %x\n", UsbConfig->EnableComplianceMode)); + DEBUG ((DEBUG_INFO, " PdoProgramming = %x\n", UsbConfig->PdoProgramming)); + DEBUG ((DEBUG_INFO, " OverCurrentEnable = %x\n", UsbConfig->OverCurrentEnable)); + DEBUG ((DEBUG_INFO, " XhciOcLock = %x\n", UsbConfig->XhciOcLock)); + DEBUG ((DEBUG_INFO, " Usb2PhySusPgEnable = %x\n", UsbConfig->Usb2PhySusPgEnable)); + + for (Index = 0; Index < GetPchUsb2MaxPhysicalPortNum (); Index++) { + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled = %x\n", Index, UsbConfig->PortUsb20[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb20[Index].OverCurrentPin)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Petxiset)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Txiset)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Predeemp)); + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Pehalfbit)); + } + + for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) { + DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled = %x\n", Index, UsbConfig->PortUsb30[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmph)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp)); + + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfgEnable = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffsetCfgEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfg = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffsetCfg)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelNEnable = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelNEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelN = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelN)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelPEnable = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelPEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelP = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelP)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnResEnable = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpDwnResEnable)); + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnRes = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpDwnRes)); + } + + DEBUG ((DEBUG_INFO, " XdciConfig.Enable= %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 = 0; Index < GetPchMaxPciePortNum (); Index++) { + DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug= %x\n", Index, PcieConfig->RootPort[Index].HotPlug)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci= %x\n", Index, PcieConfig->RootPort[Index].PmSci)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync= %x\n", Index, PcieConfig->RootPort[Index].ExtSync)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect= %x\n", Index, PcieConfig->RootPort[Index].ClkReqDetect)); + DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport= %x\n", Index, PcieConfig->RootPort[Index].UnsupportedRequestReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].FatalErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].NoFatalErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport= %x\n", Index, PcieConfig->RootPort[Index].CorrectableErrorReport)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnFatalError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnNonFatalError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnCorrectableError)); + DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload= %x\n", Index, PcieConfig->RootPort[Index].MaxPayload)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotImplemented= %x\n", Index, PcieConfig->RootPort[Index].SlotImplemented)); + DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled= %x\n", Index, PcieConfig->RootPort[Index].AcsEnabled)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PtmEnabled= %x\n", Index, PcieConfig->RootPort[Index].PtmEnabled)); + DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting= %x\n", Index, PcieConfig->RootPort[Index].AdvancedErrorReporting)); + DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing= %x\n", Index, PcieConfig->RootPort[Index].TransmitterHalfSwing)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed= %x\n", Index, PcieConfig->RootPort[Index].PcieSpeed)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method= %x\n", Index, PcieConfig->RootPort[Index].Gen3EqPh3Method)); + DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber= %x\n", Index, PcieConfig->RootPort[Index].PhysicalSlotNumber)); + DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout= %x\n", Index, PcieConfig->RootPort[Index].CompletionTimeout)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm= %x\n", Index, PcieConfig->RootPort[Index].Aspm)); + DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates= %x\n", Index, PcieConfig->RootPort[Index].L1Substates)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable= %x\n", Index, PcieConfig->RootPort[Index].LtrEnable)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock= %x\n", Index, PcieConfig->RootPort[Index].LtrConfigLock)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxSnoopLatency)); + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxNoSnoopLatency)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMode)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMultiplier)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMode)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier)); + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] ForceLtrOverride= %x\n", Index, PcieConfig->RootPort[Index].ForceLtrOverride)); + DEBUG ((DEBUG_INFO, " RootPort[%d] DetectTimeoutMs= %x\n", Index, PcieConfig->RootPort[Index].DetectTimeoutMs)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitScale)); + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitValue)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp= %x\n", Index, PcieConfig->RootPort[Index].Uptp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp= %x\n", Index, PcieConfig->RootPort[Index].Dptp)); + DEBUG ((DEBUG_INFO, " RootPort[%d] EnableCpm= %x\n", Index, PcieConfig->RootPort[Index].EnableCpm)); + + } + for (Index = 0; Index < GetPchMaxPcieClockNum (); Index++) { + DEBUG ((DEBUG_INFO, " Clock[%d] Usage= %x\n", Index, PcieConfig->PcieClock[Index].Usage)); + DEBUG ((DEBUG_INFO, " Clock[%d] ClkReq= %x\n", Index, PcieConfig->PcieClock[Index].ClkReq)); + } + for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) { + DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cm)); + DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cp)); + } + DEBUG ((DEBUG_INFO, " EnablePort8xhDecode= %x\n", PcieConfig->EnablePort8xhDecode)); + DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex= %x\n", PcieConfig->PchPciePort8xhDecodePortIndex)); + DEBUG ((DEBUG_INFO, " DisableRootPortClockGating= %x\n", PcieConfig->DisableRootPortClockGating)); + DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite= %x\n", PcieConfig->EnablePeerMemoryWrite)); + DEBUG ((DEBUG_INFO, " ComplianceTestMode= %x\n", PcieConfig->ComplianceTestMode)); + DEBUG ((DEBUG_INFO, " RpFunctionSwap= %x\n", PcieConfig->RpFunctionSwap)); + DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr= %x\n", PcieConfig->PcieDeviceOverrideTablePtr)); +} + +/** + 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= %x\n", SataConfig->Enable)); + DEBUG ((DEBUG_INFO, " SataMode= %x\n", SataConfig->SataMode)); + + for (Index = 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++) { + DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled= %x\n", Index, SataConfig->PortSettings[Index].Enable)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug= %x\n", Index, SataConfig->PortSettings[Index].HotPlug)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw= %x\n", Index, SataConfig->PortSettings[Index].InterlockSw)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] External= %x\n", Index, SataConfig->PortSettings[Index].External)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp= %x\n", Index, SataConfig->PortSettings[Index].SpinUp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive= %x\n", Index, SataConfig->PortSettings[Index].SolidStateDrive)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp= %x\n", Index, SataConfig->PortSettings[Index].DevSlp)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig= %x\n", Index, SataConfig->PortSettings[Index].EnableDitoConfig)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal= %x\n", Index, SataConfig->PortSettings[Index].DmVal)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal= %x\n", Index, SataConfig->PortSettings[Index].DitoVal)); + DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd= %x\n", Index, SataConfig->PortSettings[Index].ZpOdd)); + } + + DEBUG ((DEBUG_INFO, " RaidDeviceId= %x\n", SataConfig->Rst.RaidDeviceId)); + DEBUG ((DEBUG_INFO, " Sata interrupt mode = %x\n", SataConfig->Rst.SataRstInterrupt)); + DEBUG ((DEBUG_INFO, " Raid0= %x\n", SataConfig->Rst.Raid0)); + DEBUG ((DEBUG_INFO, " Raid1= %x\n", SataConfig->Rst.Raid1)); + DEBUG ((DEBUG_INFO, " Raid10= %x\n", SataConfig->Rst.Raid10)); + DEBUG ((DEBUG_INFO, " Raid5= %x\n", SataConfig->Rst.Raid5)); + DEBUG ((DEBUG_INFO, " Irrt= %x\n", SataConfig->Rst.Irrt)); + DEBUG ((DEBUG_INFO, " OromUiBanner= %x\n", SataConfig->Rst.OromUiBanner)); + DEBUG ((DEBUG_INFO, " OromUiDelay= %x\n", SataConfig->Rst.OromUiDelay)); + DEBUG ((DEBUG_INFO, " HddUnlock= %x\n", SataConfig->Rst.HddUnlock)); + DEBUG ((DEBUG_INFO, " LedLocate= %x\n", SataConfig->Rst.LedLocate)); + DEBUG ((DEBUG_INFO, " IrrtOnly= %x\n", SataConfig->Rst.IrrtOnly)); + DEBUG ((DEBUG_INFO, " SmartStorage= %x\n", SataConfig->Rst.SmartStorage)); + DEBUG ((DEBUG_INFO, " LegacyOrom= %x\n", SataConfig->Rst.LegacyOrom)); + DEBUG ((DEBUG_INFO, " OptaneMemory= %x\n", SataConfig->Rst.OptaneMemory)); + DEBUG ((DEBUG_INFO, " CpuAttachedStorage= %x\n", SataConfig->Rst.CpuAttachedStorage)); + + DEBUG ((DEBUG_INFO, " SpeedSupport= %x\n", SataConfig->SpeedLimit)); + DEBUG ((DEBUG_INFO, " EsataSpeedLimit= %x\n", SataConfig->EsataSpeedLimit)); + DEBUG ((DEBUG_INFO, " LedEnable= %x\n", SataConfig->LedEnable)); + DEBUG ((DEBUG_INFO, " TestMode= %x\n", SataConfig->TestMode)); + DEBUG ((DEBUG_INFO, " SalpSupport= %x\n", SataConfig->SalpSupport)); + DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", SataConfig->PwrOptEnable)); + + for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) { + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].Enable)); + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort)); + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay)); + } + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T1M %x\n", SataConfig->ThermalThrottling.P0T1M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T2M %x\n", SataConfig->ThermalThrottling.P0T2M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T3M %x\n", SataConfig->ThermalThrottling.P0T3M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDisp %x\n", SataConfig->ThermalThrottling.P0TDisp)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0Tinact %x\n", SataConfig->ThermalThrottling.P0Tinact)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDispFinit %x\n", SataConfig->ThermalThrottling.P0TDispFinit)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T1M %x\n", SataConfig->ThermalThrottling.P1T1M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T2M %x\n", SataConfig->ThermalThrottling.P1T2M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T3M %x\n", SataConfig->ThermalThrottling.P1T3M)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDisp %x\n", SataConfig->ThermalThrottling.P1TDisp)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1Tinact %x\n", SataConfig->ThermalThrottling.P1Tinact)); + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDispFinit %x\n", SataConfig->ThermalThrottling.P1TDispFinit)); + DEBUG ((DEBUG_INFO, " ThermalThrottling SuggestedSetting %x\n", SataConfig->ThermalThrottling.SuggestedSetting)); +} + +/** + Print PCH_IOAPIC_CONFIG and serial out. + + @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that provides the platform setting + +**/ +VOID +PchPrintIoApicConfig ( + IN CONST PCH_IOAPIC_CONFIG *IoApicConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config ------------------\n")); + DEBUG ((DEBUG_INFO, " IoApicEntry24_119= %x\n", IoApicConfig->IoApicEntry24_119)); + DEBUG ((DEBUG_INFO, " Enable8254ClockGating= %x\n", IoApicConfig->Enable8254ClockGating)); + DEBUG ((DEBUG_INFO, " Enable8254ClockGatingOnS3= %x\n", IoApicConfig->Enable8254ClockGatingOnS3)); + DEBUG ((DEBUG_INFO, " IoApicId= %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= %x\n", LockDownConfig->GlobalSmi)); + DEBUG ((DEBUG_INFO, " BiosInterface= %x\n", LockDownConfig->BiosInterface)); + DEBUG ((DEBUG_INFO, " RtcMemoryLock= %x\n", LockDownConfig->RtcMemoryLock)); + DEBUG ((DEBUG_INFO, " BiosLock= %x\n", LockDownConfig->BiosLock)); + DEBUG ((DEBUG_INFO, " UnlockGpioPads= %x\n", LockDownConfig->UnlockGpioPads)); +} + +/** + Print PCH_HDAUDIO_CONFIG and serial out. + + @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that provides the platform setting + +**/ +VOID +PchPrintHdAudioConfig ( + IN CONST PCH_HDAUDIO_CONFIG *HdaConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config ------------------\n")); + DEBUG ((DEBUG_INFO, " DSP Enable = %x\n", HdaConfig->DspEnable)); + DEBUG ((DEBUG_INFO, " DSP UAA Compliance = %x\n", HdaConfig->DspUaaCompliance)); + DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect = %x\n", HdaConfig->IDispCodecDisconnect)); + DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme)); + DEBUG ((DEBUG_INFO, " Codec Sx Wake Capability = %x\n", HdaConfig->CodecSxWakeCapability)); + DEBUG ((DEBUG_INFO, " VC Type = %x\n", HdaConfig->VcType)); + DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n", HdaConfig->HdAudioLinkFrequency)); + DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n", HdaConfig->IDispLinkFrequency)); + DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n", HdaConfig->IDispLinkTmode)); + DEBUG ((DEBUG_INFO, " Audio Link: HDA Link = %x\n", HdaConfig->AudioLinkHda)); + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#0 = %x\n", HdaConfig->AudioLinkDmic0)); + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#1 = %x\n", HdaConfig->AudioLinkDmic1)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#0 = %x\n", HdaConfig->AudioLinkSsp0)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#1 = %x\n", HdaConfig->AudioLinkSsp1)); + DEBUG ((DEBUG_INFO, " Audio Link: SSP#2 = %x\n", HdaConfig->AudioLinkSsp1)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#1 = %x\n", HdaConfig->AudioLinkSndw1)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#2 = %x\n", HdaConfig->AudioLinkSndw2)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#3 = %x\n", HdaConfig->AudioLinkSndw3)); + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#4 = %x\n", HdaConfig->AudioLinkSndw4)); + DEBUG ((DEBUG_INFO, " SoundWire Buffer RCOMP = %x\n", HdaConfig->SndwBufferRcomp)); + DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n", HdaConfig->ResetWaitTimer)); + DEBUG ((DEBUG_INFO, " VerbTableEntryNum = %x\n", HdaConfig->VerbTableEntryNum)); + DEBUG ((DEBUG_INFO, " VerbTablePtr = %x\n", HdaConfig->VerbTablePtr)); +} + +/** + 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 = %x\n", PmConfig->WakeConfig.PmeB0S5Dis)); + DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride = %x\n", PmConfig->WakeConfig.WolEnableOverride)); + DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx = %x\n", PmConfig->WakeConfig.LanWakeFromDeepSx)); + DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx = %x\n", PmConfig->WakeConfig.PcieWakeFromDeepSx)); + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable = %x\n", PmConfig->WakeConfig.WoWlanEnable)); + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable = %x\n", PmConfig->WakeConfig.WoWlanDeepSxEnable)); + + DEBUG ((DEBUG_INFO, " PchDeepSxPol = %x\n", PmConfig->PchDeepSxPol)); + DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert = %x\n", PmConfig->PchSlpS3MinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert = %x\n", PmConfig->PchSlpS4MinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert = %x\n", PmConfig->PchSlpSusMinAssert)); + DEBUG ((DEBUG_INFO, " PchSlpAMinAssert = %x\n", PmConfig->PchSlpAMinAssert)); + DEBUG ((DEBUG_INFO, " LpcClockRun = %x\n", PmConfig->LpcClockRun)); + DEBUG ((DEBUG_INFO, " SlpStrchSusUp = %x\n", PmConfig->SlpStrchSusUp)); + DEBUG ((DEBUG_INFO, " SlpLanLowDc = %x\n", PmConfig->SlpLanLowDc)); + DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n", PmConfig->PwrBtnOverridePeriod)); + DEBUG ((DEBUG_INFO, " DisableEnergyReport = %x\n", PmConfig->DisableEnergyReport)); + DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown = %x\n", PmConfig->DisableDsxAcPresentPulldown)); + DEBUG ((DEBUG_INFO, " PchPwrCycDur = %x\n", PmConfig->PchPwrCycDur)); + DEBUG ((DEBUG_INFO, " PciePllSsc = %x\n", PmConfig->PciePllSsc)); + DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n", PmConfig->DisableNativePowerButton)); + DEBUG ((DEBUG_INFO, " SlpS0Enabled = %x\n", PmConfig->SlpS0Enable)); + DEBUG ((DEBUG_INFO, " MeWakeSts = %x\n", PmConfig->MeWakeSts)); + DEBUG ((DEBUG_INFO, " WolOvrWkSts = %x\n", PmConfig->WolOvrWkSts)); + DEBUG ((DEBUG_INFO, " EnableTcoTimer = %x\n", PmConfig->EnableTcoTimer)); + DEBUG ((DEBUG_INFO, " VrAlert = %x\n", PmConfig->VrAlert)); + DEBUG ((DEBUG_INFO, " PowerButtonDebounce = %x\n", PmConfig->PowerButtonDebounce)); + DEBUG ((DEBUG_INFO, " SlpS0VmRuntimeControl = %x\n", PmConfig->SlpS0VmRuntimeControl)); + DEBUG ((DEBUG_INFO, " SlpS0Vm070VSupport = %x\n", PmConfig->SlpS0Vm070VSupport)); + DEBUG ((DEBUG_INFO, " SlpS0Vm075VSupport = %x\n", PmConfig->SlpS0Vm075VSupport)); + DEBUG ((DEBUG_INFO, " SlpS0Override = %x\n", PmConfig->SlpS0Override)); + DEBUG ((DEBUG_INFO, " SlpS0DisQForDebug = %x\n", PmConfig->SlpS0DisQForDebug)); + DEBUG ((DEBUG_INFO, " PsOnEnable = %x\n", PmConfig->PsOnEnable)); + DEBUG ((DEBUG_INFO, " CpuC10GatePinEnable = %x\n", PmConfig->CpuC10GatePinEnable)); + DEBUG ((DEBUG_INFO, " PmcDbgMsgEn = %x\n", PmConfig->PmcDbgMsgEn)); + DEBUG ((DEBUG_INFO, " ModPhySusPgEnable = %x\n", PmConfig->ModPhySusPgEnable)); + DEBUG ((DEBUG_INFO, " SlpS0WithGbeSupport = %x\n", PmConfig->SlpS0WithGbeSupport)); +} + +/** + Print PCH_DMI_CONFIG and serial out. + + @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides the platform setting + +**/ +VOID +PchPrintDmiConfig ( + IN CONST PCH_DMI_CONFIG *DmiConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config ------------------\n")); + DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", DmiConfig->PwrOptEnable)); + DEBUG ((DEBUG_INFO, " DmiAspmCtrl= %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= %x\n", SerialIrqConfig->SirqEnable)); + DEBUG ((DEBUG_INFO, " SirqMode= %x\n", SerialIrqConfig->SirqMode)); + DEBUG ((DEBUG_INFO, " StartFramePulse= %x\n", SerialIrqConfig->StartFramePulse)); +} +/** + Print PCH_THERMAL_CONFIG and serial out. + + @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that provides the platform setting + +**/ +VOID +PchPrintThermalConfig ( + IN CONST PCH_THERMAL_CONFIG *ThermalConfig + ) +{ + UINTN Index; + + DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config ------------------\n")); + DEBUG ((DEBUG_INFO, " TsmicLock= %x\n", ThermalConfig->TsmicLock)); + DEBUG ((DEBUG_INFO, " TTLevels T0Level %x centigrade degree\n", ThermalConfig->TTLevels.T0Level)); + DEBUG ((DEBUG_INFO, " TTLevels T1Level %x centigrade degree\n", ThermalConfig->TTLevels.T1Level)); + DEBUG ((DEBUG_INFO, " TTLevels T2Level %x centigrade degree\n", ThermalConfig->TTLevels.T2Level)); + DEBUG ((DEBUG_INFO, " TTLevels TTEnable %x\n", ThermalConfig->TTLevels.TTEnable)); + DEBUG ((DEBUG_INFO, " TTLevels TTState13Enable %x\n", ThermalConfig->TTLevels.TTState13Enable)); + DEBUG ((DEBUG_INFO, " TTLevels TTLock %x\n", ThermalConfig->TTLevels.TTLock)); + DEBUG ((DEBUG_INFO, " TTLevels SuggestedSetting %x\n", ThermalConfig->TTLevels.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.TS0TW)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS1TW %x\n", ThermalConfig->DmiHaAWC.TS1TW)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS2TW %x\n", ThermalConfig->DmiHaAWC.TS2TW)); + DEBUG ((DEBUG_INFO, " DmiHaAWC TS3TW %x\n", ThermalConfig->DmiHaAWC.TS3TW)); + DEBUG ((DEBUG_INFO, " DmiHaAWC SuggestedSetting %x\n", ThermalConfig->DmiHaAWC.SuggestedSetting)); + + DEBUG ((DEBUG_INFO, " MemoryThrottling Enable= %x\n", ThermalConfig->MemoryThrottling.Enable)); + for (Index = 0; Index < MaxTsGpioPin; Index++) { + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PmsyncEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PmsyncEnable)); + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting C0TransmitEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].C0TransmitEnable)); + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PinSelection= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PinSelection)); + } + DEBUG ((DEBUG_INFO, " PchHotEnable = %x\n", ThermalConfig->PchHotEnable)); + DEBUG ((DEBUG_INFO, " PchHotLevel = %x\n", ThermalConfig->PchHotLevel)); +} + +/** + Print PCH_GENERAL_CONFIG and serial out. + + @param[in] PchGeneralConfig Pointer to a PCH_GENERAL_CONFIG that provides the platform setting + +**/ +VOID +PchPrintGeneralConfig ( + IN CONST PCH_GENERAL_CONFIG *PchGeneralConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH General Config ------------------\n")); + DEBUG ((DEBUG_INFO, " Crid= %x\n", PchGeneralConfig->Crid)); + DEBUG ((DEBUG_INFO, " LegacyIoLowLatency = %x\n", PchGeneralConfig->LegacyIoLowLatency)); +} + +/** + Print PCH_LAN_CONFIG and serial out. + + @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides the platform setting + +**/ +VOID +PchPrintLanConfig ( + IN CONST PCH_LAN_CONFIG *LanConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config ------------------\n")); + DEBUG ((DEBUG_INFO, " Enable= %x\n", LanConfig->Enable)); + DEBUG ((DEBUG_INFO, " LtrEnable= %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] = {"I2C0","I2C1","I2C2","I2C3","I2C4","I2C5","SPI0","SPI1","SPI2","UA00","UA01","UA02"}; +#endif + + DEBUG ((DEBUG_INFO, "------------------ PCH Serial IO Config ------------------\n")); + DEBUG_CODE_BEGIN (); + for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) { + DEBUG ((DEBUG_INFO, " SerialIoController %a: Mode 0x%x\n", DeviceName[Index], SerialIoConfig->DevMode[Index])); + } + DEBUG_CODE_END (); + for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) { + DEBUG ((DEBUG_INFO, " SpiCsPolarity[%d] = 0x%x\n", Index, SerialIoConfig->SpiCsPolarity[Index])); + } + for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) { + DEBUG ((DEBUG_INFO, " UartHwFlowCtrl[%d] = 0x%x\n", Index, SerialIoConfig->UartHwFlowCtrl[Index])); + } + for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index ++) { + DEBUG ((DEBUG_INFO, " I2cPadsTermination[%d] = 0x%x\n", Index, SerialIoConfig->I2cPadsTermination[Index])); + } + DEBUG ((DEBUG_INFO, " DebugUartNumber = 0x%x\n", SerialIoConfig->DebugUartNumber)); + DEBUG ((DEBUG_INFO, " EnableDebugUartAfterPost = 0x%x\n", SerialIoConfig->EnableDebugUartAfterPost)); + DEBUG ((DEBUG_INFO, " Uart0PinMuxing = 0x%x\n", SerialIoConfig->Uart0PinMuxing)); +} + +/** + Print PCH_INTERRUPT_CONFIG and serial out + + @param[in] InterruptConfig Pointer to Interrupt Configuration structure + +**/ +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 = 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 = 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= %d\n", InterruptConfig->GpioIrqRoute)); + DEBUG ((DEBUG_INFO, " SciIrqSelect= %d\n", InterruptConfig->SciIrqSelect)); + DEBUG ((DEBUG_INFO, " TcoIrqEnable= %d\n", InterruptConfig->TcoIrqEnable)); + DEBUG ((DEBUG_INFO, " TcoIrqSelect= %d\n", InterruptConfig->TcoIrqSelect)); +} + +/** + Print PCH_SCS_CONFIG and serial out. + + @param[in] ScsConfig Pointer to a PCH_SCS_CONFIG that provides the platform setting + +**/ +VOID +PchPrintScsConfig ( + IN CONST PCH_SCS_CONFIG *ScsConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH SCS Config ------------------\n")); + DEBUG ((DEBUG_INFO, " ScsEmmcEnabled = %x\n", ScsConfig->ScsEmmcEnabled)); + DEBUG ((DEBUG_INFO, " ScsSdcardEnabled = %x\n", ScsConfig->ScsSdcardEnabled)); + DEBUG ((DEBUG_INFO, " SdCardPowerEnableActiveHigh = %x\n", ScsConfig->SdCardPowerEnableActiveHigh)); + DEBUG ((DEBUG_INFO, " ScsUfsEnabled = %x\n", ScsConfig->ScsUfsEnabled)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400Enabled = %x\n", ScsConfig->ScsEmmcHs400Enabled)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TuningRequired = %x\n", ScsConfig->ScsEmmcHs400TuningRequired)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DllDataValid = %x\n", ScsConfig->ScsEmmcHs400DllDataValid)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400RxStrobeDll1 = %x\n", ScsConfig->ScsEmmcHs400RxStrobeDll1)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TxDataDll = %x\n", ScsConfig->ScsEmmcHs400TxDataDll)); + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DriverStrength = %x\n", ScsConfig->ScsEmmcHs400DriverStrength)); +} + +/** + Print PCH_ISH_CONFIG and serial out. + + @param[in] IshConfig Pointer to a PCH_ISH_CONFIG that provides the platform setting + +**/ +VOID +PchPrintIshConfig ( + IN CONST PCH_ISH_CONFIG *IshConfig + ) +{ + DEBUG ((DEBUG_INFO, "------------------ PCH ISH Config ------------------\n")); + DEBUG ((DEBUG_INFO, " SPI GPIO Assigned = %x\n", IshConfig->SpiGpioAssign)); + DEBUG ((DEBUG_INFO, " UART0 GPIO Assigned = %x\n", IshConfig->Uart0GpioAssign)); + DEBUG ((DEBUG_INFO, " UART1 GPIO Assigned = %x\n", IshConfig->Uart1GpioAssign)); + DEBUG ((DEBUG_INFO, " I2C0 GPIO Assigned = %x\n", IshConfig->I2c0GpioAssign)); + DEBUG ((DEBUG_INFO, " I2C1 GPIO Assigned = %x\n", IshConfig->I2c1GpioAssign)); + DEBUG ((DEBUG_INFO, " I2C2 GPIO Assigned = %x\n", IshConfig->I2c2GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_0 GPIO Assigned = %x\n", IshConfig->Gp0GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_1 GPIO Assigned = %x\n", IshConfig->Gp1GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_2 GPIO Assigned = %x\n", IshConfig->Gp2GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_3 GPIO Assigned = %x\n", IshConfig->Gp3GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_4 GPIO Assigned = %x\n", IshConfig->Gp4GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_5 GPIO Assigned = %x\n", IshConfig->Gp5GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_6 GPIO Assigned = %x\n", IshConfig->Gp6GpioAssign)); + DEBUG ((DEBUG_INFO, " GP_7 GPIO Assigned = %x\n", IshConfig->Gp7GpioAssign)); +} + +/** + 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 = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) { + DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].WriteProtectionEnable)); + DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].ReadProtectionEnable)); + DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeLimit)); + DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d] = %x\n", Index, FlashProtectConfig->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= %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 = %x\n", CnviConfig->Mode)); + DEBUG ((DEBUG_INFO, "CNVi MfUart1 type = %x\n", CnviConfig->MfUart1Type)); +} + +/** + 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 = %x\n", HsioConfig->ChipsetInitBinPtr)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Length = %x\n", HsioConfig->ChipsetInitBinLen)); + BiosChipsetInitVerInfoPtr = (PCH_HSIO_VER_INFO *) HsioConfig->ChipsetInitBinPtr; + if (HsioConfig->ChipsetInitBinPtr && HsioConfig->ChipsetInitBinLen) { + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC = %x\n", BiosChipsetInitVerInfoPtr->BaseCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC = %x\n", BiosChipsetInitVerInfoPtr->OemCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC = %x\n", BiosChipsetInitVerInfoPtr->SusCrc)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Version = %x\n", BiosChipsetInitVerInfoPtr->Version)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Product = %x\n", BiosChipsetInitVerInfoPtr->Product)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Metal Layer = %x\n", BiosChipsetInitVerInfoPtr->MetalLayer)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base Layer = %x\n", BiosChipsetInitVerInfoPtr->BaseLayer)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM Version = %x\n", BiosChipsetInitVerInfoPtr->OemVersion)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Debug Mode = %x\n", BiosChipsetInitVerInfoPtr->DebugMode)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC Valid = %x\n", BiosChipsetInitVerInfoPtr->OemCrcValid)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC Valid = %x\n", BiosChipsetInitVerInfoPtr->SusCrcValid)); + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC Valid = %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 = GetConfigBlock ((VOID *) SiPolicyPpi, &gPchGeneralConfigGuid, (VOID *) &PchGeneralConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIoApicConfigGuid, (VOID *) &IoApicConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gDmiConfigGuid, (VOID *) &DmiConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHdAudioConfigGuid, (VOID *) &HdAudioConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gInterruptConfigGuid, (VOID *) &InterruptConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIshConfigGuid, (VOID *) &IshConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLanConfigGuid, (VOID *) &LanConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLockDownConfigGuid, (VOID *) &LockDownConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gP2sbConfigGuid, (VOID *) &P2sbConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPmConfigGuid, (VOID *) &PmConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gScsConfigGuid, (VOID *) &ScsConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIrqConfigGuid, (VOID *) &SerialIrqConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gThermalConfigGuid, (VOID *) &ThermalConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gUsbConfigGuid, (VOID *) &UsbConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gEspiConfigGuid, (VOID *) &EspiConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCnviConfigGuid, (VOID *) &CnviConfig); + ASSERT_EFI_ERROR (Status); + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHsioConfigGuid, (VOID *) &HsioConfig); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy Start ------------------------\n")); + DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPolicyPpi->TableHeader.Header.Revision)); + + PchPrintGeneralConfig (PchGeneralConfig); + PchPrintPcieConfig (PcieRpConfig); + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum (); SataCtrlIndex++) { + SataConfig = 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 Protocol End --------------------------\n")); +DEBUG_CODE_END(); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c new file mode 100644 index 0000000000..2a1da20667 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.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[] = { + 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Name = %g\n", &PchGeneralConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Name = %g\n", &PcieRpConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + PCI Express related settings + ********************************/ + PcieRpConfig->RpFunctionSwap = TRUE; + + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + PcieRpConfig->RootPort[Index].Aspm = PchPcieAspmAutoConfig; + PcieRpConfig->RootPort[Index].PmSci = TRUE; + PcieRpConfig->RootPort[Index].AcsEnabled = TRUE; + PcieRpConfig->RootPort[Index].PtmEnabled = TRUE; + PcieRpConfig->RootPort[Index].DpcEnabled = TRUE; + PcieRpConfig->RootPort[Index].RpDpcExtensionsEnabled = TRUE; + PcieRpConfig->RootPort[Index].MaxPayload = PchPcieMaxPayload256; + PcieRpConfig->RootPort[Index].SlotImplemented = TRUE; + PcieRpConfig->RootPort[Index].PhysicalSlotNumber = (UINT8) Index; + PcieRpConfig->RootPort[Index].L1Substates = PchPcieL1SubstatesL1_1_2; + PcieRpConfig->RootPort[Index].EnableCpm = TRUE; + PcieRpConfig->RootPort[Index].Gen3EqPh3Method = PchPcieEqHardware; + + // + // PCIe LTR Configuration. + // + PcieRpConfig->RootPort[Index].LtrEnable = TRUE; + + PcieRpConfig->RootPort[Index].LtrMaxSnoopLatency = 0x1003; + PcieRpConfig->RootPort[Index].LtrMaxNoSnoopLatency = 0x1003; + + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMode = 2; + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMultiplier = 2; + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideValue = 60; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMode = 2; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier = 2; + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideValue = 60; + + PcieRpConfig->RootPort[Index].Uptp = 5; + PcieRpConfig->RootPort[Index].Dptp = 7; + + PcieRpConfig->EqPh3LaneParam[Index].Cm = 6; + PcieRpConfig->EqPh3LaneParam[Index].Cp = 2; + } + + PcieRpConfig->SwEqCoeffList[0].Cm = 4; + PcieRpConfig->SwEqCoeffList[0].Cp = 8; + PcieRpConfig->SwEqCoeffList[1].Cm = 6; + PcieRpConfig->SwEqCoeffList[1].Cp = 2; + PcieRpConfig->SwEqCoeffList[2].Cm = 8; + PcieRpConfig->SwEqCoeffList[2].Cp = 6; + PcieRpConfig->SwEqCoeffList[3].Cm = 10; + PcieRpConfig->SwEqCoeffList[3].Cp = 8; + PcieRpConfig->SwEqCoeffList[4].Cm = 12; + PcieRpConfig->SwEqCoeffList[4].Cp = 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 = (PCH_SATA_CONFIG *)ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Name = %g\n", &SataConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SataConfig->Header.GuidHob.Header.HobLength)); + + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum (); SataCtrlIndex++, SataConfig++) { + /******************************** + SATA related settings + ********************************/ + SataConfig->Enable = TRUE; + SataConfig->SalpSupport = TRUE; + SataConfig->SataMode = PchSataModeAhci; + + for (PortIndex = 0; PortIndex < GetPchMaxSataPortNum (SataCtrlIndex); PortIndex++) { + SataConfig->PortSettings[PortIndex].Enable = TRUE; + SataConfig->PortSettings[PortIndex].DmVal = 15; + SataConfig->PortSettings[PortIndex].DitoVal = 625; + } + + SataConfig->Rst.Raid0 = TRUE; + SataConfig->Rst.Raid1 = TRUE; + SataConfig->Rst.Raid10 = TRUE; + SataConfig->Rst.Raid5 = TRUE; + SataConfig->Rst.Irrt = TRUE; + SataConfig->Rst.OromUiBanner = TRUE; + SataConfig->Rst.OromUiDelay = PchSataOromDelay2sec; + SataConfig->Rst.HddUnlock = TRUE; + SataConfig->Rst.LedLocate = TRUE; + SataConfig->Rst.IrrtOnly = TRUE; + SataConfig->Rst.SmartStorage = TRUE; + SataConfig->Rst.OptaneMemory = TRUE; + SataConfig->Rst.CpuAttachedStorage = TRUE; + + for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) { + SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay = 100; + } + + SataConfig->PwrOptEnable = TRUE; + SataConfig->ThermalThrottling.SuggestedSetting = 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 = GetConfigBlock ((VOID *) SiPolicy, &gSataConfigGuid, (VOID *) &SataConfig); + ASSERT_EFI_ERROR (Status); + + SataConfig += SataCtrlIndex; + + return SataConfig; +} + +/** + Load Config block default + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIoApicConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_IOAPIC_CONFIG *IoApicConfig; + IoApicConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Name = %g\n", &IoApicConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IoApicConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Io Apic configuration + ********************************/ + IoApicConfig->IoApicId = 0x02; + IoApicConfig->IoApicEntry24_119 = TRUE; + IoApicConfig->Enable8254ClockGating = TRUE; + IoApicConfig->Enable8254ClockGatingOnS3 = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadDmiConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_DMI_CONFIG *DmiConfig; + DmiConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Name = %g\n", &DmiConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", DmiConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + DMI related settings + ********************************/ + DmiConfig->DmiAspmCtrl = PchPcieAspmAutoConfig; +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadFlashProtectionConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig; + FlashProtectionConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Name = %g\n", &FlashProtectionConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HdAudioConfig->Header.GuidHob.Name = %g\n", &HdAudioConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HdAudioConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HdAudioConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + HD-Audio configuration + ********************************/ + HdAudioConfig->DspEnable = TRUE; + HdAudioConfig->HdAudioLinkFrequency = PchHdaLinkFreq24MHz; + HdAudioConfig->IDispLinkFrequency = PchHdaLinkFreq96MHz; + HdAudioConfig->IDispLinkTmode = PchHdaIDispMode2T; + HdAudioConfig->ResetWaitTimer = 600; // Must be at least 521us (25 frames) + HdAudioConfig->AudioLinkHda = TRUE; + HdAudioConfig->AudioLinkDmic0 = TRUE; + HdAudioConfig->AudioLinkDmic1 = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadInterruptConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_INTERRUPT_CONFIG *InterruptConfig; + InterruptConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Name = %g\n", &InterruptConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Header.HobLength = 0x%x\n", InterruptConfig->Header.GuidHob.Header.HobLength)); + + LoadDeviceInterruptConfig (InterruptConfig); + + ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <= PCH_MAX_PXRC_CONFIG); + CopyMem ( + InterruptConfig->PxRcConfig, + mPxRcConfig, + sizeof (mPxRcConfig) + ); + + InterruptConfig->GpioIrqRoute = 14; + InterruptConfig->SciIrqSelect = 9; + InterruptConfig->TcoIrqSelect = 9; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIshConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ISH_CONFIG *IshConfig; + IshConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Name = %g\n", &IshConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + LpcDid = PchGetLpcDid (); + + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Name = %g\n", &LanConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LanConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Lan configuration + ********************************/ + LanConfig->Enable = TRUE; + LanConfig->LtrEnable = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadLockDownConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LOCK_DOWN_CONFIG *LockDownConfig; + LockDownConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Name = %g\n", &LockDownConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LockDownConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Lockdown configuration + ********************************/ + LockDownConfig->GlobalSmi = TRUE; + LockDownConfig->BiosInterface = TRUE; + LockDownConfig->RtcMemoryLock = TRUE; + LockDownConfig->BiosLock = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadP2sbConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_P2SB_CONFIG *P2sbConfig; + P2sbConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Name = %g\n", &P2sbConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Name = %g\n", &PmConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PmConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + MiscPm Configuration + ********************************/ + PmConfig->MeWakeSts = TRUE; + PmConfig->WolOvrWkSts = TRUE; + + PmConfig->WakeConfig.WolEnableOverride = TRUE; + PmConfig->WakeConfig.LanWakeFromDeepSx = TRUE; + + PmConfig->PchSlpS3MinAssert = PchSlpS350ms; + PmConfig->PchSlpS4MinAssert = PchSlpS41s; + PmConfig->PchSlpSusMinAssert = PchSlpSus4s; + PmConfig->PchSlpAMinAssert = PchSlpA2s; + + PmConfig->SlpLanLowDc = TRUE; + PmConfig->PciePllSsc = 0xFF; + PmConfig->LpcClockRun = TRUE; + PmConfig->SlpS0Enable = TRUE; + PmConfig->CpuC10GatePinEnable = TRUE; + if (IsWhlCpu () && (GetCpuStepping () == EnumCflV0)) { + PmConfig->SlpS0WithGbeSupport = FALSE; + } else { + PmConfig->SlpS0WithGbeSupport = TRUE; + } + + if (IsPchLp ()) { + PmConfig->ModPhySusPgEnable = TRUE; + } +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadScsConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_SCS_CONFIG *ScsConfig; + ScsConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Name = %g\n", &ScsConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ScsConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SCS Configuration + ********************************/ + ScsConfig->ScsEmmcEnabled = IsPchLp () ? TRUE : FALSE; // eMMC present on PCH-LP only + ScsConfig->ScsEmmcHs400DriverStrength = DriverStrength40Ohm; + //Enable Sd Card controller for Non-Desktop sku platforms + if (GetCpuSku () != EnumCpuTrad) { + ScsConfig->ScsSdcardEnabled = TRUE; + } + ScsConfig->SdCardPowerEnableActiveHigh = TRUE; + ScsConfig->ScsUfsEnabled = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Name = %g\n", &SerialIoConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIoConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SerialIo Configuration + ********************************/ + for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) { + SerialIoConfig->DevMode[Index] = PchSerialIoPci; + } + SerialIoConfig->DebugUartNumber = PcdGet8 (PcdSerialIoUartNumber); +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadSerialIrqConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig; + SerialIrqConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Name = %g\n", &SerialIrqConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIrqConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Serial IRQ Configuration + ********************************/ + SerialIrqConfig->SirqEnable = TRUE; + SerialIrqConfig->SirqMode = PchQuietMode; + SerialIrqConfig->StartFramePulse = PchSfpw4Clk; +} +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadThermalConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_THERMAL_CONFIG *ThermalConfig; + ThermalConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Name = %g\n", &ThermalConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ThermalConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Thermal configuration. + ********************************/ + ThermalConfig->TsmicLock = TRUE; + ThermalConfig->PchHotLevel = 0x154; + ThermalConfig->TTLevels.SuggestedSetting = TRUE; + ThermalConfig->TTLevels.PchCrossThrottling = TRUE; + ThermalConfig->DmiHaAWC.SuggestedSetting = TRUE; + + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable = TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnable = TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable = TRUE; + ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnable = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadUsbConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + UINTN PortIndex; + USB_CONFIG *UsbConfig; + UsbConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Name = %g\n", &UsbConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Header.HobLength = 0x%x\n", UsbConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + USB related configuration + ********************************/ + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) { + UsbConfig->PortUsb20[PortIndex].Enable = TRUE; + } + + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) { + UsbConfig->PortUsb30[PortIndex].Enable = TRUE; + } + + // + // BIOS should program PDO in PEI phase by default + // + UsbConfig->PdoProgramming = TRUE; + + // + // Default values of USB2 AFE settings. + // + UsbConfig->Usb2PhySusPgEnable = TRUE; + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) { + UsbConfig->PortUsb20[PortIndex].Afe.Petxiset = 3; + UsbConfig->PortUsb20[PortIndex].Afe.Txiset = 2; + UsbConfig->PortUsb20[PortIndex].Afe.Predeemp = 1; + UsbConfig->PortUsb20[PortIndex].Afe.Pehalfbit = 1; + } + + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) { + UsbConfig->PortUsb30HsioRx[PortIndex].HsioOlfpsCfgPullUpDwnRes = 3; + } + + UsbConfig->XhciOcLock = TRUE; + + // + // xDCI configuration + // + UsbConfig->XdciConfig.Enable = FALSE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadEspiConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ESPI_CONFIG *EspiConfig; + EspiConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Name = %g\n", &EspiConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", EspiConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Espi configuration. + ********************************/ + EspiConfig->BmeMasterSlaveEnabled = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadCnviConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_CNVI_CONFIG *CnviConfig; + CnviConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Name = %g\n", &CnviConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CnviConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + Cnvi configuration. + ********************************/ + CnviConfig->Mode = CnviModeAuto; // Automatic detection +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHsioConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HSIO_CONFIG *HsioConfig; + HsioConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Name = %g\n", &HsioConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioConfig->Header.GuidHob.Header.HobLength)); +} + +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mPchIpBlocks [] = { + {&gPchGeneralConfigGuid, sizeof (PCH_GENERAL_CONFIG), PCH_GENERAL_CONFIG_REVISION, LoadPchGeneralConfigDefault}, + {&gPcieRpConfigGuid, sizeof (PCH_PCIE_CONFIG), PCIE_RP_CONFIG_REVISION, LoadPcieRpConfigDefault}, + {&gSataConfigGuid, sizeof (PCH_SATA_CONFIG), SATA_CONFIG_REVISION, LoadSataConfigDefault}, + {&gIoApicConfigGuid, sizeof (PCH_IOAPIC_CONFIG), IOAPIC_CONFIG_REVISION, LoadIoApicConfigDefault}, + {&gDmiConfigGuid, sizeof (PCH_DMI_CONFIG), DMI_CONFIG_REVISION, LoadDmiConfigDefault}, + {&gFlashProtectionConfigGuid, sizeof (PCH_FLASH_PROTECTION_CONFIG), FLASH_PROTECTION_CONFIG_REVISION, LoadFlashProtectionConfigDefault}, + {&gHdAudioConfigGuid, sizeof (PCH_HDAUDIO_CONFIG), HDAUDIO_CONFIG_REVISION, LoadHdAudioConfigDefault}, + {&gInterruptConfigGuid, sizeof (PCH_INTERRUPT_CONFIG), INTERRUPT_CONFIG_REVISION, LoadInterruptConfigDefault}, + {&gIshConfigGuid, sizeof (PCH_ISH_CONFIG), ISH_CONFIG_REVISION, LoadIshConfigDefault}, + {&gLanConfigGuid, sizeof (PCH_LAN_CONFIG), LAN_CONFIG_REVISION, LoadLanConfigDefault}, + {&gLockDownConfigGuid, sizeof (PCH_LOCK_DOWN_CONFIG), LOCK_DOWN_CONFIG_REVISION, LoadLockDownConfigDefault}, + {&gP2sbConfigGuid, sizeof (PCH_P2SB_CONFIG), P2SB_CONFIG_REVISION, LoadP2sbConfigDefault}, + {&gPmConfigGuid, sizeof (PCH_PM_CONFIG), PM_CONFIG_REVISION, LoadPmConfigDefault}, + {&gScsConfigGuid, sizeof (PCH_SCS_CONFIG), SCS_CONFIG_REVISION, LoadScsConfigDefault}, + {&gSerialIoConfigGuid, sizeof (PCH_SERIAL_IO_CONFIG), SERIAL_IO_CONFIG_REVISION, LoadSerialIoConfigDefault}, + {&gSerialIrqConfigGuid, sizeof (PCH_LPC_SIRQ_CONFIG), SERIAL_IRQ_CONFIG_REVISION, LoadSerialIrqConfigDefault}, + {&gThermalConfigGuid, sizeof (PCH_THERMAL_CONFIG), THERMAL_CONFIG_REVISION, LoadThermalConfigDefault}, + {&gUsbConfigGuid, sizeof (USB_CONFIG), USB_CONFIG_REVISION, LoadUsbConfigDefault}, + {&gEspiConfigGuid, sizeof (PCH_ESPI_CONFIG), ESPI_CONFIG_REVISION, LoadEspiConfigDefault}, + {&gCnviConfigGuid, sizeof (PCH_CNVI_CONFIG), CNVI_CONFIG_REVISION, LoadCnviConfigDefault}, + {&gHsioConfigGuid, sizeof (PCH_HSIO_CONFIG), HSIO_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 (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)); +} + +/** + PchAddConfigBlocks add all PCH config blocks. + + @param[in] ConfigBlockTableAddress The pointer to add PCH config blocks + + @retval EFI_SUCCESS The policy default is initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer +**/ +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/PeiPchPolicyLib/PeiPchPolicyLibCnl.c new file mode 100644 index 0000000000..d19692ff2c --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibCnl.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 Host 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 patching as + PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Mapping + + 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[] = { +// {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, programmed 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 in PCR[SERIALIO] + PCICFGCTRL[10] + {30, 3, PchIntD, 23}, // SerialIo: SPI #1, INTA is default, programmed in 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, programmed 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, programmed in PCR[SERIALIO] + PCICFGCTRL[1] + {21, 1, PchIntB, 17}, // SerialIo I2C Controller #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[2] + {21, 2, PchIntC, 18}, // SerialIo I2C Controller #2, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[3] + {21, 3, PchIntD, 19}, // SerialIo I2C Controller #3, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[4] + {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value, programmed 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 devices that exist on PCH-LP +// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mPchLpOnlyDevIntConfig[] = { + {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, programmed in PCR[SERIALIO] + PCICFGCTRL[5] + {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, programmed 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 in 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 mPchHOnlyDevIntConfig[] = { + {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 in 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 = ARRAY_SIZE (mDevIntConfig); + ASSERT (IntConfigTableEntries <= PCH_MAX_DEVICE_INTERRUPT_CONFIG); + InterruptConfig->NumOfDevIntConfig = IntConfigTableEntries; + CopyMem ( + InterruptConfig->DevIntConfig, + mDevIntConfig, + sizeof (mDevIntConfig) + ); + + if (IsPchLp ()) { + CopyMem ( + &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig]), + mPchLpOnlyDevIntConfig, + sizeof (mPchLpOnlyDevIntConfig) + ); + InterruptConfig->NumOfDevIntConfig += ARRAY_SIZE (mPchLpOnlyDevIntConfig); + } else if (IsPchH ()) { + CopyMem ( + &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig]), + mPchHOnlyDevIntConfig, + sizeof (mPchHOnlyDevIntConfig) + ); + InterruptConfig->NumOfDevIntConfig += ARRAY_SIZE (mPchHOnlyDevIntConfig); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c new file mode 100644 index 0000000000..dfab5d29c2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Name = %g\n", &PchGeneralPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Name = %g\n", &DciPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Name = %g\n", &WdtPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PchTraceHubPreMemConfig->Header.GuidHob.Name = %g\n", &PchTraceHubPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PchTraceHubPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PchTraceHubPreMemConfig->Header.GuidHob.Header.HobLength)); +} + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = { + 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Name = %g\n", &SmbusPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SmbusPreMemConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + SMBus configuration + ********************************/ + SmbusPreMemConfig->Enable = TRUE; + SmbusPreMemConfig->DynamicPowerGating = TRUE; + SmbusPreMemConfig->SpdWriteDisable = TRUE; + SmbusPreMemConfig->SmbusIoBase = PcdGet16 (PcdSmbusBaseAddress); + ASSERT (sizeof (mSmbusRsvdAddresses) <= PCH_MAX_SMBUS_RESERVED_ADDRESS); + SmbusPreMemConfig->NumRsvdSmbusAddresses = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Name = %g\n", &LpcPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LpcPreMemConfig->Header.GuidHob.Header.HobLength)); + + /******************************** + LPC Configuration + ********************************/ + LpcPreMemConfig->EnhancePort8xhDecoding = TRUE; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadHsioPciePreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig; + HsioPciePreMemConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Name = %g\n", &HsioPciePreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Header.HobLength = 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Name = %g\n", &HsioSataPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Header.HobLength = 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 = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig); + ASSERT_EFI_ERROR (Status); + + HsioSataPreMemConfig += 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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name = %g\n", &PcieRpPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpPreMemConfig->Header.GuidHob.Header.HobLength)); + + for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); RpIndex ++) { + PcieRpPreMemConfig->RpEnabledMask |= (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 = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name = %g\n", &HdaPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HdaPreMemConfig->Header.GuidHob.Header.HobLength)); + HdaPreMemConfig->Enable = 1; +} + +/** + Load Config block default + + @param[in] ConfigBlockPointer Pointer to config block +**/ +VOID +LoadIshPreMemConfigDefault ( + IN VOID *ConfigBlockPointer + ) +{ + PCH_ISH_PREMEM_CONFIG *IshPreMemConfig; + IshPreMemConfig = ConfigBlockPointer; + + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name = %g\n", &IshPreMemConfig->Header.GuidHob.Name)); + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IshPreMemConfig->Header.GuidHob.Header.HobLength)); + //Enable ISH controller for Non-Desktop sku platforms + if (GetCpuSku () != EnumCpuTrad) { + IshPreMemConfig->Enable = TRUE; + } +} + + +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mPchIpBlocksPreMem [] = { + {&gPchGeneralPreMemConfigGuid, sizeof (PCH_GENERAL_PREMEM_CONFIG), PCH_GENERAL_PREMEM_CONFIG_REVISION, LoadPchGeneralPreMemConfigDefault}, + {&gDciPreMemConfigGuid, sizeof (PCH_DCI_PREMEM_CONFIG), DCI_PREMEM_CONFIG_REVISION, LoadDciPreMemConfigDefault}, + {&gWatchDogPreMemConfigGuid, sizeof (PCH_WDT_PREMEM_CONFIG), WATCH_DOG_PREMEM_CONFIG_REVISION, LoadWatchDogPreMemConfigDefault}, + {&gPchTraceHubPreMemConfigGuid, sizeof (PCH_TRACE_HUB_PREMEM_CONFIG), PCH_TRACEHUB_PREMEM_CONFIG_REVISION, LoadPchTraceHubPreMemConfigDefault}, + {&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, LoadHsioPciePreMemConfigDefault}, + {&gHsioSataPreMemConfigGuid, sizeof (PCH_HSIO_SATA_PREMEM_CONFIG), HSIO_SATA_PREMEM_CONFIG_REVISION, LoadHsioSataPreMemConfigDefault}, + {&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 table +**/ +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 config blocks + + @retval EFI_SUCCESS The policy default is initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer +**/ +EFI_STATUS +EFIAPI +PchAddPreMemConfigBlocks ( + IN VOID *ConfigBlockTableAddress + ) +{ + DEBUG ((DEBUG_INFO, "PCH AddPreMemConfigBlocks\n")); + + return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocksPreMem[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/PchReset.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 platform specific reset. + The exact type of the reset is defined by 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 = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR)); + EfiPeiReset2Ppi = (EFI_PEI_RESET2_PPI *) AllocateZeroPool (sizeof (EFI_PEI_RESET2_PPI)); + if ((EfiPeiReset2Descriptor == NULL) || + (EfiPeiReset2Ppi == NULL)) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + /// + /// Initialize the EFI Reset2 ppi instance + /// + EfiPeiReset2Ppi->ResetSystem = ResetSystem; + + EfiPeiReset2Descriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + EfiPeiReset2Descriptor->Guid = &gEfiPeiReset2PpiGuid; + EfiPeiReset2Descriptor->Ppi = EfiPeiReset2Ppi; + + Status = PeiServicesInstallPpi (EfiPeiReset2Descriptor); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "PchInitializeReset() End\n")); + + return Status; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c new file mode 100644 index 0000000000..58f2d86103 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.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 = 0; Index < 30; Index++) { + DEBUG ((DEBUG_INFO, "*")); + } + DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n")); + for (Index = 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 Reset Type Guid. +**/ +VOID +PchResetCallback ( + IN EFI_RESET_TYPE ResetType, + IN EFI_GUID *ResetTypeGuid + ) +{ + EFI_STATUS Status; + UINTN Instance; + PCH_RESET_CALLBACK_PPI *PchResetCallbackPpi; + + Instance = 0; + do { + Status = 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 == 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 processors + 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 equivalent + to the ACPI G2/S5 or G3 states. + + System shutdown should not return, if it returns, it means the system does + not support shut down reset. +**/ +VOID +EFIAPI +ResetShutdown ( + VOID + ) +{ + UINT16 ABase; + UINT32 Data32; + + // + // Loop through callback functions of PchResetCallback PPI + // + PchResetCallback (EfiResetShutdown, NULL); + + ABase = PmcGetAcpiBase (); + /// + /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system 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 = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT)); + + Data32 = (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP + B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5); + + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT), Data32); + + Data32 = 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 platform specific. + + @param[in] DataSize The size of ResetData in bytes. + @param[in] ResetData Optional element used to introduce a platform specific reset. + The exact type of the reset is defined by 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 == NULL) { + DEBUG ((DEBUG_ERROR, "[PeiResetSystemLib] ResetData is not available.\n")); + return; + } + GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID)); + if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) { + PchGlobalReset(); + } else { + return; + } +} + +/** + Calling this function causes the system to enter a power state for capsule 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/PchSpi.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 Interface. + + 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 = 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_COMMAND_MEMORY_SPACE); + PciSegmentWrite32 (PchSpiBase + R_SPI_CFG_BAR0, PCH_SPI_BASE_ADDRESS); + PciSegmentOr8 (PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE); +} + +/** + 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 = PeiServicesLocatePpi ( + &gPchSpiPpiGuid, + 0, + NULL, + (VOID **)&SpiPpi + ); + + if (Status != 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 = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_SPI_INSTANCE)); + if (NULL == PeiSpiInstance) { + return EFI_OUT_OF_RESOURCES; + } + + SpiInstance = &(PeiSpiInstance->SpiInstance); + SpiProtocolConstructor (SpiInstance); + + PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PeiSpiInstance->PpiDescriptor.Guid = &gPchSpiPpiGuid; + PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol); + + /// + /// Install the SPI PPI + /// + DEBUG ((DEBUG_INFO, "SPI PPI Installed\n")); + Status = 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 initialized + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase + +**/ +EFI_STATUS +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + UINT64 SpiBaseAddress; + + SpiBaseAddress = 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) != 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 = 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; +} -- 2.16.2.windows.1