From: "Nate DeSimone" <nathaniel.l.desimone@intel.com>
To: "Kubacki, Michael A" <michael.a.kubacki@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Chaganty, Rangasai V" <rangasai.v.chaganty@intel.com>,
"Chiu, Chasel" <chasel.chiu@intel.com>,
"Gao, Liming" <liming.gao@intel.com>,
"Kinney, Michael D" <michael.d.kinney@intel.com>,
"Sinha, Ankit" <ankit.sinha@intel.com>
Subject: Re: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances
Date: Sat, 17 Aug 2019 00:52:38 +0000 [thread overview]
Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE129AE@ORSMSX114.amr.corp.intel.com> (raw)
In-Reply-To: <20190817001603.30632-20-michael.a.kubacki@intel.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
-----Original Message-----
From: Kubacki, Michael A
Sent: Friday, August 16, 2019 5:16 PM
To: devel@edk2.groups.io
Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Sinha, Ankit <ankit.sinha@intel.com>
Subject: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances
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 <rangasai.v.chaganty@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
---
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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+#
+# 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _GPIO_LIBRARY_H_
+#define _GPIO_LIBRARY_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Private/Library/GpioHelpersLib.h>
+#include <Register/PchRegsGpio.h>
+
+// 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. <BR>
+
+ 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. <BR>
+
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PEI_PCH_POLICY_LIBRARY_H_
+#define _PEI_PCH_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPolicyLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PchRegsSpi.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GpioLibrary.h"
+#include <Register/PchRegsPcr.h>
+
+//
+// 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GpioLibrary.h"
+#include <Register/PchRegsPcr.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GpioLibrary.h"
+#include <Library/PrintLib.h>
+
+/**
+ 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. <BR>
+
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Private/Library/PchDmiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PchEspiLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PchRegsSpi.h>
+#include <Register/PchRegsSmbus.h>
+
+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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TimerLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegsPcr.h>
+#include <Register/PchRegsLpc.h>
+
+#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]=<SlvID>, Bit [17:16] = 00b, Bit[11:0] = <addr_xxx>.
+ // 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]=<SlvID>, Bit [17:16] = 01b, Bit[11:0] = <addr_xxx>.
+ // 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]=<SlvID>, Bit [17:16] = 10b, Bit[11:0] = <addr_xxx>.
+ // 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]=<SlvID>, 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsSpi.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchHsioLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include "PchInfoLibPrivate.h"
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PchRegsPcie.h>
+#include <IndustryStandard/Pci30.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchRegsLpcCnl.h>
+#include "PchInfoLibPrivate.h"
+#include <Private/Library/PmcPrivateLib.h>
+#include <Register/PchRegsLpc.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <PcieRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsPcie.h>
+#include <Register/PchRegsPcr.h>
+
+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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchPcrLib.h>
+#include <Register/PchRegsPcr.h>
+
+#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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPmcLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsP2sb.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <SaAccess.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PcdLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchSerialIoUartLib.h>
+#include <Include/PcieRegs.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsPcr.h>
+#include <Register/PchRegsSerialIo.h>
+
+#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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PcdLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+
+#include <PchLimits.h>
+#include <Register/PchRegsSerialIoCnl.h>
+#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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchSerialIoUartLib.h>
+#include <IndustryStandard/Pci30.h>
+
+#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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PmcLib.h>
+#include <Register/PchRegsPmc.h>
+
+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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <PchReservedResources.h>
+#include <Register/PchRegsPmc.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Register/PchRegs.h>
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/PchInfoLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegsSata.h>
+#include <Library/SataLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegsSata.h>
+#include <Library/SataLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/Wdt.h>
+#include <Library/PchWdtCommonLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/IoLib.h>
+#include <Register/PchRegsPmc.h>
+
+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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+
+/**
+ 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. <BR>
+
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PeiPchPolicyLibrary.h"
+#include <Private/PchHsio.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PeiPchPolicyLibrary.h"
+#include <Library/PchPcieRpLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Register/PchRegsLpcCnl.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PeiPchPolicyLibrary.h"
+#include <Library/PchPcieRpLib.h>
+#include <Library/CpuPlatformLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PeiPchPolicyLibrary.h"
+#include <Library/CpuPlatformLib.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/Reset2.h>
+#include <Ppi/PchReset.h>
+#include <Library/PchResetLib.h>
+#include <Library/ResetSystemLib.h>
+
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchResetLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PmcLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Ppi/PchReset.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PchRegsPmc.h>
+
+/**
+ 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. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Ppi/Spi.h>
+#include <Private/Library/PchSpiCommonLib.h>
+#include <PchReservedResources.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PchRegsSpi.h>
+
+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
next prev parent reply other threads:[~2019-08-17 0:52 UTC|newest]
Thread overview: 121+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-17 0:15 [edk2-platforms][PATCH V1 00/37] Coffee Lake and Whiskey Lake support Kubacki, Michael A
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 01/37] CoffeelakeSiliconPkg: Add package and Include headers Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:08 ` Chiu, Chasel
2019-08-17 1:18 ` Chaganty, Rangasai V
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 02/37] CoffeelakeSiliconPkg/Cpu: Add " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:08 ` Chiu, Chasel
2019-08-17 6:58 ` Chaganty, Rangasai V
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 03/37] CoffeelakeSiliconPkg/Me: " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:08 ` Chiu, Chasel
2019-08-17 7:04 ` Chaganty, Rangasai V
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 04/37] CoffeelakeSiliconPkg/Pch: Add include headers Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:08 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 05/37] CoffeelakeSiliconPkg/Pch: Add ConfigBlock headers Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:09 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 06/37] CoffeelakeSiliconPkg/Pch: Add Library include headers Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:09 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 07/37] CoffeelakeSiliconPkg/Pch: Add PPI and Protocol " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:09 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 08/37] CoffeelakeSiliconPkg/Pch: Add Register " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:09 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 09/37] CoffeelakeSiliconPkg/Pch: Add Private " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:12 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 10/37] CoffeelakeSiliconPkg/Pch: Add Private/Library " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:09 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 11/37] CoffeelakeSiliconPkg/Pch: Add Private/Protocol " Kubacki, Michael A
2019-08-17 0:51 ` Nate DeSimone
2019-08-17 1:10 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 12/37] CoffeelakeSiliconPkg/SampleCode: Add Include headers Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:12 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 13/37] CoffeelakeSiliconPkg/SystemAgent: " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:12 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 14/37] CoffeelakeSiliconPkg: Add package common library instances Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:12 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 15/37] CoffeelakeSiliconPkg/Cpu: Add " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 16/37] CoffeelakeSiliconPkg/Me: " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:12 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 17/37] CoffeelakeSiliconPkg/Pch: Add Base " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 18/37] CoffeelakeSiliconPkg/Pch: Add DXE " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone [this message]
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 20/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 22/37] CoffeelakeSiliconPkg/Pch: Add DXE private " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 24/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 25/37] CoffeelakeSiliconPkg/SystemAgent: Add " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 27/37] CoffeelakeSiliconPkg/Pch: Add PchSmiDispatcher Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 28/37] CoffeelakeSiliconPkg/SystemAgent: Add modules Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 29/37] CoffeelakeSiliconPkg: Add package DSC files Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 30/37] Maintainers.txt: Add CoffeelakeSiliconPkg maintainers Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 31/37] WhiskeylakeOpenBoardPkg: Add package and headers Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-19 18:09 ` Sinha, Ankit
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 32/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add headers Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 33/37] WhiskeylakeOpenBoardPkg: Add library instances Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 34/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: " Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 20:08 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 35/37] WhiskeylakeOpenBoardPkg: Add modules Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 7:50 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 36/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add DSC and build files Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 20:11 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 37/37] Add WhiskeylakeOpenBoardPkg to global build config and documentation Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 20:00 ` Chaganty, Rangasai V
2019-08-19 18:14 ` [edk2-platforms][PATCH V1 00/37] Coffee Lake and Whiskey Lake support Sinha, Ankit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=02A34F284D1DA44BB705E61F7180EF0AAEE129AE@ORSMSX114.amr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox