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 23/37] CoffeelakeSiliconPkg/Pch: Add PEI private library instances
Date: Sat, 17 Aug 2019 00:53:48 +0000 [thread overview]
Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE12AA1@ORSMSX114.amr.corp.intel.com> (raw)
In-Reply-To: <20190817001603.30632-24-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 23/37] CoffeelakeSiliconPkg/Pch: Add PEI private library instances
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082
Adds PCH PEI private library class instances. These library instances
may be compatible with other boot phases as indicated by the library type.
* PeiDxeSmmGpioPrivateLibCnl
* PeiDxeSmmPchDmiLib
* PeiDxeSmmPchDmiWithS3Lib
* PeiDxeSmmPchInitCommonLib
* PeiDxeSmmPchPciExpressHelpersLib
* PeiDxeSmmPchPsfPrivateLibCnl
* PeiDxeSmmPmcPrivateLibCnl
* PeiDxeSmmPmcPrivateLibWithS3
* PeiGpioHelpersLib
* PeiGpioNameBufferLib
* PeiPmcPrivateLibCnl
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/Private/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibCnl.inf | 45 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf | 40 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf | 40 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf | 34 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf | 42 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLibCnl.inf | 41 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCnl.inf | 48 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf | 39 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLibCnl.inf | 40 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.inf | 42 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf | 35 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h | 477 ++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.h | 70 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.h | 113 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h | 42 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibInternal.h | 490 ++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibInternal.h | 47 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNamesCnl.c | 166 ++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c | 1304 +++++++++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibCnl.c | 2275 ++++++++++++++++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c | 752 ++++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLibCnl.c | 225 ++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.c | 67 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.c | 113 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiLib.c | 569 +++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c | 79 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PchInitCommon.c | 221 ++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c | 2407 ++++++++++++++++++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c | 542 +++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibCnl.c | 338 +++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLib.c | 92 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c | 1033 +++++++++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibClient.c | 73 +
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibCnl.c | 360 +++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c | 194 ++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.c | 356 +++
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/GpioNameBufferPei.c | 68 +
37 files changed, 12919 insertions(+)
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibCnl.inf
new file mode 100644
index 0000000000..318b54a99c
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibCnl.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGpioPrivateLibCnl
+FILE_GUID = E078A734-BEA0-47CF-A476-3742316D01FC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PmcLib
+ PchInfoLib
+ GpioLib
+ GpioNameBufferLib
+ SataLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioNativePrivateLib.c
+ GpioPrivateLibCnl.c
+ GpioNativePrivateLibCnl.c
+ GpioNamesCnl.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf
new file mode 100644
index 0000000000..b36fc15901
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the PeiDxeSmmPchDmiLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchDmiLib
+FILE_GUID = 067DC1C4-2668-4F06-9921-307514B66B34
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchDmiLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchInfoLib
+ PchPcrLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchDmiLib.c
+ PchDmi14.c
+ PchDmi15.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf
new file mode 100644
index 0000000000..1eda7cdba8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the PeiDxeSmmPchDmiWithS3Lib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchDmiWithS3Lib
+FILE_GUID = 32CCA047-6AF0-46FF-83DA-32BA62484075
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchDmiWithS3Lib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchPcrLib
+ PchInfoLib
+ S3BootScriptLib
+ PchDmiLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchDmiWithS3Lib.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
new file mode 100644
index 0000000000..d81c428a1c
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
@@ -0,0 +1,34 @@
+## @file
+# Component description file for the PchInitCommonLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiDxeSmmPchInitCommonLib
+ FILE_GUID = E9C4FE04-8A79-43FA-B3E0-603359C31B43
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchInitCommonLib
+
+[Sources]
+ PchInitCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CoffeelakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PciSegmentLib
+ PchCycleDecodingLib
+ PchPcieRpLib
+ PchSbiAccessLib
+ PchInfoLib
+ SataLib
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..16b1c019b8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PeiDxeSmmPchPciExpressHelpersLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciExpressHelpersLib
+FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciExpressHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PchPcieRpLib
+PchPcrLib
+PchInfoLib
+GpioLib
+TimerLib
+PchInitCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPciExpressHelpersLibrary.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLibCnl.inf
new file mode 100644
index 0000000000..0ed9f30dcc
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLibCnl.inf
@@ -0,0 +1,41 @@
+## @file
+# PEI/DXE/SMM PCH PSF Private Lib for Cannon Lake PCH
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPsfPrivateLibCnl
+FILE_GUID = 7A6C18CA-0353-433E-885D-DD68BFAD38BE
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PciSegmentLib
+ PchInfoLib
+ PchPcrLib
+ SataLib
+ SaPlatformLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchPsfPrivateLib.c
+ PchPsfPrivateLibCnl.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCnl.inf
new file mode 100644
index 0000000000..adb154dd14
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCnl.inf
@@ -0,0 +1,48 @@
+## @file
+# PEI/DXE/SMM PCH PMC Private Lib 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 = PeiDxeSmmPmcPrivateLibCnl
+FILE_GUID = A1CB52AD-4FAB-4214-94A0-323E3BE4E934
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+TimerLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+PmcLib
+PchPsfPrivateLib
+PchDmiLib
+SataLib
+BaseMemoryLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+
+
+[Sources]
+PmcPrivateLib.c
+PmcPrivateLibClient.c
+PmcPrivateLibCnl.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf
new file mode 100644
index 0000000000..cd1380dc43
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf
@@ -0,0 +1,39 @@
+## @file
+# PEI/DXE/SMM PCH private PMC Lib.
+# This part of PMC lib includes S3BootScript support
+#
+# 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 = PeiDxeSmmPmcPrivateLibWithS3
+FILE_GUID = 5890CA5A-1955-4A02-A09C-01E4150606CC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcPrivateLibWithS3
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PmcLib
+PcdLib
+S3BootScriptLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PmcPrivateLibWithS3.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLibCnl.inf
new file mode 100644
index 0000000000..ab3645c61d
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLibCnl.inf
@@ -0,0 +1,40 @@
+## @file
+# PEI PCH PMC Private Lib for Cannon Lake PCH.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiPmcPrivateLibCnl
+FILE_GUID = 1DD4EA23-12F2-4F05-93AF-535476106D8C
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PeiPmcPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+IoLib
+DebugLib
+PeiServicesLib
+PciSegmentLib
+ConfigBlockLib
+PchInfoLib
+PchPcrLib
+PmcLib
+PmcPrivateLib
+PchEspiLib
+GpioPrivateLib
+PeiItssLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PeiPmcPrivateLib.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
new file mode 100644
index 0000000000..b6f786d80b
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PeiGpioHelpersLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiGpioHelpersLib
+FILE_GUID = 1838E1E7-3CC4-4A74-90D9-B421EF2A579F
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = GpioHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiGpioHelpersLib.c
+
+
+[Guids]
+gGpioLibUnlockHobGuid
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf
new file mode 100644
index 0000000000..3619a2e6a7
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PeiGpioMemLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiGpioNameBufferLib
+FILE_GUID = 16EC5CA8-8195-4847-B6CB-662CDAB863F2
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = GpioNameBufferLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[LibraryClasses]
+HobLib
+BaseLib
+IoLib
+DebugLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Sources]
+GpioNameBufferPei.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h
new file mode 100644
index 0000000000..e081027c40
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h
@@ -0,0 +1,477 @@
+/** @file
+ Header file for GPIO Private Lib Internal functions.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
+#define _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
+
+#include <Private/Library/GpioPrivateLib.h>
+
+#define GPIO_PAD_NONE 0
+
+/**
+ This function provides SerialIo I2C controller pins
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoI2cPins (
+ IN UINT32 SerialIoI2cControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides SerialIo UART controller pins
+
+ @param[in] SerialIoUartControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+ @param[in] PinMuxing UART controller pin muxing
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoUartPins (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl,
+ IN UINT32 PinMuxing,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides SerialIo SPI controller pins
+
+ @param[in] SerialIoSpiControllerNumber SPI controller
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoSpiPins (
+ IN UINT32 SerialIoSpiControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides ISH GP pin data
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @param[out] NativePin ISH GP pin
+**/
+VOID
+GpioGetIshGpPin (
+ IN UINT32 IshGpPinNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ );
+
+/**
+ This function provides ISH UART controller pins
+
+ @param[in] IshUartControllerNumber ISH UART controller
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetIshUartPins (
+ IN UINT32 IshUartControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides ISH I2C controller pins
+
+ @param[in] IshI2cControllerNumber ISH I2C controller
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetIshI2cPins (
+ IN UINT32 IshI2cControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides ISH SPI controller pins
+
+ @param[in] IshSpiControllerNumber SPI controller
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetIshSpiPins (
+ IN UINT32 IshSpiControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides SCS SD CARD controller pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetScsSdCardPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides SCS SD CARD detect pin
+
+ @retval GpioPin SD CARD Detect pin
+**/
+GPIO_PAD
+GpioGetScsSdCardDetectPin (
+ VOID
+ );
+
+/**
+ This function provides SCS eMMC controller pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetScsEmmcPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides HD Audio Link pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetHdAudioLinkPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides DMIC interface pins
+
+ @param[in] DmicNumber DMIC interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaDmicPins (
+ IN UINT32 DmicNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides SSP/I2S interface pins
+
+ @param[in] SspInterfaceNumber SSP/I2S interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaSspPins (
+ IN UINT32 SspInterfaceNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides SNDW interface pins
+
+ @param[in] SndwInterfaceNumber SNDWx interface number
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaSndwPins (
+ IN UINT32 SndwInterfaceNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides SMBUS interface pins
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetSmbusPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides SATA DevSlp pin data
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+ @param[out] NativePin SATA DevSlp pin
+**/
+VOID
+GpioGetSataDevSlpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ );
+
+/**
+ This function provides PCIe CLKREQ pin data
+
+ @param[in] ClkreqIndex CLKREQ# number
+ @param[out] NativePin Native pin data
+**/
+VOID
+GpioGetPcieClkReqPin (
+ IN UINT32 ClkreqIndex,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ );
+
+/**
+ This function provides eDP pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetEdpPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides DDPx interface pins
+
+ @param[in] DdpInterface DDPx interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetDdpPins (
+ IN GPIO_DDP DdpInterface,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi BT UART pins
+
+ @param[in] ConnectionType CNVi BT UART connection type
+ @param[out] VCnviBtUartPad Table with vCNV_BT_UARTx pads
+ @param[out] VCnviBtUartPadMode vCNV_BT_UARTx pad mode
+ @param[out] VUartForCnviBtPad Table with vUART0 pads
+ @param[out] VUartForCnviBtPadMode vUART0 pad mode
+**/
+VOID
+GpioGetCnviBtUartPins (
+ IN VGPIO_CNVI_BT_UART_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviBtUartPad,
+ OUT GPIO_PAD_MODE *VCnviBtUartPadMode,
+ OUT GPIO_PAD **VUartForCnviBtPad,
+ OUT GPIO_PAD_MODE *VUartForCnviBtPadMode
+ );
+
+/**
+ This function provides CNVi BT UART external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviBtUartExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi BT I2S pins
+
+ @param[in] ConnectionType CNVi BT I2S connection type
+ @param[out] VCnviBtI2sPad Table with vCNV_BT_I2Sx pads
+ @param[out] VCnviBtI2sPadMode vCNV_BT_I2Sx pad mode
+ @param[out] VSspForCnviBtPad Table with vSSP2 pads
+ @param[out] VSspForCnviBtPadMode vSSP2 pad mode
+**/
+VOID
+GpioGetCnviBtI2sPins (
+ IN VGPIO_CNVI_BT_I2S_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviBtI2sPad,
+ OUT GPIO_PAD_MODE *VCnviBtI2sPadMode,
+ OUT GPIO_PAD **VSspForCnviBtPad,
+ OUT GPIO_PAD_MODE *VSspForCnviBtPadMode
+ );
+
+/**
+ This function provides CNVi BT I2S external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviBtI2sExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi MFUART1 pins
+
+ @param[in] ConnectionType CNVi MFUART1 connection type
+ @param[out] VCnviBtI2sPad Table with vCNV_MFUART1x pads
+ @param[out] VCnviBtI2sPadMode vCNV_MFUART1x pad mode
+ @param[out] VSspForCnviBtPad Table with vISH_UART0 pads
+ @param[out] VSspForCnviBtPadMode vISH_UART0 pad mode
+**/
+VOID
+GpioGetCnviMfUart1Pins (
+ IN VGPIO_CNVI_MF_UART1_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviMfUart1Pad,
+ OUT GPIO_PAD_MODE *VCnviMfUart1PadMode,
+ OUT GPIO_PAD **VUartForCnviMfUart1Pad,
+ OUT GPIO_PAD_MODE *VUartForCnviMfUart1PadMode
+ );
+
+/**
+ This function provides CNVi MFUART1 external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviMfUart1ExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi Bluetooth Enable pad
+
+ @retval GpioPad CNVi Bluetooth Enable pad
+**/
+GPIO_PAD
+GpioGetCnviBtEnablePin (
+ VOID
+ );
+
+/**
+ This function provides CNVi BRI RGI GPIO pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnvBriRgiPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi MFUART2 external pins
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnvMfUart2ExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ );
+
+/**
+ This function provides CNVi BT interface select pin
+
+ @retval GpioPad GPIO pad for CNVi BT interface select
+**/
+GPIO_PAD
+GpioGetCnviBtIfSelectPin (
+ VOID
+ );
+
+/**
+ This function provides CNVi BT Charging pin
+
+ @retval GpioPad GPIO pad for CNVi BT Charging select
+**/
+GPIO_PAD
+GpioGetCnviBtChargingPin (
+ VOID
+ );
+
+/**
+ This function provides CNVi A4WP pin
+
+ @param[out] GpioNativePad GPIO native pad for CNVi A4WP
+**/
+VOID
+GpioGetCnviA4WpPin (
+ OUT GPIO_PAD_NATIVE_FUNCTION *GpioNativePad
+ );
+
+/**
+ This function provides CNVi BT host wake int pin
+
+ @retval GpioPad GPIO pad BT host wake int
+**/
+GPIO_PAD
+GpioGetCnviBtHostWakeIntPin (
+ VOID
+ );
+
+/**
+ This function provides IMGCLKOUT pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetImgClkOutPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ );
+
+/**
+ This function provides PWRBTN pin
+
+ @retval GpioPad PWRTBTN pin
+**/
+GPIO_PAD
+GpioGetPwrBtnPin (
+ VOID
+ );
+
+/**
+ This procedure enables debounce feature on a selected pad configured in input mode
+ Debounce time can be specified in microseconds. GPIO HW supports only certain values
+ according to below formula:
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period).
+ RTC clock with f = 32 KHz is used for glitch filter.
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us).
+ Supported DebounceTime values are following:
+ DebounceTime = 0 -> Debounce feature disabled
+ DebounceTime > 0 && < 250us -> Not supported
+ DebounceTime = 250us - 1024000us -> Supported range (DebounceTime = 250us * 2^n)
+ For values not supported by GPIO HW, function will round down
+ to closest supported
+
+ @param[in] GpioPad GPIO pad
+ @param[in, out] DebounceTime Debounce Time in microseconds
+ If Debounce Time = 0, Debouncer feature will be disabled
+ Function will set DebounceTime argument to rounded supported value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad or unsupported DebounceDuration value
+ @retval EFI_UNSUPPORTED GpioPad is not owned by host
+**/
+EFI_STATUS
+GpioSetDebounceTimer (
+ IN GPIO_PAD GpioPad,
+ IN OUT UINT32 *DebounceTime
+ );
+
+/**
+ This function provides LPC pin
+
+ @retval GpioPad LPC pin
+**/
+GPIO_PAD
+GpioGetLpcPin (
+ VOID
+ );
+
+#endif // _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.h
new file mode 100644
index 0000000000..1d50c04b0f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.h
@@ -0,0 +1,70 @@
+/** @file
+ Internal header file for PCH DMI library for SIP14
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __PCH_DMI_14_H__
+#define __PCH_DMI_14_H__
+
+#include <Private/Library/PchDmiLib.h>
+#include <Private/Library/PeiPchDmiLib.h>
+
+/**
+ This function checks if DMI SIP14 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi14Locked (
+ VOID
+ );
+
+/**
+ Enable PCIe Relaxed Order for DMI SIP14
+**/
+VOID
+PchDmi14EnablePcieRelaxedOrder (
+ VOID
+ );
+
+/**
+ This function will switch SAI value to be driven to IOSF Primary Fabric
+ for cycles with Core BDF from HOSTIA_BOOT_SAI to HOSTIA_POSTBOOT_SAI.
+ To be used when PCH is paired with CFL CPU.
+**/
+VOID
+PchDmi14EnablePostBootSai (
+ VOID
+ );
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi14SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ );
+
+/**
+ Get PCH DMI SIP14 Virtual Channel Control and Status registers
+
+ @param[in] Vc The virtual channel number for programing
+ @param[out] DmiVcCtlAddress DMI Virtual Channel Control register address
+ @param[out] DmiVcStsAddress DMI Virtual Channel Status register address
+**/
+VOID
+PchDmi14VcRegs (
+ IN PCH_DMI_VC_TYPE Vc,
+ OUT UINT16 *DmiVcCtlAddress,
+ OUT UINT16 *DmiVcStsAddress
+ );
+
+
+#endif
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.h
new file mode 100644
index 0000000000..744a96fe14
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.h
@@ -0,0 +1,113 @@
+/** @file
+ Internal header file for PCH DMI library for SIP15
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __PCH_DMI_15_H__
+#define __PCH_DMI_15_H__
+
+#include <Private/Library/PchDmiLib.h>
+#include <Private/Library/PeiPchDmiLib.h>
+
+/**
+ This function checks if DMI SIP15 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi15Locked (
+ VOID
+ );
+
+/**
+ Set DMI thermal throttling to recommended configuration.
+ It's intended only for P-DMI SIP15.
+**/
+VOID
+PchDmi15SetRecommendedThermalThrottling (
+ VOID
+ );
+
+/**
+ Set DMI thermal throttling to custom configuration.
+ This function will configure Thermal Sensor 0/1/2/3 TargetWidth and set
+ DMI Thermal Sensor Autonomous Width Enable.
+ It's intended only for P-DMI SIP15.
+
+ @param[in] DmiThermalThrottling DMI Thermal Throttling structure.
+**/
+VOID
+PchDmi15SetCustomThermalThrottling (
+ IN DMI_THERMAL_THROTTLING DmiThermalThrottling
+ );
+
+/**
+ Enable PCIe Relaxed Order for DMI SIP15
+**/
+VOID
+PchDmi15EnablePcieRelaxedOrder (
+ VOID
+ );
+
+/**
+ This function will switch SAI value to be driven to IOSF Primary Fabric
+ for cycles with Core BDF from HOSTIA_BOOT_SAI to HOSTIA_POSTBOOT_SAI.
+ To be used when PCH is paired with CFL CPU.
+**/
+VOID
+PchDmi15EnablePostBootSai (
+ VOID
+ );
+
+/**
+ This function will do necessary configuration after platform
+ should have switched to POSTBOOT_SAI. It needs to be called even if
+ POSTBOOT_SAI was not set.
+**/
+VOID
+PchDmi15ConfigAfterPostBootSai (
+ VOID
+ );
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi15SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ );
+
+/**
+ Get PCH DMI SIP15 Virtual Channel Control and Status registers
+
+ @param[in] Vc The virtual channel number for programing
+ @param[out] DmiVcCtlAddress DMI Virtual Channel Control register address
+ @param[out] DmiVcStsAddress DMI Virtual Channel Status register address
+**/
+VOID
+PchDmi15VcRegs (
+ IN PCH_DMI_VC_TYPE Vc,
+ OUT UINT16 *DmiVcCtlAddress,
+ OUT UINT16 *DmiVcStsAddress
+ );
+
+/**
+ The function sets the Target Link Speed to GEN 3 in P-DMI SIP15.
+
+ @param[in] TargetLinkSpeed Target Link Speed
+ 2: GEN2
+ 3: GEN3
+**/
+VOID
+PchDmi15SetTargetLinkSpeed (
+ IN UINT8 TargetLinkSpeed
+ );
+
+#endif
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..b14f24b18f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
@@ -0,0 +1,42 @@
+/** @file
+ Header file for PCH Pci Express helps library implementation.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/TimerLib.h>
+#include <Private/Library/PchPciExpressHelpersLib.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <Private/Library/PchInitCommonLib.h>
+#include <PcieRegs.h>
+#include <Register/PchRegsPcie.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+#define CONFIG_WRITE_LOOP_COUNT 100000
+
+//
+// LTR related macros
+//
+#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK)
+#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10)
+#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x))))
+
+#endif
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibInternal.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibInternal.h
new file mode 100644
index 0000000000..f633df0411
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibInternal.h
@@ -0,0 +1,490 @@
+/** @file
+ This file contains internal header for PSF lib usage
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_PSF_PRIVATE_LIB_INTERNAL_H_
+#define _PCH_PSF_PRIVATE_LIB_INTERNAL_H_
+
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <Register/PchRegsPcr.h>
+
+#define PSF_PORT_NULL ((PSF_PORT){0,0})
+#define PSF_IS_PORT_NULL(PsfPort) ((PsfPort.PsfPid == 0) && (PsfPort.RegBase == 0))
+
+/**
+ Disable bridge (e.g. PCIe Root Port) at PSF level
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableBridge (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable bridge (e.g. PCIe Root Port) at PSF level in RS3
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfRs3DisableBridge (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Check if bridge (e.g. PCIe Root Port) is enabled at PSF level
+
+ @param[in] PsfPort PSF PORT data structure
+
+ @retval TRUE Bridge behind PSF Port is enabled
+ FALSE Bridge behind PSF Port is disabled
+**/
+BOOLEAN
+PsfIsBridgeEnabled (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Enable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable device Memory Space at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDeviceMemSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Enable device Memory Space at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDeviceMemSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Set device BARx address at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1, ...)
+ @param[in] BarValue 32bit BAR value
+**/
+VOID
+PsfSetDeviceBarValue (
+ IN PSF_PORT PsfPort,
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ );
+
+/**
+ Return PSF_PORT for TraceHub device
+
+ @retval PsfPort PSF PORT structure for TraceHub device
+**/
+PSF_PORT
+PsfTraceHubPort (
+ VOID
+ );
+
+/**
+ This procedure will return PSF_PORT for TraceHub ACPI device
+
+ @retval PsfPort PSF PORT structure for TraceHub ACPI device
+**/
+PSF_PORT
+PsfTraceHubAcpiDevPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for HECI device
+
+ @param[in] HeciDevice HECIx Device (HECI1-4)
+
+ @retval PsfPort PSF PORT structure for HECI device
+**/
+PSF_PORT
+PsfHeciPort (
+ IN UINT8 HeciDevice
+ );
+
+/**
+ This procedure will return PSF_PORT for SOL device
+
+ @retval PsfPort PSF PORT structure for SOL device
+**/
+PSF_PORT
+PsfSolPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for ISH device
+
+ @retval PsfPort PSF PORT structure for ISH device
+**/
+PSF_PORT
+PsfIshPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for CNVi device
+
+ @retval PsfPort PSF PORT structure for CNVi device
+**/
+PSF_PORT
+PsfCnviPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for PMC device
+
+ @retval PsfPort PSF PORT structure for PMC device
+**/
+PSF_PORT
+PsfPmcPort (
+ VOID
+ );
+
+/**
+ Return second level PSF_PORT to which PCIE Root Port device is connected (directly)
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+**/
+PSF_PORT
+PsfPcieSecondLevelPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return PSF_PORT at root PSF level to which PCIe Root Port device is connected
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+
+**/
+PSF_PORT
+PsfRootPciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return RS3 PSF_PORT at root PSF level to which PCIe Root Port device is connected
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+**/
+PSF_PORT
+PsfRootRs3PciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Check if PCIe Root Port is enabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval TRUE PCIe Root Port is enabled
+ FALSE PCIe Root Port is disabled
+**/
+BOOLEAN
+PsfIsPcieRootPortEnabled (
+ IN UINT32 RpIndex
+ );
+
+//
+// Type of enpoint connected to PSF port.
+// PsfNullPort is used for ports which do not exist
+//
+typedef enum {
+ PsfNullPort,
+ PsfToPsfPort,
+ PsfPcieCtrlPort
+} PSF_TOPO_PORT_TYPE;
+
+//
+// Structure for storing information on location in PSF topology
+// Every PSF node is identified by PsfID and PsfPortId
+//
+typedef struct {
+ UINT8 PsfId;
+ UINT8 PortId;
+} PSF_TOPO_PORT;
+
+#define PSF_TOPO_PORT_NULL ((PSF_TOPO_PORT){0, 0})
+#define PSF_IS_TOPO_PORT_NULL(PsfTopoPort) (((PsfTopoPort).PsfId == 0) && ((PsfTopoPort).PortId == 0))
+
+//
+// This is optional field containing PSF port specific data
+//
+typedef union {
+ UINT32 PcieCtrlIndex;
+} PSF_TOPO_PORT_DATA;
+
+//
+// Structure representing PSF port in PSF topology
+// If port is of PsfToPsfPort type Child will point to the first
+// port of sub PSF segment.
+//
+typedef struct PSF_TOPOLOGY {
+ PSF_TOPO_PORT PsfPort;
+ PSF_TOPO_PORT_TYPE PortType;
+ CONST struct PSF_TOPOLOGY *Child;
+ PSF_TOPO_PORT_DATA PortData;
+} PSF_TOPOLOGY;
+
+//
+// Tag for identifying last element of PSF_TOPOLOGY type array
+//
+#define PSF_TOPOLOGY_END {{0, 0}, PsfNullPort, NULL}
+
+/**
+ Get PSF Pcie Tree topology
+
+ @param[in] PsfTopology PSF Port from PSF PCIe tree topology
+
+ @retval PsfTopology PSF PCIe tree topology
+**/
+CONST PSF_TOPOLOGY*
+PsfGetRootPciePsfTopology (
+ VOID
+ );
+
+//
+// Structure for storing data on PCIe controller to PSF assignment and GrantCount register offsets
+//
+typedef struct {
+ PCH_SBI_PID PsfPid;
+ UINT16 DevGntCnt0Base;
+ UINT16 TargetGntCntPg1Tgt0Base;
+} PSF_GRANT_COUNT_REG;
+
+/**
+ Grant count regs data for PSF that is directly connected to PCIe Root Ports
+
+ @param[in] Controller PCIe Root Port Controller index (0 based)
+ @param[out] GrantCountReg Structure with PSF Grant Count register data
+**/
+VOID
+PsfPcieGrantCountBaseReg (
+ IN UINT8 Controller,
+ OUT PSF_GRANT_COUNT_REG *GrantCountReg
+ );
+
+/**
+ Get Grant Count number (Device Grant Count and Target Grant Count)
+ for PSF that is directly connected to PCIe Root Ports
+
+ @param[in] Controller PCIe Root Port Controller index
+ @param[in] Channel PCIe Root Port Channel index
+ @param[out] DgcrNo Device Grant Count number
+ @param[out] PgTgtNo Target Grant Count number
+**/
+VOID
+PsfPcieGrantCountNumber (
+ IN UINT8 Controller,
+ IN UINT8 Channel,
+ OUT UINT8 *DgcrNo,
+ OUT UINT8 *PgTgtNo
+ );
+
+/**
+ Grant count regs data for a given PSF-to-PSF port.
+
+ @param[in] PsfTopoPort PSF-to-PSF port
+
+ @param[out] GrantCountReg Structure with PSF Grant Count register data
+**/
+VOID
+PsfSegmentGrantCountBaseReg (
+ IN PSF_TOPO_PORT PsfTopoPort,
+ OUT PSF_GRANT_COUNT_REG *GrantCountReg
+ );
+
+/**
+ Grant Count number (Device Grant Count and Target Grant Count) for a given PSF-to-PSF port.
+
+ @param[in] PsfTopoPort PSF-to-PSF port
+ @param[out] DgcrNo Device Grant Count number
+ @param[out] PgTgtNo Target Grant Count number
+**/
+VOID
+PsfSegmentGrantCountNumber (
+ IN PSF_TOPO_PORT PsfTopoPort,
+ OUT UINT8 *DgcrNo,
+ OUT UINT8 *PgTgtNo
+ );
+
+//
+// Do not override PSF Grant Count value and leave HW default setting
+//
+#define DEFAULT_PCIE_GRANT_COUNT 0xFF
+
+typedef struct {
+ UINT32 Id;
+ PCH_SBI_PID SbPid;
+} PSF_SEGMENT;
+
+/**
+ Get list of supported PSF segments.
+
+ @param[out] PsfTable Array of supported PSF segments
+ @param[out] PsfTableLength Length of PsfTable
+**/
+VOID
+PsfSegments (
+ OUT PSF_SEGMENT **PsfTable,
+ OUT UINT32 *PsfTableLength
+ );
+
+/**
+ Get PSF SideBand Port ID from PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @retval PSF SideBand Port ID
+**/
+PCH_SBI_PID
+PsfSbPortId (
+ UINT32 PsfId
+ );
+
+/**
+ Get EOI register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] EoiTargetBase EOI Target register
+ @param[out] EoiControlBase EOI Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfEoiRegData (
+ UINT32 PsfId,
+ UINT16 *EoiTargetBase,
+ UINT16 *EoiControlBase
+ );
+
+/**
+ Get MCTP register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] MctpTargetBase MCTP Target register
+ @param[out] MctpControlBase MCTP Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfMctpRegData (
+ UINT32 PsfId,
+ UINT16 *MctpTargetBase,
+ UINT16 *MctpControlBase
+ );
+
+/**
+ P2SB PSF port Destination ID (psf_id:port_group_id:port_id:channel_id)
+
+ @retval P2SB Destination ID
+**/
+PSF_PORT_DEST_ID
+PsfP2sbDestinationId (
+ VOID
+ );
+
+/**
+ DMI PSF port Destination ID (psf_id:port_group_id:port_id:channel_id)
+
+ @retval DMI Destination ID
+**/
+PSF_PORT_DEST_ID
+PsfDmiDestinationId (
+ VOID
+ );
+
+/**
+ Check if MCTP is supported
+
+ @retval TRUE MCTP is supported
+ FALSE MCTP is not supported
+**/
+BOOLEAN
+PsfIsMctpSupported (
+ VOID
+ );
+
+/**
+ Return the PSF (Root level) Function Config PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfRootPcieFunctionConfigPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return the PSF (Root level) RS3 Function Config PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfRootRs3PcieFunctionConfigPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return the PSF Function Config Second Level PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfPcieFunctionConfigSecondLevelPort (
+ IN UINT32 RpIndex
+ );
+
+#endif
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibInternal.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibInternal.h
new file mode 100644
index 0000000000..c08d1cf10d
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibInternal.h
@@ -0,0 +1,47 @@
+/** @file
+ Internal header file for PMC Private library
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PMC_PRIVATE_LIB_INTERNAL_H_
+#define _PMC_PRIVATE_LIB_INTERNAL_H_
+
+/**
+ Check if MODPHY SUS PG is supported
+
+ @retval Status of MODPHY SUS PG support
+**/
+BOOLEAN
+PmcIsModPhySusPgSupported (
+ VOID
+ );
+
+/**
+ This function is part of PMC init and configures which clock wake signals should
+ set the SLOW_RING, SA, FAST_RING_CF and SLOW_RING_CF indication sent up to the CPU/PCH
+**/
+VOID
+PmcInitClockWakeEnable (
+ VOID
+ );
+
+/**
+ This function configures PWRMBASE + 0x1E00 register
+**/
+VOID
+PmcConfigureRegPwrm1E00 (
+ VOID
+ );
+
+/**
+ This function configures Misc PM_SYNC events settings
+**/
+VOID
+PmcConfigurePmSyncEventsSettings (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNamesCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNamesCnl.c
new file mode 100644
index 0000000000..5a4876bfeb
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNamesCnl.c
@@ -0,0 +1,166 @@
+/** @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 <Base.h>
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <GpioPinsCnlLp.h>
+#include <GpioPinsCnlH.h>
+
+STATIC CONST CHAR8* mGpioGppaNames[] = {
+ "ESPI_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioGppbNames[] = {
+ "GSPI0_CLK_LOOPBK",
+ "GSPI1_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioGpdNames[] = {
+ "SLP_LANB",
+ "SLP_SUSB",
+ "SLP_WAKEB",
+ "SLP_DRAM_RESETB"
+};
+
+STATIC CONST CHAR8* mGpioGppiNames[] = {
+ "SYS_PWROK",
+ "SYS_RESETB",
+ "MLK_RSTB"
+};
+
+STATIC CONST CHAR8* mGpioSpiNames[] = {
+ "SPI0_IO_2",
+ "SPI0_IO_3",
+ "SPI0_MOSI_IO_0",
+ "SPI0_MOSI_IO_1",
+ "SPI0_TPM_CSB",
+ "SPI0_FLASH_0_CSB",
+ "SPI0_FLASH_1_CSB",
+ "SPI0_CLK",
+ "SPI0_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioAzaNames[] = {
+ "HDA_BCLK",
+ "HDA_RSTB",
+ "HDA_SYNC",
+ "HDA_SDO",
+ "HDA_SDI_0",
+ "HDA_SDI_1",
+ "SSP1_SFRM",
+ "SSP1_TXD"
+};
+
+STATIC CONST CHAR8* mGpioJtagNames[] = {
+ "JTAG_TDO",
+ "JTAGX",
+ "PRDYB",
+ "PREQB",
+ "CPU_TRSTB",
+ "JTAG_TDI",
+ "JTAG_TMS",
+ "JTAG_TCK",
+ "ITP_PMODE"
+};
+
+STATIC CONST CHAR8* mGpioHvmosNames[] = {
+ "HVMOS_L_BKLTEN",
+ "HVMOS_L_BKLCTL",
+ "HVMOS_L_VDDEN",
+ "HVMOS_SYS_PWROK",
+ "HVMOS_SYS_RESETB",
+ "HVMOS_MLK_RSTB"
+};
+
+STATIC CONST CHAR8* mGpioCpuNames[] = {
+ "HDACPU_SDI",
+ "HDACPU_SDO",
+ "HDACPU_SCLK",
+ "PM_SYNC",
+ "PECI",
+ "CPUPWRGD",
+ "THRMTRIPB",
+ "PLTRST_CPUB",
+ "PM_DOWN",
+ "TRIGGER_IN",
+ "TRIGGER_OUT"
+};
+
+STATIC CONST GPIO_GROUP_NAME_INFO mPchLpGroupDescriptors[] = {
+ GPIO_GROUP_NAME("GPP_A", GPIO_CNL_LP_ESPI_CLK_LOOPBK, mGpioGppaNames),
+ GPIO_GROUP_NAME("GPP_B", GPIO_CNL_LP_GSPI0_CLK_LOOPBK, mGpioGppbNames),
+ GPIO_GROUP_NAME_BASIC("GPP_C"),
+ GPIO_GROUP_NAME_BASIC("GPP_D"),
+ GPIO_GROUP_NAME_BASIC("GPP_E"),
+ GPIO_GROUP_NAME_BASIC("GPP_F"),
+ GPIO_GROUP_NAME_BASIC("GPP_G"),
+ GPIO_GROUP_NAME_BASIC("GPP_H"),
+ GPIO_GROUP_NAME("GPD", GPIO_CNL_LP_SLP_LANB, mGpioGpdNames),
+ GPIO_GROUP_NAME_BASIC("VGPIO"),
+ GPIO_GROUP_NAME("SPI", GPIO_CNL_LP_SPI0_IO_2, mGpioSpiNames),
+ GPIO_GROUP_NAME("AZA", GPIO_CNL_LP_HDA_BCLK, mGpioAzaNames),
+ GPIO_GROUP_NAME("CPU", GPIO_CNL_LP_HDACPU_SDI, mGpioCpuNames),
+ GPIO_GROUP_NAME("JTAG", GPIO_CNL_LP_JTAG_TDO, mGpioJtagNames),
+ GPIO_GROUP_NAME("HVMOS", GPIO_CNL_LP_HVMOS_L_BKLTEN, mGpioHvmosNames)
+};
+
+STATIC CONST GPIO_GROUP_NAME_INFO mPchHGroupDescriptors[] = {
+ GPIO_GROUP_NAME("GPP_A", GPIO_CNL_H_ESPI_CLK_LOOPBK, mGpioGppaNames),
+ GPIO_GROUP_NAME("GPP_B", GPIO_CNL_H_GSPI0_CLK_LOOPBK, mGpioGppbNames),
+ GPIO_GROUP_NAME_BASIC("GPP_C"),
+ GPIO_GROUP_NAME_BASIC("GPP_D"),
+ GPIO_GROUP_NAME_BASIC("GPP_E"),
+ GPIO_GROUP_NAME_BASIC("GPP_F"),
+ GPIO_GROUP_NAME_BASIC("GPP_G"),
+ GPIO_GROUP_NAME_BASIC("GPP_H"),
+ GPIO_GROUP_NAME("GPP_I", GPIO_CNL_H_SYS_PWROK, mGpioGppiNames),
+ GPIO_GROUP_NAME_BASIC("GPP_J"),
+ GPIO_GROUP_NAME_BASIC("GPP_K"),
+ GPIO_GROUP_NAME("GPD", GPIO_CNL_H_SLP_LANB, mGpioGpdNames),
+ GPIO_GROUP_NAME_BASIC("VGPIO"),
+ GPIO_GROUP_NAME("SPI", GPIO_CNL_H_SPI0_IO_2, mGpioSpiNames),
+ GPIO_GROUP_NAME("AZA", GPIO_CNL_H_HDA_BCLK, mGpioAzaNames),
+ GPIO_GROUP_NAME("CPU", GPIO_CNL_H_HDACPU_SDI, mGpioCpuNames),
+ GPIO_GROUP_NAME("JTAG", GPIO_CNL_H_JTAG_TDO, mGpioJtagNames),
+};
+
+/**
+ Returns GPIO_GROUP_NAME_INFO corresponding to the given GpioPad
+
+ @param[in] GroupIndex Group index
+
+ @retval GPIO_GROUP_NAME_INFO* Pointer to the GPIO_GROUP_NAME_INFO
+ @reval NULL If no group descriptor was found
+**/
+CONST
+GPIO_GROUP_NAME_INFO*
+GpioGetGroupNameInfo (
+ IN UINT32 GroupIndex
+ )
+{
+ if (IsPchLp ()) {
+ if (GroupIndex < ARRAY_SIZE (mPchLpGroupDescriptors)) {
+ return &mPchLpGroupDescriptors[GroupIndex];
+ } else {
+ ASSERT (FALSE);
+ return NULL;
+ }
+ } else {
+ if (GroupIndex < ARRAY_SIZE (mPchHGroupDescriptors)) {
+ return &mPchHGroupDescriptors[GroupIndex];
+ } else {
+ ASSERT (FALSE);
+ return NULL;
+ }
+ }
+}
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
new file mode 100644
index 0000000000..affecf9ec0
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
@@ -0,0 +1,1304 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific purpose
+ used by Reference Code only.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <SaAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include "GpioNativePrivateLibInternal.h"
+#include <Register/PchRegsGpio.h>
+#include <Register/PchRegsSerialIo.h>
+#include <Register/PchRegsIsh.h>
+
+/**
+ This function sets SerialIo I2C controller pins into native mode
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+ @param[in] GpioTermination GPIO termination type
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSerialIoI2c (
+ IN UINT32 SerialIoI2cControllerNumber,
+ IN GPIO_ELECTRICAL_CONFIG GpioTermination
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD_NATIVE_FUNCTION *I2cGpio;
+ GPIO_CONFIG GpioConfig;
+
+ GpioGetSerialIoI2cPins (
+ SerialIoI2cControllerNumber,
+ &I2cGpio
+ );
+
+ if (I2cGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem(&GpioConfig, sizeof(GPIO_CONFIG));
+ GpioConfig.ElectricalConfig = GpioTermination;
+
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
+ GpioConfig.PadMode = I2cGpio[Index].Mode;
+
+ Status = GpioSetPadConfig(I2cGpio[Index].Pad, &GpioConfig);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets SerialIo UART controller pins into native mode
+
+ @param[in] SerialIoUartControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+ @param[in] PinMuxing UART controller pin muxing
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSerialIoUart (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl,
+ IN UINT32 PinMuxing
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT32 PinsUsed;
+ GPIO_PAD_NATIVE_FUNCTION *UartGpio;
+
+ GpioGetSerialIoUartPins (
+ SerialIoUartControllerNumber,
+ HardwareFlowControl,
+ PinMuxing,
+ &UartGpio,
+ &PinsUsed
+ );
+
+ if (UartGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PinsUsed; Index++) {
+ Status = GpioSetPadMode (UartGpio[Index].Pad, UartGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (UartGpio[Index].Pad, 0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets SerialIo SPI controller pins into native mode
+
+ @param[in] SerialIoSpiControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSerialIoSpi (
+ IN UINT32 SerialIoSpiControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SpiGpio;
+ UINT32 NumOfSpiPins;
+
+ GpioGetSerialIoSpiPins (
+ SerialIoSpiControllerNumber,
+ &SpiGpio,
+ &NumOfSpiPins
+ );
+
+ if (SpiGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < NumOfSpiPins; Index++) {
+ Status = GpioSetPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (SpiGpio[Index].Pad, 0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableIshI2c (
+ IN UINT32 IshI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *I2cGpio;
+
+ GpioGetIshI2cPins (
+ IshI2cControllerNumber,
+ &I2cGpio
+ );
+
+ if (I2cGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = GpioSetPadMode (I2cGpio[Index].Pad, I2cGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableIshUart (
+ IN UINT32 IshUartControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *UartGpio;
+
+ GpioGetIshUartPins (
+ IshUartControllerNumber,
+ &UartGpio
+ );
+
+ if (UartGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) {
+ Status = GpioSetPadMode (UartGpio[Index].Pad, UartGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] IshSpiControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableIshSpi (
+ IN UINT32 IshSpiControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SpiGpio;
+ UINT32 NumOfSpiPins;
+
+ GpioGetIshSpiPins (
+ IshSpiControllerNumber,
+ &SpiGpio,
+ &NumOfSpiPins
+ );
+
+ if (SpiGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < NumOfSpiPins; Index++) {
+ Status = GpioSetPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets ISH GP pin into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableIshGpPin (
+ IN UINT32 IshGpPinNumber
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION IshGp;
+
+ GpioGetIshGpPin (
+ IshGpPinNumber,
+ &IshGp
+ );
+
+ Status = GpioSetPadMode (IshGp.Pad, IshGp.Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets SCS SD card controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableScsSdCard (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SdCardGpio;
+ UINT32 NumOfSdCardPins;
+ GPIO_CONFIG PwrEnConfig;
+
+ GpioGetScsSdCardPins (
+ &SdCardGpio,
+ &NumOfSdCardPins
+ );
+
+ if (SdCardGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // We need to leave the PWREN#
+ // GPIO pad unlocked since it is controlled at runtime
+ // by ACPI code. It is a work around for our SD card
+ // controller not respecting PWREN# invertion settings
+ // during D3. Since this pad will be in GPIO mode when
+ // SD controller is in D3 we need to set correct pad config.
+ //
+ GpioUnlockPadCfg (SdCardGpio[0].Pad);
+ GpioGetPadConfig (SdCardGpio[0].Pad, &PwrEnConfig);
+ PwrEnConfig.PadMode = SdCardGpio[0].Mode;
+ PwrEnConfig.Direction = GpioDirOut;
+ PwrEnConfig.HostSoftPadOwn = GpioHostOwnAcpi;
+ PwrEnConfig.InterruptConfig = GpioIntDis;
+ PwrEnConfig.PowerConfig = GpioHostDeepReset;
+ PwrEnConfig.LockConfig = GpioPadUnlock;
+ GpioSetPadConfig (SdCardGpio[0].Pad, &PwrEnConfig);
+
+ for (Index = 1; Index < NumOfSdCardPins; Index++) {
+ Status = GpioSetPadMode (SdCardGpio[Index].Pad, SdCardGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // SD Card Pins GPP_G0 - G4 require Native Termination
+ // Index in mPch[Lp/H]ScsSdCardGpio (depends on mPch[Lp/H]ScsSdCardGpio internal organization):
+ // GPP_G0 = 1
+ // GPP_G4 = 5
+ //
+ if (Index >= 1 && Index <= 5) {
+ Status = GpioSetPadElectricalConfig (SdCardGpio[Index].Pad, GpioTermNative);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function enables SCS Sd Card controller card detect pin
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableScsSdCardDetect (
+ VOID
+ )
+{
+ GPIO_CONFIG PadConfig;
+ GPIO_PAD GpioPad;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ ///
+ /// vSD3_CD_B line is driven by GPPC_G_5_SD3_CDB
+ /// and is used for interrupt for card detect event.
+ /// GPPC_G_5_SD3_CDB cannot be used for interrupt because this pin
+ /// is in native mode.
+ ///
+ GpioPad = GpioGetScsSdCardDetectPin ();
+ PadConfig.PadMode = GpioPadModeGpio;
+ PadConfig.Direction = GpioDirIn;
+ PadConfig.HostSoftPadOwn = GpioHostOwnGpio;
+ PadConfig.InterruptConfig = GpioIntBothEdge;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+
+ // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mode.
+ GpioUnlockPadCfg (GpioPad);
+
+ return GpioSetPadConfig (GpioPad, &PadConfig);
+}
+
+/**
+ This function sets SCS eMMC controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableScsEmmc (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *EmmcGpio;
+ UINT32 NumOfEmmcPins;
+
+ GpioGetScsEmmcPins (
+ &EmmcGpio,
+ &NumOfEmmcPins
+ );
+
+ if (EmmcGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < NumOfEmmcPins; Index++) {
+ Status = GpioSetPadMode (EmmcGpio[Index].Pad, EmmcGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets HDA Link pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaLink (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *HdaLinkGpio;
+ UINT32 NumOfHdaLinkPins;
+
+ GpioGetHdAudioLinkPins (
+ &HdaLinkGpio,
+ &NumOfHdaLinkPins
+ );
+
+ if (HdaLinkGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < NumOfHdaLinkPins; Index++) {
+ Status = GpioSetPadMode (HdaLinkGpio[Index].Pad, HdaLinkGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets HDA DMIC pins into native mode
+
+ @param[in] DmicNumber DMIC number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaDmic (
+ IN UINT32 DmicNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *DmicGpio;
+
+ GpioGetHdaDmicPins (
+ DmicNumber,
+ &DmicGpio
+ );
+
+ if (DmicGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_HDA_DMIC_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (DmicGpio[Index].Pad, DmicGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets HDA SSP interface pins into native mode
+
+ @param[in] SspInterfaceNumber SSPx interface number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSsp (
+ IN UINT32 SspInterfaceNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SspGpio;
+
+ GpioGetHdaSspPins (
+ SspInterfaceNumber,
+ &SspGpio
+ );
+
+ if (SspGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_HDA_SSP_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (SspGpio[Index].Pad, SspGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets HDA SoundWire interface pins into native mode
+
+ @param[in] SndwInterfaceNumber SNDWx interface number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSndw (
+ IN UINT32 SndwInterfaceNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SndwGpio;
+
+ GpioGetHdaSndwPins (
+ SndwInterfaceNumber,
+ &SndwGpio
+ );
+
+ if (SndwGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_HDA_SNDW_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (SndwGpio[Index].Pad, SndwGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets SMBUS controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSmbus (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SmbusGpio;
+
+ GpioGetSmbusPins (&SmbusGpio);
+
+ if (SmbusGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_SMBUS_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (SmbusGpio[Index].Pad, SmbusGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets SATA DevSlp pins into native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataDevSlpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION DevSlpGpio;
+
+ GpioGetSataDevSlpPin (
+ SataCtrlIndex,
+ SataPort,
+ &DevSlpGpio
+ );
+
+ GpioSetPadResetConfig (DevSlpGpio.Pad, GpioResumeReset);
+
+ return GpioSetPadMode (DevSlpGpio.Pad, DevSlpGpio.Mode);
+}
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+ This is an optional parameter and may be NULL.
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad OPTIONAL
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION DevSlpNativePad;
+ GPIO_PAD_MODE GpioMode;
+ EFI_STATUS Status;
+
+ ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
+
+ GpioGetSataDevSlpPin (
+ SataCtrlIndex,
+ SataPort,
+ &DevSlpNativePad
+ );
+
+ Status = GpioGetPadMode (DevSlpNativePad.Pad, &GpioMode);
+
+ if (EFI_ERROR (Status) || (GpioMode != DevSlpNativePad.Mode)) {
+ if (DevSlpPad != NULL) {
+ *DevSlpPad = GPIO_PAD_NONE;
+ }
+ return FALSE;
+ } else {
+ if (DevSlpPad != NULL) {
+ *DevSlpPad = DevSlpNativePad.Pad;
+ }
+ return TRUE;
+ }
+}
+
+/**
+ This function sets SATAGPx pin into native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataGpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION SataGpGpio;
+
+ GpioGetSataGpPin (
+ SataCtrlIndex,
+ SataPort,
+ &SataGpGpio
+ );
+
+ DEBUG_CODE_BEGIN ();
+ GPIO_PAD_MODE PadMode;
+ GpioGetPadMode (SataGpGpio.Pad, &PadMode);
+ if (PadMode == GpioPadModeNative1) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Cannot enable SATAGP%d, %a already used for SATAXPCIE_%d\n",
+ SataPort,
+ GpioName (SataGpGpio.Pad),
+ SataPort));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG_CODE_END ();
+
+ return GpioSetPadMode (SataGpGpio.Pad, SataGpGpio.Mode);
+}
+
+/**
+ Returns a pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION ClkReqGpio;
+
+ GpioGetPcieClkReqPin (
+ ClkreqIndex,
+ &ClkReqGpio
+ );
+
+ return ClkReqGpio.Pad;
+}
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ )
+{
+ GPIO_CONFIG PadConfig;
+ GPIO_PAD_NATIVE_FUNCTION ClkReqGpio;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ GpioGetPcieClkReqPin (
+ ClkreqIndex,
+ &ClkReqGpio
+ );
+
+ PadConfig.PadMode = ClkReqGpio.Mode;
+ PadConfig.Direction = GpioDirNone;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+ DEBUG ((DEBUG_INFO, "Enabling CLKREQ%d\n", ClkreqIndex));
+ GpioSetPadConfig (ClkReqGpio.Pad, &PadConfig);
+}
+
+
+/**
+ This function sets HPD, VDDEN, BKLTEN and BKLTCTL pins into native mode for eDP Panel
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableEdpPins (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD_NATIVE_FUNCTION *EdpPins;
+ UINT32 EdpPinsNumber;
+
+ GpioGetEdpPins (
+ &EdpPins,
+ &EdpPinsNumber
+ );
+
+ if (EdpPins == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Configure HPD, VDD and BKLT Pins for eDP panel
+ //
+ for (Index = 0; Index < EdpPinsNumber; Index++) {
+ Status = GpioSetPadMode (EdpPins[Index].Pad, EdpPins[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets DDP pins into native mode
+
+ @param[in] DdpInterface DDPx interface
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableDpInterface (
+ IN GPIO_DDP DdpInterface
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *DdpGpio;
+
+ GpioGetDdpPins (
+ DdpInterface,
+ &DdpGpio
+ );
+
+ if (DdpGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_DDP_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (DdpGpio[Index].Pad, DdpGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function configures GPIO connection between CNVi and CRF
+ @param[in] None
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviCrfConnection (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD_NATIVE_FUNCTION *CnviBriRgiExternalPad;
+
+ GpioGetCnvBriRgiPins (&CnviBriRgiExternalPad);
+
+ if (CnviBriRgiExternalPad == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Configure CNVi BRI and RGI buses for high speed communication with CRF
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (CnviBriRgiExternalPad[Index].Pad, CnviBriRgiExternalPad[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function configures virtual GPIO connection for CNVi Bluetooth UART
+
+ @param[in] ConnectionType
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviBtUartConnection (
+ IN VGPIO_CNVI_BT_UART_CONNECTION_TYPE ConnectionType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD *VCnviBtUartPad;
+ GPIO_PAD_MODE VCnviBtUartPadMode;
+ GPIO_PAD *VUartForCnviBtPad;
+ GPIO_PAD_MODE VUartForCnviBtPadMode;
+ GPIO_PAD_NATIVE_FUNCTION *CnviBtUartExternalPad;
+
+ GpioGetCnviBtUartPins (
+ ConnectionType,
+ &VCnviBtUartPad,
+ &VCnviBtUartPadMode,
+ &VUartForCnviBtPad,
+ &VUartForCnviBtPadMode
+ );
+
+ if ((VCnviBtUartPad == NULL) ||
+ (VUartForCnviBtPad == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Configure CNVi Bluetooth UART for certain connection
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VCnviBtUartPad[Index], VCnviBtUartPadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable virtual connection for UART for Bluetooth
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VUartForCnviBtPad[Index], VUartForCnviBtPadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable CNVi BT UART on external pads
+ //
+ if (ConnectionType == GpioCnviBtUartToExternalPads) {
+
+ GpioGetCnviBtUartExternalPins (&CnviBtUartExternalPad);
+
+ if (CnviBtUartExternalPad == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (CnviBtUartExternalPad[Index].Pad, CnviBtUartExternalPad[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function configures virtual GPIO connection for CNVi Bluetooth I2S
+
+ @param[in] ConnectionType
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviBtI2sConnection (
+ IN VGPIO_CNVI_BT_I2S_CONNECTION_TYPE ConnectionType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD *VCnviBtI2sPad;
+ GPIO_PAD_MODE VCnviBtI2sPadMode;
+ GPIO_PAD *VSspForCnviBtPad;
+ GPIO_PAD_MODE VSspForCnviBtPadMode;
+ GPIO_PAD_NATIVE_FUNCTION *CnviBtI2sExternalPad;
+
+ GpioGetCnviBtI2sPins (
+ ConnectionType,
+ &VCnviBtI2sPad,
+ &VCnviBtI2sPadMode,
+ &VSspForCnviBtPad,
+ &VSspForCnviBtPadMode
+ );
+
+ if ((VCnviBtI2sPad == NULL) ||
+ (VSspForCnviBtPad == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Configure CNVi Bluetooth I2S for certain connection
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VCnviBtI2sPad[Index], VCnviBtI2sPadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable virtual connection for SSP for Bluetooth
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VSspForCnviBtPad[Index], VSspForCnviBtPadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable CNV BT I2S on external pads
+ //
+ if (ConnectionType == (VGPIO_CNVI_BT_I2S_CONNECTION_TYPE) GpioCnviBtI2sToExternalPads) {
+
+ GpioGetCnviBtI2sExternalPins (&CnviBtI2sExternalPad);
+
+ if (CnviBtI2sExternalPad == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (CnviBtI2sExternalPad[Index].Pad, CnviBtI2sExternalPad[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function configures virtual GPIO connection for CNVi MFUART1
+
+ @param[in] ConnectionType
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviMfUart1Connection (
+ IN VGPIO_CNVI_MF_UART1_CONNECTION_TYPE ConnectionType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ GPIO_PAD *VCnviMfUart1Pad;
+ GPIO_PAD_MODE VCnviMfUart1PadMode;
+ GPIO_PAD *VUartForCnviMfUart1Pad;
+ GPIO_PAD_MODE VUartForCnviMfUart1PadMode;
+ GPIO_PAD_NATIVE_FUNCTION *CnviMfUart1ExternalPad;
+
+ GpioGetCnviMfUart1Pins (
+ ConnectionType,
+ &VCnviMfUart1Pad,
+ &VCnviMfUart1PadMode,
+ &VUartForCnviMfUart1Pad,
+ &VUartForCnviMfUart1PadMode
+ );
+
+ if ((VCnviMfUart1Pad == NULL) ||
+ (VUartForCnviMfUart1Pad == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Configure CNVi MFUART1 for certain connection
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VCnviMfUart1Pad[Index], VCnviMfUart1PadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable virtual connection for MFUART1
+ //
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (VUartForCnviMfUart1Pad[Index], VUartForCnviMfUart1PadMode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Enable CNV MFUART1 on external pads
+ //
+ if (ConnectionType == GpioCnviMfUart1ToExternalPads) {
+
+ GpioGetCnviMfUart1ExternalPins (&CnviMfUart1ExternalPad);
+
+ if (CnviMfUart1ExternalPad == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) {
+ Status = GpioSetPadMode (CnviMfUart1ExternalPad[Index].Pad, CnviMfUart1ExternalPad[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function sets CNVi Bluetooth Enable value
+
+ @param[in] Value CNVi BT enable value
+ 0: Disable, 1: Enable
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviBtEnState (
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD CnviBtEnPad;
+ GPIO_CONFIG PadConfig;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ PadConfig.PadMode = GpioPadModeGpio;
+ PadConfig.HostSoftPadOwn = GpioHostOwnGpio;
+ PadConfig.Direction = GpioDirOut;
+ if (Value == 1) {
+ PadConfig.OutputState = GpioOutHigh;
+ } else {
+ PadConfig.OutputState = GpioOutLow;
+ }
+ CnviBtEnPad = GpioGetCnviBtEnablePin ();
+
+ // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mode and it is GPO
+ GpioUnlockPadCfg (CnviBtEnPad);
+ GpioUnlockPadCfgTx (CnviBtEnPad);
+ Status = GpioSetPadConfig (CnviBtEnPad, &PadConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ This function sets CNVi Bluetooth main host interface
+
+ @param[in] BtInterface CNVi BT Interface Select value
+ GpioCnviBtIfUart: UART, GpioCnviBtIfUsb: USB
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviBtInterface (
+ IN VGPIO_CNVI_BT_INTERFACE BtInterface
+ )
+{
+ EFI_STATUS Status;
+ GPIO_CONFIG PadConfig;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ PadConfig.PadMode = GpioPadModeGpio;
+ PadConfig.Direction = GpioDirOut;
+ if (BtInterface == GpioCnviBtIfUsb) {
+ PadConfig.OutputState = GpioOutHigh;
+ } else {
+ PadConfig.OutputState = GpioOutLow;
+ }
+
+ Status = GpioSetPadConfig (GpioGetCnviBtIfSelectPin (), &PadConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets CNVi Bluetooth Wireless Charging support
+
+ @param[in] BtWirelessCharging CNVi BT Wireless Charging support
+ 0: Normal BT operation (no Wireless Charging support)
+ 1: Enable BT Wireless Charging
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviBtWirelessCharging (
+ IN UINT32 BtWirelessCharging
+ )
+{
+ EFI_STATUS Status;
+ GPIO_CONFIG CnviBtChargingPadConfig;
+ GPIO_PAD_NATIVE_FUNCTION A4WpPad;
+
+ ZeroMem (&CnviBtChargingPadConfig, sizeof (CnviBtChargingPadConfig));
+
+ CnviBtChargingPadConfig.PadMode = GpioPadModeGpio;
+ CnviBtChargingPadConfig.Direction = GpioDirOut;
+
+ if (BtWirelessCharging == 1) {
+ CnviBtChargingPadConfig.OutputState = GpioOutHigh;
+
+ GpioGetCnviA4WpPin (&A4WpPad);
+
+ Status = GpioSetPadMode (A4WpPad.Pad, A4WpPad.Mode);
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ CnviBtChargingPadConfig.OutputState = GpioOutLow;
+ }
+
+ Status = GpioSetPadConfig (GpioGetCnviBtChargingPin (), &CnviBtChargingPadConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function enables and configures CNVi Bluetooth Host wake-up interrupt
+
+ @param[in] None
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviBtHostWakeInt (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD CnviBtHostWakeIntPad;
+ GPIO_CONFIG PadConfig;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ PadConfig.PadMode = GpioPadModeGpio;
+ PadConfig.Direction = GpioDirIn;
+ PadConfig.HostSoftPadOwn = GpioHostOwnGpio;
+ PadConfig.InterruptConfig = GpioIntEdge;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+ CnviBtHostWakeIntPad = GpioGetCnviBtHostWakeIntPin ();
+
+ // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mode.
+ GpioUnlockPadCfg (CnviBtHostWakeIntPad);
+ Status = GpioSetPadConfig (CnviBtHostWakeIntPad, &PadConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function enables IMGU CLKOUT native pin
+
+ @param[in] None
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableImguClkOut (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *ImguClkOutGpio;
+ UINT32 NoOfNativePins;
+
+ GpioGetImgClkOutPins (
+ &ImguClkOutGpio,
+ &NoOfNativePins
+ );
+
+ if (ImguClkOutGpio == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < NoOfNativePins; Index++) {
+ Status = GpioSetPadMode (ImguClkOutGpio[Index].Pad, ImguClkOutGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Power button debounce configuration
+ Debounce time can be specified in microseconds. Only certain values according
+ to below formula are supported:
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period).
+ RTC clock with f = 32 KHz is used for glitch filter.
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us).
+ Supported DebounceTime values are following:
+ DebounceTime = 0 -> Debounce feature disabled
+ DebounceTime > 0 && < 250us -> Not supported
+ DebounceTime = 250us - 1024000us -> Supported range (DebounceTime = 250us * 2^n)
+ For values not supported by HW, they will be rounded down to closest supported one
+
+ @param[in] DebounceTime Debounce Time in microseconds
+ If Debounce Time = 0, Debouncer feature will be disabled
+ Function will set DebounceTime argument to rounded supported value
+**/
+VOID
+GpioSetPwrBtnDebounceTimer (
+ IN UINT32 DebounceTime
+ )
+{
+ GpioSetDebounceTimer (GpioGetPwrBtnPin (), &DebounceTime);
+}
+
+/**
+ Configure LPC GPIO
+**/
+VOID
+LpcConfigureGpio (
+ VOID
+ )
+{
+ GPIO_PAD GpioPad;
+ GpioPad = GpioGetLpcPin();
+
+ if (GpioPad == 0) {
+ return;
+ } else {
+ GpioSetPadElectricalConfig (GpioPad, GpioTermWpu20K);
+ }
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibCnl.c
new file mode 100644
index 0000000000..4cff00c27b
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibCnl.c
@@ -0,0 +1,2275 @@
+/** @file
+ This file contains specific GPIO information
+
+ 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 <SaAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <GpioPinsCnlLp.h>
+#include <GpioPinsCnlH.h>
+#include <Register/PchRegsGpio.h>
+#include <Register/PchRegsGpioCnl.h>
+#include <Register/PchRegsSerialIo.h>
+#include <Register/PchRegsIsh.h>
+#include <Register/PchRegsScs.h>
+#include <Register/PchRegsLpcCnl.h>
+
+#include "GpioNativePrivateLibInternal.h"
+
+//
+// I2C controller pins
+// I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio [][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_CNL_LP_GPP_C16, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_C17, GpioPadModeNative1}},
+ {{GPIO_CNL_LP_GPP_C18, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_C19, GpioPadModeNative1}},
+ {{GPIO_CNL_LP_GPP_H4, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H5 , GpioPadModeNative1}},
+ {{GPIO_CNL_LP_GPP_H6, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H7 , GpioPadModeNative1}},
+ {{GPIO_CNL_LP_GPP_H8, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H9 , GpioPadModeNative1}},
+ {{GPIO_CNL_LP_GPP_H10, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H11, GpioPadModeNative1}}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio [][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_CNL_H_GPP_C16, GpioPadModeNative1}, {GPIO_CNL_H_GPP_C17, GpioPadModeNative1}}, // I2C0
+ {{GPIO_CNL_H_GPP_C18, GpioPadModeNative1}, {GPIO_CNL_H_GPP_C19, GpioPadModeNative1}}, // I2C1
+ {{GPIO_CNL_H_GPP_D13, GpioPadModeNative3}, {GPIO_CNL_H_GPP_D14, GpioPadModeNative3}}, // I2C2
+ {{GPIO_CNL_H_GPP_D4, GpioPadModeNative2}, {GPIO_CNL_H_GPP_D23, GpioPadModeNative2}} // I2C3
+};
+
+
+/**
+ This function provides SerialIo I2C controller pins
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoI2cPins (
+ IN UINT32 SerialIoI2cControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (SerialIoI2cControllerNumber < ARRAY_SIZE (mPchLpI2cGpio)) {
+ *NativePinsTable = mPchLpI2cGpio[SerialIoI2cControllerNumber];
+ return;
+ }
+ } else {
+ if (SerialIoI2cControllerNumber < ARRAY_SIZE (mPchHI2cGpio)) {
+ *NativePinsTable = mPchHI2cGpio[SerialIoI2cControllerNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+//
+// UART controller pins
+// UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio [][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_CNL_LP_GPP_C8, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C9, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C10, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_CNL_LP_GPP_C12, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C13, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C14, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_CNL_LP_GPP_C20, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C21, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C22, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_C23, GpioPadModeNative1},
+ },
+ { // UART0 (2nd pin set)
+ {GPIO_CNL_LP_GPP_F5, GpioPadModeNative2},
+ {GPIO_CNL_LP_GPP_F6, GpioPadModeNative2},
+ {GPIO_CNL_LP_GPP_F4, GpioPadModeNative2},
+ {GPIO_CNL_LP_GPP_F7, GpioPadModeNative2}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio [][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_CNL_H_GPP_C8, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C9, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C10, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_CNL_H_GPP_C12, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C13, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C14, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_CNL_H_GPP_C20, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C21, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C22, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_C23, GpioPadModeNative1}
+ },
+ { // UART0 (2nd pin set)
+ {GPIO_CNL_H_GPP_J5, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_J6, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_J4, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_J7, GpioPadModeNative2}
+ }
+};
+
+/**
+ This function provides SerialIo UART controller pins
+
+ @param[in] SerialIoUartControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+ @param[in] PinMuxing UART controller pin muxing
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoUartPins (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl,
+ IN UINT32 PinMuxing,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ UINTN UartGpioIndex;
+
+ UartGpioIndex = SerialIoUartControllerNumber;
+
+ if ((SerialIoUartControllerNumber == 0) && (PinMuxing == 1)) {
+ // Last record is for UART0 second pin set
+ if (IsPchLp ()) {
+ UartGpioIndex = ARRAY_SIZE (mPchLpUartGpio) - 1;
+ } else {
+ UartGpioIndex = ARRAY_SIZE (mPchHUartGpio) - 1;
+ }
+ }
+
+ if (HardwareFlowControl) {
+ *NoOfNativePins = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER;
+ } else {
+ *NoOfNativePins = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL;
+ }
+
+ if (IsPchLp ()) {
+ if (UartGpioIndex < ARRAY_SIZE (mPchLpUartGpio)) {
+ *NativePinsTable = mPchLpUartGpio[UartGpioIndex];
+ return;
+ }
+ } else {
+ if (UartGpioIndex < ARRAY_SIZE (mPchHUartGpio)) {
+ *NativePinsTable = mPchHUartGpio[UartGpioIndex];
+ return;
+ }
+ }
+
+ *NativePinsTable = NULL;
+ *NoOfNativePins = 0;
+ ASSERT (FALSE);
+}
+
+//
+// SPI controller pins
+// SPI[controller number][pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio [][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_CNL_LP_GPP_B15, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B16, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B17, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_CNL_LP_GPP_B19, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B20, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B21, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B22, GpioPadModeNative1}
+ },
+ { // SPI2
+ {GPIO_CNL_LP_GPP_D9, GpioPadModeNative3},
+ {GPIO_CNL_LP_GPP_D10, GpioPadModeNative3},
+ {GPIO_CNL_LP_GPP_D11, GpioPadModeNative3},
+ {GPIO_CNL_LP_GPP_D12, GpioPadModeNative3}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio [][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_CNL_H_GPP_B15, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B16, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B17, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_CNL_H_GPP_B19, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B20, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B21, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B22, GpioPadModeNative1}
+ },
+ { // SPI2
+ {GPIO_CNL_H_GPP_D9, GpioPadModeNative3},
+ {GPIO_CNL_H_GPP_D10, GpioPadModeNative3},
+ {GPIO_CNL_H_GPP_D11, GpioPadModeNative3},
+ {GPIO_CNL_H_GPP_D12, GpioPadModeNative3}
+ }
+};
+
+/**
+ This function provides SerialIo SPI controller pins
+
+ @param[in] SerialIoSpiControllerNumber SPI controller
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetSerialIoSpiPins (
+ IN UINT32 SerialIoSpiControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ if (SerialIoSpiControllerNumber < ARRAY_SIZE (mPchLpSpiGpio)) {
+ *NativePinsTable = mPchLpSpiGpio[SerialIoSpiControllerNumber];
+ *NoOfNativePins = ARRAY_SIZE (mPchLpSpiGpio[SerialIoSpiControllerNumber]);
+ return;
+ }
+ } else {
+ if (SerialIoSpiControllerNumber < ARRAY_SIZE (mPchHSpiGpio)) {
+ *NativePinsTable = mPchHSpiGpio[SerialIoSpiControllerNumber];
+ *NoOfNativePins = ARRAY_SIZE (mPchHSpiGpio[SerialIoSpiControllerNumber]);
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ *NoOfNativePins = 0;
+ ASSERT (FALSE);
+}
+
+//
+// ISH GP pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[] =
+{
+ {GPIO_CNL_LP_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_CNL_LP_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_CNL_LP_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_CNL_LP_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_CNL_LP_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_CNL_LP_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_CNL_LP_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_CNL_LP_GPP_A17, GpioPadModeNative2} // ISH_GP_7
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[] =
+{
+ {GPIO_CNL_H_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_CNL_H_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_CNL_H_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_CNL_H_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_CNL_H_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_CNL_H_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_CNL_H_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_CNL_H_GPP_A17, GpioPadModeNative2} // ISH_GP_7
+};
+
+/**
+ This function provides ISH GP pin data
+
+ @param[in] IshGpPinNumber ISH GP pin number
+ @param[out] NativePin ISH GP pin
+**/
+VOID
+GpioGetIshGpPin (
+ IN UINT32 IshGpPinNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ )
+{
+ if (IsPchLp ()) {
+ if (IshGpPinNumber < ARRAY_SIZE (mPchLpIshGPGpio)) {
+ *NativePin = mPchLpIshGPGpio[IshGpPinNumber];
+ return;
+ }
+ } else {
+ if (IshGpPinNumber < ARRAY_SIZE (mPchHIshGPGpio)) {
+ *NativePin = mPchHIshGPGpio[IshGpPinNumber];
+ return;
+ }
+ }
+ *NativePin = (GPIO_PAD_NATIVE_FUNCTION){0};
+ ASSERT (FALSE);
+}
+
+//
+// ISH UART controller pins
+// ISH UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { // UART0
+ {GPIO_CNL_LP_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_CNL_LP_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_CNL_LP_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_CNL_LP_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { // UART1
+ {GPIO_CNL_LP_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_CNL_LP_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_CNL_LP_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTSB
+ {GPIO_CNL_LP_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTSB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { // UART0
+ {GPIO_CNL_H_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_CNL_H_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_CNL_H_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_CNL_H_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { // UART1
+ {GPIO_CNL_H_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_CNL_H_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_CNL_H_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTS
+ {GPIO_CNL_H_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTS
+ }
+};
+
+/**
+ This function provides ISH UART controller pins
+
+ @param[in] IshUartControllerNumber ISH UART controller
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetIshUartPins (
+ IN UINT32 IshUartControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (IshUartControllerNumber < ARRAY_SIZE (mPchLpIshUartGpio)) {
+ *NativePinsTable = mPchLpIshUartGpio[IshUartControllerNumber];
+ return;
+ }
+ } else {
+ if (IshUartControllerNumber < ARRAY_SIZE (mPchHIshUartGpio)) {
+ *NativePinsTable = mPchHIshUartGpio[IshUartControllerNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// ISH I2C controller pins
+// ISH I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { // I2C0
+ {GPIO_CNL_LP_GPP_D5, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_CNL_LP_GPP_D6, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { // I2C1
+ {GPIO_CNL_LP_GPP_D7, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_CNL_LP_GPP_D8, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { // I2C2
+ {GPIO_CNL_LP_GPP_H10, GpioPadModeNative2},// ISH_I2C2_SDA
+ {GPIO_CNL_LP_GPP_H11, GpioPadModeNative2} // ISH_I2C2_SCL
+ },
+ { // I2C3
+ {GPIO_CNL_LP_GPP_H4, GpioPadModeNative2},// ISH_I2C3_SDA
+ {GPIO_CNL_LP_GPP_H5, GpioPadModeNative2} // ISH_I2C3_SCL
+ },
+ { // I2C4
+ {GPIO_CNL_LP_GPP_H6, GpioPadModeNative2},// ISH_I2C4_SDA
+ {GPIO_CNL_LP_GPP_H7, GpioPadModeNative2} // ISH_I2C4_SCL
+ },
+ { // I2C5
+ {GPIO_CNL_LP_GPP_H8, GpioPadModeNative2},// ISH_I2C5_SDA
+ {GPIO_CNL_LP_GPP_H9, GpioPadModeNative2} // ISH_I2C5_SCL
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { // I2C0
+ {GPIO_CNL_H_GPP_H19, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_CNL_H_GPP_H20, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { // I2C1
+ {GPIO_CNL_H_GPP_H21, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_CNL_H_GPP_H22, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { // I2C2
+ {GPIO_CNL_H_GPP_D4, GpioPadModeNative1},// ISH_I2C2_SDA
+ {GPIO_CNL_H_GPP_D23, GpioPadModeNative1} // ISH_I2C2_SCL
+ }
+};
+
+/**
+ This function provides ISH I2C controller pins
+
+ @param[in] IshI2cControllerNumber ISH I2C controller
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetIshI2cPins (
+ IN UINT32 IshI2cControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (IshI2cControllerNumber < ARRAY_SIZE (mPchLpIshI2cGpio)) {
+ *NativePinsTable = mPchLpIshI2cGpio[IshI2cControllerNumber];
+ return;
+ }
+ } else {
+ if (IshI2cControllerNumber < ARRAY_SIZE (mPchHIshI2cGpio)) {
+ *NativePinsTable = mPchHIshI2cGpio[IshI2cControllerNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// ISH SPI controller pins
+// ISH SPI[pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_CNL_LP_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_CNL_LP_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_CNL_LP_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_CNL_LP_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_CNL_H_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_CNL_H_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_CNL_H_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_CNL_H_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+/**
+ This function provides ISH SPI controller pins
+
+ @param[in] IshSpiControllerNumber SPI controller
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetIshSpiPins (
+ IN UINT32 IshSpiControllerNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ if (IshSpiControllerNumber < ARRAY_SIZE (mPchLpIshSpiGpio)) {
+ *NativePinsTable = mPchLpIshSpiGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpIshSpiGpio);
+ return;
+ }
+ } else {
+ if (IshSpiControllerNumber < ARRAY_SIZE (mPchHIshSpiGpio)) {
+ *NativePinsTable = mPchHIshSpiGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchHIshSpiGpio);
+ return;
+ }
+ }
+
+ *NoOfNativePins = 0;
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// GPIO pins for SD controller
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpScsSdCardGpio[9] =
+{
+ {GPIO_CNL_LP_GPP_A17, GpioPadModeNative1},// SD_PWR_EN_B
+ {GPIO_CNL_LP_GPP_G0, GpioPadModeNative1},// SD_CMD
+ {GPIO_CNL_LP_GPP_G1, GpioPadModeNative1},// SD_DATA_0
+ {GPIO_CNL_LP_GPP_G2, GpioPadModeNative1},// SD_DATA_1
+ {GPIO_CNL_LP_GPP_G3, GpioPadModeNative1},// SD_DATA_2
+ {GPIO_CNL_LP_GPP_G4, GpioPadModeNative1},// SD_DATA_3
+ {GPIO_CNL_LP_GPP_G5, GpioPadModeNative1},// SD_CDB
+ {GPIO_CNL_LP_GPP_G6, GpioPadModeNative1},// SD_CLK
+ {GPIO_CNL_LP_GPP_G7, GpioPadModeNative1} // SD_WP
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHScsSdCardGpio[9] =
+{
+ {GPIO_CNL_H_GPP_A17, GpioPadModeNative1},// SD_PWR_EN_B
+ {GPIO_CNL_H_GPP_G0, GpioPadModeNative1},// SD_CMD
+ {GPIO_CNL_H_GPP_G1, GpioPadModeNative1},// SD_DATA_0
+ {GPIO_CNL_H_GPP_G2, GpioPadModeNative1},// SD_DATA_1
+ {GPIO_CNL_H_GPP_G3, GpioPadModeNative1},// SD_DATA_2
+ {GPIO_CNL_H_GPP_G4, GpioPadModeNative1},// SD_DATA_3
+ {GPIO_CNL_H_GPP_G5, GpioPadModeNative1},// SD_CDB
+ {GPIO_CNL_H_GPP_G6, GpioPadModeNative1},// SD_CLK
+ {GPIO_CNL_H_GPP_G7, GpioPadModeNative1} // SD_WP
+};
+
+/**
+ This function provides SCS SD CARD controller pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetScsSdCardPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpScsSdCardGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpScsSdCardGpio);
+ } else {
+ *NativePinsTable = mPchHScsSdCardGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchHScsSdCardGpio);
+ }
+}
+
+/**
+ This function provides SCS SD CARD detect pin
+
+ @retval GpioPin SD CARD Detect pin
+**/
+GPIO_PAD
+GpioGetScsSdCardDetectPin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_VGPIO39;
+ } else {
+ return GPIO_CNL_H_VGPIO6;
+ }
+}
+
+//
+// GPIO pins for eMMC controller
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpScsEmmcGpio[12] =
+{
+ {GPIO_CNL_LP_GPP_F11, GpioPadModeNative1},// EMMC_CMD
+ {GPIO_CNL_LP_GPP_F12, GpioPadModeNative1},// EMMC_DATA_0
+ {GPIO_CNL_LP_GPP_F13, GpioPadModeNative1},// EMMC_DATA_1
+ {GPIO_CNL_LP_GPP_F14, GpioPadModeNative1},// EMMC_DATA_2
+ {GPIO_CNL_LP_GPP_F15, GpioPadModeNative1},// EMMC_DATA_3
+ {GPIO_CNL_LP_GPP_F16, GpioPadModeNative1},// EMMC_DATA_4
+ {GPIO_CNL_LP_GPP_F17, GpioPadModeNative1},// EMMC_DATA_5
+ {GPIO_CNL_LP_GPP_F18, GpioPadModeNative1},// EMMC_DATA_6
+ {GPIO_CNL_LP_GPP_F19, GpioPadModeNative1},// EMMC_DATA_7
+ {GPIO_CNL_LP_GPP_F20, GpioPadModeNative1},// EMMC_RCLK
+ {GPIO_CNL_LP_GPP_F21, GpioPadModeNative1},// EMMC_CLK
+ {GPIO_CNL_LP_GPP_F22, GpioPadModeNative1} // EMMC_RESETB
+};
+
+/**
+ This function provides SCS eMMC controller pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetScsEmmcPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpScsEmmcGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpScsEmmcGpio);
+ } else {
+ ASSERT (FALSE);
+ return;
+ }
+}
+
+//
+// GPIO pins for HD Audio Link [pin: BCLK/RSTB/SYNC/SDO/SDIx]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaLinkGpio[PCH_GPIO_HDA_LINK_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_HDA_BCLK, GpioPadModeNative1},// HDA_BCLK
+ {GPIO_CNL_LP_HDA_RSTB, GpioPadModeNative1},// HDA_RSTB
+ {GPIO_CNL_LP_HDA_SYNC, GpioPadModeNative1},// HDA_SYNC
+ {GPIO_CNL_LP_HDA_SDO, GpioPadModeNative1},// HDA_SDO
+ {GPIO_CNL_LP_HDA_SDI_0, GpioPadModeNative1},// HDA_SDI_0
+ {GPIO_CNL_LP_HDA_SDI_1, GpioPadModeNative1} // HDA_SDI_1
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaLinkGpio[PCH_GPIO_HDA_LINK_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_HDA_BCLK, GpioPadModeNative1},// HDA_BCLK
+ {GPIO_CNL_H_HDA_RSTB, GpioPadModeNative1},// HDA_RSTB
+ {GPIO_CNL_H_HDA_SYNC, GpioPadModeNative1},// HDA_SYNC
+ {GPIO_CNL_H_HDA_SDO, GpioPadModeNative1},// HDA_SDO
+ {GPIO_CNL_H_HDA_SDI_0, GpioPadModeNative1},// HDA_SDI_0
+ {GPIO_CNL_H_HDA_SDI_1, GpioPadModeNative1} // HDA_SDI_1
+};
+
+/**
+ This function provides HD Audio Link pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetHdAudioLinkPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpHdaLinkGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpHdaLinkGpio);
+ } else {
+ *NativePinsTable = mPchHHdaLinkGpio;
+ *NoOfNativePins = ARRAY_SIZE (mPchHHdaLinkGpio);
+ }
+}
+
+//
+// GPIO pins for HD Audio DMIC [DMIC number][pin: CLK/DATA]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaDmicGpio[][PCH_GPIO_HDA_DMIC_NUMBER_OF_PINS] =
+{
+ { // DMIC0
+ {GPIO_CNL_LP_GPP_D19, GpioPadModeNative1},// DMIC_CLK_0
+ {GPIO_CNL_LP_GPP_D20, GpioPadModeNative1} // DMIC_DATA_0
+ },
+ { // DMIC1
+ {GPIO_CNL_LP_GPP_D17, GpioPadModeNative1},// DMIC_CLK_1
+ {GPIO_CNL_LP_GPP_D18, GpioPadModeNative1} // DMIC_DATA_1
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaDmicGpio[][PCH_GPIO_HDA_DMIC_NUMBER_OF_PINS] =
+{
+ { // DMIC0
+ {GPIO_CNL_H_GPP_D19, GpioPadModeNative1},// DMIC_CLK_0
+ {GPIO_CNL_H_GPP_D20, GpioPadModeNative1} // DMIC_DATA_0
+ },
+ { // DMIC1
+ {GPIO_CNL_H_GPP_D17, GpioPadModeNative1},// DMIC_CLK_1
+ {GPIO_CNL_H_GPP_D18, GpioPadModeNative1} // DMIC_DATA_1
+ }
+};
+
+/**
+ This function provides DMIC interface pins
+
+ @param[in] DmicNumber DMIC interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaDmicPins (
+ IN UINT32 DmicNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (DmicNumber < ARRAY_SIZE (mPchLpHdaDmicGpio)) {
+ *NativePinsTable = mPchLpHdaDmicGpio[DmicNumber];
+ return;
+ }
+ } else {
+ if (DmicNumber < ARRAY_SIZE (mPchHHdaDmicGpio)) {
+ *NativePinsTable = mPchHHdaDmicGpio[DmicNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// GPIO pins for HD Audio SSPx/I2Sx interface [SSP number][pin: SCLK/SFRM/TXD/RXD]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaSspInterfaceGpio[][PCH_GPIO_HDA_SSP_NUMBER_OF_PINS] =
+{
+ { // SSP0/I2S0
+ {GPIO_CNL_LP_HDA_BCLK, GpioPadModeNative2},// SSP0_SCLK
+ {GPIO_CNL_LP_HDA_SYNC, GpioPadModeNative2},// SSP0_SFRM
+ {GPIO_CNL_LP_HDA_SDO, GpioPadModeNative2},// SSP0_TXD
+ {GPIO_CNL_LP_HDA_SDI_0, GpioPadModeNative2} // SSP0_RXD
+ },
+ { // SSP1/I2S1
+ {GPIO_CNL_LP_HDA_RSTB, GpioPadModeNative2},// SSP1_SCLK
+ {GPIO_CNL_LP_SSP1_SFRM, GpioPadModeNative1},// SSP1_SFRM
+ {GPIO_CNL_LP_SSP1_TXD, GpioPadModeNative1},// SSP1_TXD
+ {GPIO_CNL_LP_HDA_SDI_1, GpioPadModeNative2} // SSP1_RXD
+ },
+ { // SSP2/I2S2
+ {GPIO_CNL_LP_GPP_H0, GpioPadModeNative1},// SSP2_SCLK
+ {GPIO_CNL_LP_GPP_H1, GpioPadModeNative1},// SSP2_SFRM
+ {GPIO_CNL_LP_GPP_H2, GpioPadModeNative1},// SSP2_TXD
+ {GPIO_CNL_LP_GPP_H3, GpioPadModeNative1} // SSP2_RXD
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaSspInterfaceGpio[][PCH_GPIO_HDA_SSP_NUMBER_OF_PINS] =
+{
+ { // SSP0/I2S0
+ {GPIO_CNL_H_HDA_BCLK, GpioPadModeNative2},// SSP0_SCLK
+ {GPIO_CNL_H_HDA_SYNC, GpioPadModeNative2},// SSP0_SFRM
+ {GPIO_CNL_H_HDA_SDO, GpioPadModeNative2},// SSP0_TXD
+ {GPIO_CNL_H_HDA_SDI_0, GpioPadModeNative2} // SSP0_RXD
+ },
+ { // SSP1/I2S1
+ {GPIO_CNL_H_HDA_RSTB, GpioPadModeNative2},// SSP1_SCLK
+ {GPIO_CNL_H_SSP1_SFRM, GpioPadModeNative1},// SSP1_SFRM
+ {GPIO_CNL_H_SSP1_TXD, GpioPadModeNative1},// SSP1_TXD
+ {GPIO_CNL_H_HDA_SDI_1, GpioPadModeNative2} // SSP1_RXD
+ },
+ { // SSP2/I2S2
+ {GPIO_CNL_H_GPP_D5, GpioPadModeNative1}, // SSP2_SFRM
+ {GPIO_CNL_H_GPP_D6, GpioPadModeNative1}, // SSP2_TXD
+ {GPIO_CNL_H_GPP_D7, GpioPadModeNative1}, // SSP2_RXD
+ {GPIO_CNL_H_GPP_D8, GpioPadModeNative1} // SSP2_SCLK
+ }
+};
+
+/**
+ This function provides SSP/I2S interface pins
+
+ @param[in] SspInterfaceNumber SSP/I2S interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaSspPins (
+ IN UINT32 SspInterfaceNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (SspInterfaceNumber < ARRAY_SIZE (mPchLpHdaSspInterfaceGpio)) {
+ *NativePinsTable = mPchLpHdaSspInterfaceGpio[SspInterfaceNumber];
+ return;
+ }
+ } else {
+ if (SspInterfaceNumber < ARRAY_SIZE (mPchHHdaSspInterfaceGpio)) {
+ *NativePinsTable = mPchHHdaSspInterfaceGpio[SspInterfaceNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// GPIO Pin for HD Audio SSP_MCLK/I2S_MCLK
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaSspMasterClockGpio = {GPIO_CNL_LP_GPP_D23, GpioPadModeNative1};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaSspMasterClockGpio = {GPIO_CNL_H_GPP_B11, GpioPadModeNative1};
+
+/**
+ This function sets HDA SSP Master Clock into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSspMasterClock (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GpioSetPadMode (mPchLpHdaSspMasterClockGpio.Pad, mPchLpHdaSspMasterClockGpio.Mode);
+ } else {
+ return GpioSetPadMode (mPchHHdaSspMasterClockGpio.Pad, mPchHHdaSspMasterClockGpio.Mode);
+ }
+}
+
+//
+// GPIO pins for HD Audio SoundWire interface [SNDW number][pin: CLK/DATA]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaSndwGpio[][PCH_GPIO_HDA_SNDW_NUMBER_OF_PINS] =
+{
+ { // SNDW1
+ {GPIO_CNL_LP_HDA_RSTB, GpioPadModeNative3},// SNDW1_CLK
+ {GPIO_CNL_LP_HDA_SDI_1, GpioPadModeNative3} // SNDW1_DATA
+ },
+ { // SNDW2
+ {GPIO_CNL_LP_SSP1_SFRM, GpioPadModeNative2},// SNDW2_CLK
+ {GPIO_CNL_LP_SSP1_TXD, GpioPadModeNative2} // SNDW2_DATA
+ },
+ { // SNDW3
+ {GPIO_CNL_LP_GPP_D17, GpioPadModeNative2},// SNDW3_CLK
+ {GPIO_CNL_LP_GPP_D18, GpioPadModeNative2} // SNDW3_DATA
+ },
+ { // SNDW4
+ {GPIO_CNL_LP_GPP_D19, GpioPadModeNative2},// SNDW4_CLK
+ {GPIO_CNL_LP_GPP_D20, GpioPadModeNative2} // SNDW4_DATA
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaSndwGpio[][PCH_GPIO_HDA_SNDW_NUMBER_OF_PINS] =
+{
+ { // SNDW1
+ {GPIO_CNL_H_HDA_RSTB, GpioPadModeNative3},// SNDW1_CLK
+ {GPIO_CNL_H_HDA_SDI_1, GpioPadModeNative3} // SNDW1_DATA
+ },
+ { // SNDW2
+ {GPIO_CNL_H_SSP1_SFRM, GpioPadModeNative2},// SNDW2_CLK
+ {GPIO_CNL_H_SSP1_TXD, GpioPadModeNative2} // SNDW2_DATA
+ },
+ { // SNDW3
+ {GPIO_CNL_H_GPP_D17, GpioPadModeNative2},// SNDW3_CLK
+ {GPIO_CNL_H_GPP_D18, GpioPadModeNative2} // SNDW3_DATA
+ },
+ { // SNDW4
+ {GPIO_CNL_H_GPP_D19, GpioPadModeNative2},// SNDW4_CLK
+ {GPIO_CNL_H_GPP_D20, GpioPadModeNative2} // SNDW4_DATA
+ }
+};
+
+/**
+ This function provides SNDW interface pins
+
+ @param[in] SndwInterfaceNumber SNDWx interface number
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetHdaSndwPins (
+ IN UINT32 SndwInterfaceNumber,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ if (SndwInterfaceNumber < ARRAY_SIZE (mPchLpHdaSndwGpio)) {
+ *NativePinsTable = mPchLpHdaSndwGpio[SndwInterfaceNumber];
+ return;
+ }
+ } else {
+ if (SndwInterfaceNumber < ARRAY_SIZE (mPchHHdaSndwGpio)) {
+ *NativePinsTable = mPchHHdaSndwGpio[SndwInterfaceNumber];
+ return;
+ }
+ }
+ *NativePinsTable = NULL;
+ ASSERT (FALSE);
+}
+
+//
+// GPIO pins for SMBUS
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSmbusGpio[PCH_GPIO_SMBUS_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_C0, GpioPadModeNative1},// SMB_CLK
+ {GPIO_CNL_LP_GPP_C1, GpioPadModeNative1} // SMB_DATA
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSmbusGpio[PCH_GPIO_SMBUS_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_C0, GpioPadModeNative1}, // SMB_CLK
+ {GPIO_CNL_H_GPP_C1, GpioPadModeNative1} // SMB_DATA
+};
+
+/**
+ This function provides SMBUS interface pins
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetSmbusPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpSmbusGpio;
+ } else {
+ *NativePinsTable = mPchHSmbusGpio;
+ }
+}
+
+//
+// SMBUS Alert pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSmbusAlertGpio = {GPIO_CNL_LP_GPP_C2, GpioPadModeNative1};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSmbusAlertGpio = {GPIO_CNL_H_GPP_C2, GpioPadModeNative1};
+
+/**
+ This function sets SMBUS ALERT pin into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSmbusAlert (
+ VOID
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION SmbusAlertGpio;
+
+ if (IsPchLp ()) {
+ SmbusAlertGpio = mPchLpSmbusAlertGpio;
+ } else {
+ SmbusAlertGpio = mPchHSmbusAlertGpio;
+ }
+
+ return GpioSetPadMode (SmbusAlertGpio.Pad, SmbusAlertGpio.Mode);
+}
+
+//
+// SATADevSlpPin to GPIO pin mapping
+// SATA_DEVSLP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[] =
+{
+ {GPIO_CNL_LP_GPP_E4, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_E5, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_E6, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[] =
+{
+ {GPIO_CNL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F7, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F8, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F9, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata1DevSlpPinToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 1
+ {GPIO_CNL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F7, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata2DevSlpPinToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 2
+ {GPIO_CNL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F7, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata3DevSlpPinToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 3
+ {GPIO_CNL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_F7, GpioPadModeNative1}
+};
+
+/**
+ This function provides SATA DevSlp pin data
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+ @param[out] NativePin SATA DevSlp pin
+**/
+VOID
+GpioGetSataDevSlpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ )
+{
+ if (IsCdfPch ()) {
+ if (SataCtrlIndex == SATA_1_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata1DevSlpPinToGpioMap)) {
+ *NativePin = mCdfPchSata1DevSlpPinToGpioMap[SataPort];
+ return;
+ }
+ } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata2DevSlpPinToGpioMap)) {
+ *NativePin = mCdfPchSata2DevSlpPinToGpioMap[SataPort];
+ return;
+ }
+ } else if (SataCtrlIndex == SATA_3_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata3DevSlpPinToGpioMap)) {
+ *NativePin = mCdfPchSata3DevSlpPinToGpioMap[SataPort];
+ return;
+ }
+ }
+ } else {
+ if (IsPchLp ()) {
+ if (SataPort < ARRAY_SIZE (mPchLpSataDevSlpPinToGpioMap)) {
+ *NativePin = mPchLpSataDevSlpPinToGpioMap[SataPort];
+ return;
+ }
+ } else {
+ if (SataPort < ARRAY_SIZE (mPchHSataDevSlpPinToGpioMap)) {
+ *NativePin = mPchHSataDevSlpPinToGpioMap[SataPort];
+ return;
+ }
+ }
+ }
+ *NativePin = (GPIO_PAD_NATIVE_FUNCTION){0};
+ ASSERT (FALSE);
+}
+
+//
+// SATA reset port to GPIO pin mapping
+// SATAGP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataGpToGpioMap[] =
+{
+ {GPIO_CNL_LP_GPP_E0, GpioPadModeNative2},
+ {GPIO_CNL_LP_GPP_E1, GpioPadModeNative2},
+ {GPIO_CNL_LP_GPP_E2, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataGpToGpioMap[] =
+{
+ {GPIO_CNL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F2, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F3, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F4, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata1GpToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 1
+ {GPIO_CNL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F2, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata2GpToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 2
+ {GPIO_CNL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F2, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mCdfPchSata3GpToGpioMap[] =
+{
+/// @todo SERVER- update for SATA 3
+ {GPIO_CNL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_CNL_H_GPP_F2, GpioPadModeNative2}
+};
+
+/**
+ This function provides SATA GP pin data
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+ @param[out] NativePin SATA GP pin
+**/
+VOID
+GpioGetSataGpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ )
+{
+ if (IsCdfPch ()) {
+ if (SataCtrlIndex == SATA_1_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata1GpToGpioMap)) {
+ *NativePin = mCdfPchSata1GpToGpioMap[SataPort];
+ return;
+ }
+ } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata2GpToGpioMap)) {
+ *NativePin = mCdfPchSata2GpToGpioMap[SataPort];
+ return;
+ }
+ } else if (SataCtrlIndex == SATA_3_CONTROLLER_INDEX) {
+ if (SataPort < ARRAY_SIZE (mCdfPchSata3GpToGpioMap)) {
+ *NativePin = mCdfPchSata3GpToGpioMap[SataPort];
+ return;
+ }
+ }
+ } else {
+ if (IsPchLp ()) {
+ if (SataPort < ARRAY_SIZE (mPchLpSataGpToGpioMap)) {
+ *NativePin = mPchLpSataGpToGpioMap[SataPort];
+ return;
+ }
+ } else {
+ if (SataPort < ARRAY_SIZE (mPchHSataGpToGpioMap)) {
+ *NativePin = mPchHSataGpToGpioMap[SataPort];
+ return;
+ }
+ }
+ }
+ *NativePin = (GPIO_PAD_NATIVE_FUNCTION){0};
+ ASSERT (FALSE);
+}
+
+//
+// SATA LED pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataLedGpio = {GPIO_CNL_LP_GPP_E8, GpioPadModeNative1};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataLedGpio = {GPIO_CNL_H_GPP_E8, GpioPadModeNative1};
+
+/**
+ This function sets SATA LED pin into native mode. SATA LED indicates
+ SATA controller activity
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataLed (
+ VOID
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION SataLedGpio;
+
+ if (IsPchLp ()) {
+ SataLedGpio = mPchLpSataLedGpio;
+ } else {
+ SataLedGpio = mPchHSataLedGpio;
+ }
+
+ return GpioSetPadMode (SataLedGpio.Pad, SataLedGpio.Mode);
+}
+
+//
+// USB2 OC pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUsbOcGpioPins[] =
+{
+ {GPIO_CNL_LP_GPP_E9, GpioPadModeNative1},// USB_OC_0
+ {GPIO_CNL_LP_GPP_E10, GpioPadModeNative1},// USB_OC_1
+ {GPIO_CNL_LP_GPP_E11, GpioPadModeNative1},// USB_OC_2
+ {GPIO_CNL_LP_GPP_E12, GpioPadModeNative1} // USB_OC_3
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHUsbOcGpioPins[] =
+{
+ {GPIO_CNL_H_GPP_E9, GpioPadModeNative1},// USB_OC_0
+ {GPIO_CNL_H_GPP_E10, GpioPadModeNative1},// USB_OC_1
+ {GPIO_CNL_H_GPP_E11, GpioPadModeNative1},// USB_OC_2
+ {GPIO_CNL_H_GPP_E12, GpioPadModeNative1},// USB_OC_3
+ {GPIO_CNL_H_GPP_F15, GpioPadModeNative1},// USB_OC_4
+ {GPIO_CNL_H_GPP_F16, GpioPadModeNative1},// USB_OC_5
+ {GPIO_CNL_H_GPP_F17, GpioPadModeNative1},// USB_OC_6
+ {GPIO_CNL_H_GPP_F18, GpioPadModeNative1} // USB_OC_7
+};
+
+/**
+ This function enables USB OverCurrent pins by setting
+ USB2 OCB pins into native mode
+
+ @param[in] OcPinNumber USB OC pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableUsbOverCurrent (
+ IN UINTN OcPinNumber
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION OcGpio;
+
+ if (IsPchLp ()) {
+ if (OcPinNumber >= ARRAY_SIZE (mPchLpUsbOcGpioPins)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ OcGpio = mPchLpUsbOcGpioPins[OcPinNumber];
+ } else {
+ if (OcPinNumber >= ARRAY_SIZE (mPchHUsbOcGpioPins)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ OcGpio = mPchHUsbOcGpioPins[OcPinNumber];
+ }
+
+ return GpioSetPadMode (OcGpio.Pad, OcGpio.Mode);
+}
+
+//
+// GPIO pin for PCIE SCRCLKREQB
+// SCRCLKREQB_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[] =
+{
+ {GPIO_CNL_LP_GPP_B5, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B6, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B7, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B8, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B9, GpioPadModeNative1},
+ {GPIO_CNL_LP_GPP_B10, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[] =
+{
+ {GPIO_CNL_H_GPP_B5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B7, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B8, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B9, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_B10, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H0, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H1, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H2, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H3, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H4, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H5, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H6, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H7, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H8, GpioPadModeNative1},
+ {GPIO_CNL_H_GPP_H9, GpioPadModeNative1}
+};
+
+/**
+ This function provides PCIe CLKREQ pin data
+
+ @param[in] ClkreqIndex CLKREQ# number
+ @param[out] NativePin Native pin data
+**/
+VOID
+GpioGetPcieClkReqPin (
+ IN UINT32 ClkreqIndex,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ )
+{
+ if (IsPchLp ()) {
+ if (ClkreqIndex < ARRAY_SIZE (mPchLpPcieSrcClkReqbPinToGpioMap)) {
+ *NativePin = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex];
+ return;
+ }
+ } else {
+ if (ClkreqIndex < ARRAY_SIZE (mPchHPcieSrcClkReqbPinToGpioMap)) {
+ *NativePin = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex];
+ return;
+ }
+ }
+ *NativePin = (GPIO_PAD_NATIVE_FUNCTION){0};
+ ASSERT (FALSE);
+}
+
+//
+// PCHHOTB pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin = {GPIO_CNL_LP_GPP_B23, GpioPadModeNative2};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin = {GPIO_CNL_H_GPP_B23, GpioPadModeNative2};
+
+/**
+ This function sets PCHHOT pin into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnablePchHot (
+ VOID
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION PchHotbPin;
+
+ if (IsPchLp ()) {
+ PchHotbPin = mPchLpPchHotbPin;
+ } else {
+ PchHotbPin = mPchHPchHotbPin;
+ }
+
+ return GpioSetPadMode (PchHotbPin.Pad, PchHotbPin.Mode);
+}
+
+//
+// VRALERTB pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpVrAlertbPin = {GPIO_CNL_LP_GPP_B2, GpioPadModeNative1};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHVrAlertbPin = {GPIO_CNL_H_GPP_B2, GpioPadModeNative1};
+
+//
+// CPU_C10_GATE pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuC10GatePin = {GPIO_CNL_LP_GPP_H18, GpioPadModeNative1};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuC10GatePin = {GPIO_CNL_H_GPP_J1, GpioPadModeNative2};
+
+/**
+ This function sets VRALERTB pin into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableVrAlert (
+ VOID
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION VrAlertGpio;
+
+ if (IsPchLp ()) {
+ VrAlertGpio = mPchLpVrAlertbPin;
+ } else {
+ VrAlertGpio = mPchHVrAlertbPin;
+ }
+
+ return GpioSetPadMode (VrAlertGpio.Pad, VrAlertGpio.Mode);
+}
+
+/**
+This function sets CPU C10 Gate pins into native mode
+
+@retval Status
+**/
+EFI_STATUS
+GpioEnableCpuC10GatePin (
+ VOID
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION CpuC10GateGpio;
+
+ if (IsPchLp ()) {
+ CpuC10GateGpio = mPchLpCpuC10GatePin;
+ } else {
+ CpuC10GateGpio = mPchHCpuC10GatePin;
+ }
+
+ return GpioSetPadMode (CpuC10GateGpio.Pad, CpuC10GateGpio.Mode);
+}
+
+//
+// CPU GP pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[PCH_GPIO_CPU_GP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_CNL_LP_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_CNL_LP_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_CNL_LP_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[PCH_GPIO_CPU_GP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_CNL_H_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_CNL_H_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_CNL_H_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableCpuGpPin (
+ IN UINT32 CpuGpPinNum
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION CpuGpPin;
+
+ if (IsPchLp ()) {
+ if (CpuGpPinNum >= ARRAY_SIZE (mPchLpCpuGpPinMap)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ CpuGpPin = mPchLpCpuGpPinMap[CpuGpPinNum];
+ } else {
+ if (CpuGpPinNum >= ARRAY_SIZE (mPchHCpuGpPinMap)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ CpuGpPin = mPchHCpuGpPinMap[CpuGpPinNum];
+ }
+
+ return GpioSetPadMode (CpuGpPin.Pad, CpuGpPin.Mode);
+}
+
+//
+// DDSP_HPD pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpDdspHpdPins[] =
+{
+ {GPIO_CNL_LP_GPP_E13, GpioPadModeNative1},// DDSP_HPD_0
+ {GPIO_CNL_LP_GPP_E14, GpioPadModeNative1},// DDSP_HPD_1
+ {GPIO_CNL_LP_GPP_E15, GpioPadModeNative1},// DDSP_HPD_2
+ {GPIO_CNL_LP_GPP_E16, GpioPadModeNative1} // DDSP_HPD_3
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHDdspHpdPins[] =
+{
+ {GPIO_CNL_H_GPP_I0, GpioPadModeNative1},// DDSP_HPD_0
+ {GPIO_CNL_H_GPP_I1, GpioPadModeNative1},// DDSP_HPD_1
+ {GPIO_CNL_H_GPP_I2, GpioPadModeNative1},// DDSP_HPD_2
+ {GPIO_CNL_H_GPP_I3, GpioPadModeNative1} // DDSP_HPD_3
+};
+
+/**
+ This function sets DDSP_HPDx pin into native mode
+
+ @param[in] DdspHpdPin DDSP_HPDx pin
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableDpHotPlugDetect (
+ IN GPIO_DDSP_HPD DdspHpdPin
+ )
+{
+ GPIO_PAD_NATIVE_FUNCTION DdspHpdGpio;
+ UINT32 DdspHpdPinIndex;
+
+ if (DdspHpdPin > GpioDdspHpd3) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DdspHpdPinIndex = DdspHpdPin - GpioDdspHpd0;
+
+ if (IsPchLp ()) {
+ if (DdspHpdPinIndex >= ARRAY_SIZE (mPchLpDdspHpdPins)) {
+ goto Error;
+ }
+ DdspHpdGpio = mPchLpDdspHpdPins[DdspHpdPinIndex];
+ } else {
+ if (DdspHpdPinIndex >= ARRAY_SIZE (mPchHDdspHpdPins)) {
+ goto Error;
+ }
+ DdspHpdGpio = mPchHDdspHpdPins[DdspHpdPinIndex];
+ }
+
+ return GpioSetPadMode (DdspHpdGpio.Pad, DdspHpdGpio.Mode);
+Error:
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+//
+// EDP HPD, VDD and BKLT pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpEdpPins[PCH_GPIO_EDP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_E17, GpioPadModeNative1},// EDP_HPD
+ {GPIO_CNL_LP_HVMOS_L_VDDEN, GpioPadModeNative1},// VDDEN
+ {GPIO_CNL_LP_HVMOS_L_BKLTEN, GpioPadModeNative1},// BKLTEN
+ {GPIO_CNL_LP_HVMOS_L_BKLTCTL, GpioPadModeNative1} // BKLTCTL
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHEdpPins[PCH_GPIO_EDP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_I4, GpioPadModeNative1},// EDP_HPD
+ {GPIO_CNL_H_GPP_F19, GpioPadModeNative1},// VDDEN
+ {GPIO_CNL_H_GPP_F20, GpioPadModeNative1},// BKLTEN
+ {GPIO_CNL_H_GPP_F21, GpioPadModeNative1} // BKLTCTL
+};
+
+/**
+ This function provides eDP pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetEdpPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpEdpPins;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpEdpPins);
+ } else {
+ *NativePinsTable = mPchHEdpPins;
+ *NoOfNativePins = ARRAY_SIZE (mPchHEdpPins);
+ }
+}
+
+//
+// DDPB/C/D/F CTRLCLK and CTRLDATA pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpDdpInterfacePins[PCH_GPIO_DDP_NUMBER_OF_INTERFACES][PCH_GPIO_DDP_NUMBER_OF_PINS] =
+{
+ {// DDPB
+ {GPIO_CNL_LP_GPP_E18, GpioPadModeNative1},// DDPB_CTRLCLK
+ {GPIO_CNL_LP_GPP_E19, GpioPadModeNative1} // DDPB_CTRLDATA
+ },
+ {// DDPC
+ {GPIO_CNL_LP_GPP_E20, GpioPadModeNative1},// DDPC_CTRLCLK
+ {GPIO_CNL_LP_GPP_E21, GpioPadModeNative1} // DDPC_CTRLDATA
+ },
+ {// DDPD
+ {GPIO_CNL_LP_GPP_E22, GpioPadModeNative1},// DDPD_CTRLCLK
+ {GPIO_CNL_LP_GPP_E23, GpioPadModeNative1} // DDPD_CTRLDATA
+ },
+ {// DDPF
+ {GPIO_CNL_LP_GPP_H16, GpioPadModeNative1},// DDPF_CTRLCLK
+ {GPIO_CNL_LP_GPP_H17, GpioPadModeNative1} // DDPF_CTRLDATA
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHDdpInterfacePins[PCH_GPIO_DDP_NUMBER_OF_INTERFACES][PCH_GPIO_DDP_NUMBER_OF_PINS] =
+{
+ {// DDPB
+ {GPIO_CNL_H_GPP_I5, GpioPadModeNative1}, // DDPB_CTRLCLK
+ {GPIO_CNL_H_GPP_I6, GpioPadModeNative1}, // DDPB_CTRLDATA
+ },
+ {// DDPC
+ {GPIO_CNL_H_GPP_I7, GpioPadModeNative1}, // DDPC_CTRLCLK
+ {GPIO_CNL_H_GPP_I8, GpioPadModeNative1}, // DDPC_CTRLDATA
+ },
+ {// DDPD
+ {GPIO_CNL_H_GPP_I9, GpioPadModeNative1}, // DDPD_CTRLCLK
+ {GPIO_CNL_H_GPP_I10, GpioPadModeNative1}, // DDPD_CTRLDATA
+ },
+ {// DDPF
+ {GPIO_CNL_H_GPP_F22, GpioPadModeNative1}, // DDPF_CTRLCLK
+ {GPIO_CNL_H_GPP_F23, GpioPadModeNative1}, // DDPF_CTRLDATA
+ }
+};
+
+/**
+ This function provides DDPx interface pins
+
+ @param[in] DdpInterface DDPx interface
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetDdpPins (
+ IN GPIO_DDP DdpInterface,
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ UINT32 DdpInterfaceIndex;
+
+ switch (DdpInterface) {
+ case GpioDdpB:
+ case GpioDdpC:
+ case GpioDdpD:
+ DdpInterfaceIndex = DdpInterface - GpioDdpB;
+ break;
+ case GpioDdpF:
+ DdpInterfaceIndex = 3;
+ break;
+ default:
+ goto Error;
+ }
+
+ if (IsPchLp ()) {
+ if (DdpInterfaceIndex < ARRAY_SIZE (mPchLpDdpInterfacePins)) {
+ *NativePinsTable = mPchLpDdpInterfacePins[DdpInterfaceIndex];
+ return;
+ }
+ } else {
+ if (DdpInterfaceIndex < ARRAY_SIZE (mPchHDdpInterfacePins)) {
+ *NativePinsTable = mPchHDdpInterfacePins[DdpInterfaceIndex];
+ return;
+ }
+ }
+Error:
+ *NativePinsTable = NULL;
+ ASSERT(FALSE);
+}
+
+/**
+ This function enables CNVi RF Reset pin
+**/
+VOID
+GpioEnableCnviRfResetPin (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD GpioPad;
+ GPIO_PAD_MODE PadMode;
+
+ if (IsPchLp ()) {
+ GpioPad = GPIO_CNL_LP_GPP_H1;
+ PadMode = GpioPadModeNative3;
+ } else {
+ GpioPad = GPIO_CNL_H_GPP_D5;
+ PadMode = GpioPadModeNative3;
+ }
+
+ Status = GpioSetPadMode (GpioPad, PadMode);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function enables CNVi MODEM CLKREQ pin
+**/
+VOID
+GpioEnableCnviModemClkReqPin (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD GpioPad;
+ GPIO_PAD_MODE PadMode;
+
+ if (IsPchLp ()) {
+ GpioPad = GPIO_CNL_LP_GPP_H2;
+ PadMode = GpioPadModeNative3;
+ } else {
+ GpioPad = GPIO_CNL_H_GPP_D6;
+ PadMode = GpioPadModeNative3;
+ }
+
+ Status = GpioSetPadMode (GpioPad, PadMode);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+ This function provides CNVi BT interface select pin
+
+ @retval GpioPad GPIO pad for CNVi BT interface select
+**/
+GPIO_PAD
+GpioGetCnviBtIfSelectPin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_VGPIO5;
+ } else {
+ return GPIO_CNL_H_VGPIO7;
+ }
+}
+
+/**
+ This function provides CNVi BT Charging pin
+
+ @retval GpioPad GPIO pad for CNVi BT Charging select
+**/
+GPIO_PAD
+GpioGetCnviBtChargingPin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_VGPIO3;
+ } else {
+ return GPIO_CNL_H_VGPIO3;
+ }
+}
+
+/**
+ This function provides CNVi A4WP pin
+
+ @param[out] GpioNativePad GPIO native pad for CNVi A4WP
+**/
+VOID
+GpioGetCnviA4WpPin (
+ OUT GPIO_PAD_NATIVE_FUNCTION *GpioNativePad
+ )
+{
+ GpioNativePad->Mode = GpioPadModeNative1;
+ if (IsPchLp ()) {
+ GpioNativePad->Pad = GPIO_CNL_LP_GPP_F23;
+ } else {
+ GpioNativePad->Pad = GPIO_CNL_H_GPP_J11;
+ }
+}
+
+/**
+ This function provides CNVi BT host wake int pin
+
+ @retval GpioPad GPIO pad BT host wake int
+**/
+GPIO_PAD
+GpioGetCnviBtHostWakeIntPin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_VGPIO4;
+ } else {
+ return GPIO_CNL_H_VGPIO4;
+ }
+}
+
+//
+// CNVi Bluetooth UART pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVCnviBtUartGpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO6, // vCNV_BT_UART_TXD
+ GPIO_CNL_LP_VGPIO7, // vCNV_BT_UART_RXD
+ GPIO_CNL_LP_VGPIO8, // vCNV_BT_UART_CTS_B
+ GPIO_CNL_LP_VGPIO9 // vCNV_BT_UART_RTS_B
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVCnviBtUartGpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO8, // vCNV_BT_UART_TXD
+ GPIO_CNL_H_VGPIO9, // vCNV_BT_UART_RXD
+ GPIO_CNL_H_VGPIO10,// vCNV_BT_UART_CTS_B
+ GPIO_CNL_H_VGPIO11 // vCNV_BT_UART_RTS_B
+};
+
+//
+// vUART for Bluetooth
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVUartForCnviBtGpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO18, // vUART0_TXD
+ GPIO_CNL_LP_VGPIO19, // vUART0_RXD
+ GPIO_CNL_LP_VGPIO20, // vUART0_CTS_B
+ GPIO_CNL_LP_VGPIO21 // vUART0_RTS_B
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVUartForCnviBtGpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO20, // vUART0_TXD
+ GPIO_CNL_H_VGPIO21, // vUART0_RXD
+ GPIO_CNL_H_VGPIO22, // vUART0_CTS_B
+ GPIO_CNL_H_VGPIO23 // vUART0_RTS_B
+};
+
+/**
+ This function provides CNVi BT UART pins
+
+ @param[in] ConnectionType CNVi BT UART connection type
+ @param[out] VCnviBtUartPad Table with vCNV_BT_UARTx pads
+ @param[out] VCnviBtUartPadMode vCNV_BT_UARTx pad mode
+ @param[out] VUartForCnviBtPad Table with vUART0 pads
+ @param[out] VUartForCnviBtPadMode vUART0 pad mode
+**/
+VOID
+GpioGetCnviBtUartPins (
+ IN VGPIO_CNVI_BT_UART_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviBtUartPad,
+ OUT GPIO_PAD_MODE *VCnviBtUartPadMode,
+ OUT GPIO_PAD **VUartForCnviBtPad,
+ OUT GPIO_PAD_MODE *VUartForCnviBtPadMode
+ )
+{
+ if (IsPchLp ()) {
+ *VCnviBtUartPad = mPchLpVCnviBtUartGpioPad;
+ *VUartForCnviBtPad = mPchLpVUartForCnviBtGpioPad;
+ } else {
+ *VCnviBtUartPad = mPchHVCnviBtUartGpioPad;
+ *VUartForCnviBtPad = mPchHVUartForCnviBtGpioPad;
+ }
+
+ switch (ConnectionType) {
+ case GpioCnviBtUartToSerialIoUart0:
+ *VCnviBtUartPadMode = GpioPadModeNative1;
+ *VUartForCnviBtPadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviBtUartToIshUart0:
+ *VCnviBtUartPadMode = GpioPadModeNative2;
+ *VUartForCnviBtPadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviBtUartNotConnected:
+ case GpioCnviBtUartToExternalPads:
+ *VCnviBtUartPadMode = GpioPadModeGpio;
+ *VUartForCnviBtPadMode = GpioPadModeGpio;
+ break;
+ default:
+ ASSERT (FALSE);
+ return;
+ }
+}
+
+//
+// CNVi Bluetooth UART external pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviBtUartExternalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_C8, GpioPadModeNative2}, // CNV_BT_UART_0_RXD
+ {GPIO_CNL_LP_GPP_C9, GpioPadModeNative2}, // CNV_BT_UART_0_TXD
+ {GPIO_CNL_LP_GPP_C10, GpioPadModeNative2}, // CNV_BT_UART_0_RTS
+ {GPIO_CNL_LP_GPP_C11, GpioPadModeNative2} // CNV_BT_UART_0_CTS
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCnviBtUartExternalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_C8, GpioPadModeNative2}, // CNV_BT_UART_0_RXD
+ {GPIO_CNL_H_GPP_C9, GpioPadModeNative2}, // CNV_BT_UART_0_TXD
+ {GPIO_CNL_H_GPP_C10, GpioPadModeNative2}, // CNV_BT_UART_0_RTS
+ {GPIO_CNL_H_GPP_C11, GpioPadModeNative2} // CNV_BT_UART_0_CTS
+};
+
+/**
+ This function provides CNVi BT UART external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviBtUartExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpCnviBtUartExternalPads;
+ } else {
+ *NativePinsTable = mPchHCnviBtUartExternalPads;
+ }
+}
+
+//
+// CNVi Bluetooth I2S pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVCnviBtI2sGpioPad[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO30, // vCNV_BT_I2S_BCLK
+ GPIO_CNL_LP_VGPIO31, // vCNV_BT_I2S_WS_SYNC
+ GPIO_CNL_LP_VGPIO32, // vCNV_BT_I2S_SDO
+ GPIO_CNL_LP_VGPIO33 // vCNV_BT_I2S_SDI
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVCnviBtI2sGpioPad[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO32, // vCNV_BT_I2S_BCLK
+ GPIO_CNL_H_VGPIO33, // vCNV_BT_I2S_WS_SYNC
+ GPIO_CNL_H_VGPIO34, // vCNV_BT_I2S_SDO
+ GPIO_CNL_H_VGPIO35 // vCNV_BT_I2S_SDI
+};
+
+//
+// vSSP for Bluetooth
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVSspForCnviBtGpioPad[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO34, // vSSP2_SCLK
+ GPIO_CNL_LP_VGPIO35, // vSSP2_SFRM
+ GPIO_CNL_LP_VGPIO36, // vSSP2_TXD
+ GPIO_CNL_LP_VGPIO37 // vSSP2_RXD
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVSspForCnviBtGpioPad[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO36, // vSSP2_SCLK
+ GPIO_CNL_H_VGPIO37, // vSSP2_SFRM
+ GPIO_CNL_H_VGPIO38, // vSSP2_TXD
+ GPIO_CNL_H_VGPIO39 // vSSP2_RXD
+};
+
+/**
+ This function provides CNVi BT I2S pins
+
+ @param[in] ConnectionType CNVi BT I2S connection type
+ @param[out] VCnviBtI2sPad Table with vCNV_BT_I2Sx pads
+ @param[out] VCnviBtI2sPadMode vCNV_BT_I2Sx pad mode
+ @param[out] VSspForCnviBtPad Table with vSSP2 pads
+ @param[out] VSspForCnviBtPadMode vSSP2 pad mode
+**/
+VOID
+GpioGetCnviBtI2sPins (
+ IN VGPIO_CNVI_BT_I2S_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviBtI2sPad,
+ OUT GPIO_PAD_MODE *VCnviBtI2sPadMode,
+ OUT GPIO_PAD **VSspForCnviBtPad,
+ OUT GPIO_PAD_MODE *VSspForCnviBtPadMode
+ )
+{
+ if (IsPchLp ()) {
+ *VCnviBtI2sPad = mPchLpVCnviBtI2sGpioPad;
+ *VSspForCnviBtPad = mPchLpVSspForCnviBtGpioPad;
+ } else {
+ *VCnviBtI2sPad = mPchHVCnviBtI2sGpioPad;
+ *VSspForCnviBtPad = mPchHVSspForCnviBtGpioPad;
+ }
+
+ switch (ConnectionType) {
+ case GpioCnviBtI2sToSsp0:
+ *VCnviBtI2sPadMode = GpioPadModeNative1;
+ *VSspForCnviBtPadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviBtI2sToSsp1:
+ *VCnviBtI2sPadMode = GpioPadModeNative2;
+ *VSspForCnviBtPadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviBtI2sToSsp2:
+ *VCnviBtI2sPadMode = GpioPadModeNative3;
+ *VSspForCnviBtPadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviBtI2sNotConnected:
+ case GpioCnviBtI2sToExternalPads:
+ *VCnviBtI2sPadMode = GpioPadModeGpio;
+ *VSspForCnviBtPadMode = GpioPadModeGpio;
+ break;
+ default:
+ ASSERT (FALSE);
+ return;
+ }
+}
+
+//
+// CNVi Bluetooth I2S external pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviBtI2sExternalPads[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_H0, GpioPadModeNative2}, // CNV_BT_I2S_WS_SYNC
+ {GPIO_CNL_LP_GPP_H1, GpioPadModeNative2}, // CNV_BT_I2S_BCLK
+ {GPIO_CNL_LP_GPP_H2, GpioPadModeNative2}, // CNV_BT_I2S_SDI
+ {GPIO_CNL_LP_GPP_H3, GpioPadModeNative2} // CNV_BT_I2S_SDO
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCnviBtI2sExternalPads[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_D8, GpioPadModeNative2}, // CNV_BT_I2S_WS_SYNC
+ {GPIO_CNL_H_GPP_D5, GpioPadModeNative2}, // CNV_BT_I2S_BCLK
+ {GPIO_CNL_H_GPP_D6, GpioPadModeNative2}, // CNV_BT_I2S_SDI
+ {GPIO_CNL_H_GPP_D7, GpioPadModeNative2} // CNV_BT_I2S_SDO
+};
+
+/**
+ This function provides CNVi BT I2S external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviBtI2sExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpCnviBtI2sExternalPads;
+ } else {
+ *NativePinsTable = mPchHCnviBtI2sExternalPads;
+ }
+}
+
+//
+// CNVi MFUART1 pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVCnviMfUart1GpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO10, // vCNV_MFUART1_TXD
+ GPIO_CNL_LP_VGPIO11, // vCNV_MFUART1_RXD
+ GPIO_CNL_LP_VGPIO12, // vCNV_MFUART1_CTS_B
+ GPIO_CNL_LP_VGPIO13 // vCNV_MFUART1_RTS_B
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVCnviMfUart1GpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO12, // vCNV_MFUART1_TXD
+ GPIO_CNL_H_VGPIO13, // vCNV_MFUART1_RXD
+ GPIO_CNL_H_VGPIO14, // vCNV_MFUART1_CTS_B
+ GPIO_CNL_H_VGPIO15 // vCNV_MFUART1_RTS_B
+};
+
+//
+// vUART for MFUART1
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVUartForCnviMfUart1GpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_LP_VGPIO22, // vISH_UART0_TXD
+ GPIO_CNL_LP_VGPIO23, // vISH_UART0_RXD
+ GPIO_CNL_LP_VGPIO24, // vISH_UART0_CTS_B
+ GPIO_CNL_LP_VGPIO25 // vISH_UART0_RTS_B
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchHVUartForCnviMfUart1GpioPad[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ GPIO_CNL_H_VGPIO24, // vISH_UART0_TXD
+ GPIO_CNL_H_VGPIO25, // vISH_UART0_RXD
+ GPIO_CNL_H_VGPIO26, // vISH_UART0_CTS_B
+ GPIO_CNL_H_VGPIO27 // vISH_UART0_RTS_B
+};
+
+/**
+ This function provides CNVi MFUART1 pins
+
+ @param[in] ConnectionType CNVi MFUART1 connection type
+ @param[out] VCnviBtI2sPad Table with vCNV_MFUART1x pads
+ @param[out] VCnviBtI2sPadMode vCNV_MFUART1x pad mode
+ @param[out] VSspForCnviBtPad Table with vISH_UART0 pads
+ @param[out] VSspForCnviBtPadMode vISH_UART0 pad mode
+**/
+VOID
+GpioGetCnviMfUart1Pins (
+ IN VGPIO_CNVI_MF_UART1_CONNECTION_TYPE ConnectionType,
+ OUT GPIO_PAD **VCnviMfUart1Pad,
+ OUT GPIO_PAD_MODE *VCnviMfUart1PadMode,
+ OUT GPIO_PAD **VUartForCnviMfUart1Pad,
+ OUT GPIO_PAD_MODE *VUartForCnviMfUart1PadMode
+ )
+{
+ if (IsPchLp ()) {
+ *VCnviMfUart1Pad = mPchLpVCnviMfUart1GpioPad;
+ *VUartForCnviMfUart1Pad = mPchLpVUartForCnviMfUart1GpioPad;
+ } else {
+ *VCnviMfUart1Pad = mPchHVCnviMfUart1GpioPad;
+ *VUartForCnviMfUart1Pad = mPchHVUartForCnviMfUart1GpioPad;
+ }
+
+ switch (ConnectionType) {
+ case GpioCnviMfUart1ToSerialIoUart2:
+ *VCnviMfUart1PadMode = GpioPadModeNative2;
+ *VUartForCnviMfUart1PadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviMfUart1ToIshUart0:
+ *VCnviMfUart1PadMode = GpioPadModeNative1;
+ *VUartForCnviMfUart1PadMode = GpioPadModeNative1;
+ break;
+ case GpioCnviMfUart1NotConnected:
+ case GpioCnviMfUart1ToExternalPads:
+ *VCnviMfUart1PadMode = GpioPadModeGpio;
+ *VUartForCnviMfUart1PadMode = GpioPadModeGpio;
+ break;
+ default:
+ ASSERT (FALSE);
+ return;
+ }
+}
+
+//
+// CNVi MFUART1 external pads
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviMfUart1ExternalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_C12, GpioPadModeNative3}, // CNV_MFUART1_RXD
+ {GPIO_CNL_LP_GPP_C13, GpioPadModeNative3}, // CNV_MFUART1_TXD
+ {GPIO_CNL_LP_GPP_C14, GpioPadModeNative3}, // CNV_MFUART1_RTS
+ {GPIO_CNL_LP_GPP_C15, GpioPadModeNative3} // CNV_MFUART1_CTS
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCnviMfUart1ExternalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_C12, GpioPadModeNative3}, // CNV_MFUART1_RXD
+ {GPIO_CNL_H_GPP_C13, GpioPadModeNative3}, // CNV_MFUART1_TXD
+ {GPIO_CNL_H_GPP_C14, GpioPadModeNative3}, // CNV_MFUART1_RTS
+ {GPIO_CNL_H_GPP_C15, GpioPadModeNative3} // CNV_MFUART1_CTS
+};
+
+/**
+ This function provides CNVi MFUART1 external pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnviMfUart1ExternalPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpCnviMfUart1ExternalPads;
+ } else {
+ *NativePinsTable = mPchHCnviMfUart1ExternalPads;
+ }
+}
+
+/**
+ This function provides CNVi Bluetooth Enable pad
+
+ @retval GpioPad CNVi Bluetooth Enable pad
+**/
+GPIO_PAD
+GpioGetCnviBtEnablePin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_VGPIO0;
+ } else {
+ return GPIO_CNL_H_VGPIO0;
+ }
+}
+
+//
+// CNVi BRI (Bluetooth Radio Interface) and RGI (Radio Generic Interface) buses from Pulsar to CRF (Companion RF)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviBriRgiGpioPad[PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_F4, GpioPadModeNative1}, // CNV_BRI_DT
+ {GPIO_CNL_LP_GPP_F5, GpioPadModeNative1}, // CNV_BRI_RSP
+ {GPIO_CNL_LP_GPP_F6, GpioPadModeNative1}, // CNV_RGI_DT
+ {GPIO_CNL_LP_GPP_F7, GpioPadModeNative1} // CNV_RGI_RSP
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCnviBriRgiGpioPad[PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_J4, GpioPadModeNative1}, // CNV_BRI_DT
+ {GPIO_CNL_H_GPP_J5, GpioPadModeNative1}, // CNV_BRI_RSP
+ {GPIO_CNL_H_GPP_J6, GpioPadModeNative1}, // CNV_RGI_DT
+ {GPIO_CNL_H_GPP_J7, GpioPadModeNative1} // CNV_RGI_RSP
+};
+
+/**
+ This function provides CNVi BRI RGI GPIO pads
+
+ @param[out] NativePinsTable Table with pins
+**/
+VOID
+GpioGetCnvBriRgiPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpCnviBriRgiGpioPad;
+ } else {
+ *NativePinsTable = mPchHCnviBriRgiGpioPad;
+ }
+}
+
+
+/**
+ This function sets CNVi WiFi mode
+
+ @param[in] Value CNVi WiFi Mode value
+ GpioCnviWiFiAuto: WiFi is automatically enabled/disabled by WiFi core
+ GpioCnviWiFiEnabled: WiFi is enabled regardless of WiFi core decision
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviWifiMode (
+ IN VGPIO_CNVI_WIFI_MODE WiFiMode
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD CnviWifiModePad;
+ GPIO_CONFIG PadConfig;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ PadConfig.PadMode = GpioPadModeGpio;
+ PadConfig.Direction = GpioDirOut;
+ if (WiFiMode == GpioCnviWiFiEnabled) {
+ PadConfig.OutputState = GpioOutHigh;
+ } else {
+ PadConfig.OutputState = GpioOutLow;
+ }
+
+ if (IsPchLp ()) {
+ CnviWifiModePad = GPIO_CNL_LP_VGPIO2;
+ } else {
+ CnviWifiModePad = GPIO_CNL_H_VGPIO2;
+ }
+
+ Status = GpioSetPadConfig (CnviWifiModePad, &PadConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpImguClkOutGpioPad[SA_GPIO_IMGUCLK_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_LP_GPP_D4, GpioPadModeNative1}, // IMGCLKOUT_0
+ {GPIO_CNL_LP_GPP_H20, GpioPadModeNative1}, // IMGCLKOUT_1
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHImguClkOutGpioPad[SA_GPIO_IMGUCLK_NUMBER_OF_PINS] =
+{
+ {GPIO_CNL_H_GPP_K22, GpioPadModeNative1}, // IMGCLKOUT_0
+ {GPIO_CNL_H_GPP_K23, GpioPadModeNative1}, // IMGCLKOUT_1
+};
+
+/**
+ This function provides IMGCLKOUT pins
+
+ @param[out] NativePinsTable Table with pins
+ @param[out] NoOfNativePins Number of pins
+**/
+VOID
+GpioGetImgClkOutPins (
+ OUT GPIO_PAD_NATIVE_FUNCTION **NativePinsTable,
+ OUT UINT32 *NoOfNativePins
+ )
+{
+ if (IsPchLp ()) {
+ *NativePinsTable = mPchLpImguClkOutGpioPad;
+ *NoOfNativePins = ARRAY_SIZE (mPchLpImguClkOutGpioPad);
+ } else {
+ *NativePinsTable = mPchHImguClkOutGpioPad;
+ *NoOfNativePins = ARRAY_SIZE (mPchHImguClkOutGpioPad);
+ }
+}
+
+/**
+ This function provides PWRBTN pin
+
+ @retval GpioPad PWRTBTN pin
+**/
+GPIO_PAD
+GpioGetPwrBtnPin (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_GPD3;
+ } else {
+ return GPIO_CNL_H_GPD3;
+ }
+}
+
+/**
+ This function provides LPC pin
+
+ @retval GpioPad LPC pin
+**/
+GPIO_PAD
+GpioGetLpcPin (
+ VOID
+ )
+{
+ if (PchGetLpcDid () == V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A305_SKU) {
+ return GPIO_CNL_H_GPP_A8;
+ } else {
+ return 0;
+ }
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..2cf11c6da2
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,752 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+ 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/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+#include <Private/Library/GpioNameBufferLib.h>
+#include <Register/PchRegsPcr.h>
+
+#include "GpioNativePrivateLibInternal.h"
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return ((GPIO_GET_CHIPSET_ID (GpioPad) == GpioGetThisChipsetId ()) &&
+ (GpioGetGroupIndexFromGpioPad (GpioPad) < GpioGetNumberOfGroups ()));
+}
+
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RegVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset), RegVal);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI.
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiHostSwOwnRegAddress Address of HOSTSW_OWN register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiHostSwOwnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroup;
+ UINT32 GpioGroupInfoLength;
+ UINT32 SmiStsRegOffset;
+ UINT32 HostSwOwnRegOffset;
+ GPIO_PAD_OWN PadOwnVal;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ PadNumber = 0;
+ GroupIndex = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected group has GPI SMI Enable and Status registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioGroup = GpioGetGroupFromGroupIndex (GroupIndex);
+ *GpioPin = GpioGetGpioPadFromGroupAndPadNumber (GpioGroup, PadNumber);
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH/IE
+ //
+ GpioGetPadOwnership (*GpioPin, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a not owned by host!\n", GpioName (*GpioPin)));
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ *GpiSmiBitOffset = (UINT8)(PadNumber % 32);
+
+ HostSwOwnRegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset + (PadNumber / 32) * 0x4;
+ *GpiHostSwOwnRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, HostSwOwnRegOffset);
+
+ SmiStsRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiStsRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiStsRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ PCH_SBI_PID *GpioComSbiIds;
+ UINT32 NoOfGpioComs;
+ UINT32 GpioComIndex;
+
+ Data32And = (UINT32)~(B_GPIO_PCR_MISCCFG_IRQ_ROUTE);
+ Data32Or = (UINT32)Irq << N_GPIO_PCR_MISCCFG_IRQ_ROUTE;
+
+ 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 return Port ID of GPIO Community from GpioPad
+
+ @param[in] GpioPad GpioPad
+
+ @retval GpioCommunityPortId Port ID of GPIO Community
+**/
+UINT8
+GpioGetGpioCommunityPortIdFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ return GpioGroupInfo[GroupIndex].Community;
+}
+
+/**
+ This procedure will return PadCfg address from GpioPad
+
+ @param[in] GpioPad GpioPad
+
+ @retval GpioPadCfgAddress PadCfg Address of GpioPad
+**/
+UINT32
+GpioGetGpioPadCfgAddressFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 PadCfgRegAddress;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgRegAddress = GpioGroupInfo[GroupIndex].PadCfgOffset + S_GPIO_PCR_PADCFG * PadNumber;
+
+ return PadCfgRegAddress;
+}
+
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ // If GPIO is not owned by Host all access to PadCfg will be dropped
+ //
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a is not owned by host!\n", GpioName (GpioPad)));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 PadNumber;
+
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad (0x%08x) used on this chipset!\n", GpioPad));
+ goto Error;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if legal pin number
+ //
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ if (PadNumber >= GpioGroupInfo[GpioGetGroupIndexFromGpioPad (GpioPad)].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ goto Error;
+ }
+
+ return TRUE;
+Error:
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ This procedure will read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+
+ @retval PadCfgRegValue PADCFG_DWx value
+**/
+UINT32
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg
+ )
+{
+ UINT32 PadCfgReg;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + S_GPIO_PCR_PADCFG * PadNumber + 0x4 * DwReg;
+
+ return MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ )
+{
+ UINT32 PadCfgReg;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 PadCfgLock;
+ UINT32 PadCfgLockTx;
+
+ PadCfgLock = 0;
+ PadCfgLockTx = 0;
+
+ //
+ // Check if Pad Configuration (except output state) is to be changed.
+ // If AND and OR masks will indicate that configuration fields (other than output control)
+ // are to be modified it means that there is a need to perform an unlock (if set)
+ //
+ if ((~PadCfgAndMask | PadCfgOrMask) & (UINT32)~B_GPIO_PCR_TX_STATE) {
+ GpioGetPadCfgLock (GpioPad, &PadCfgLock);
+ if (PadCfgLock) {
+ GpioUnlockPadCfg (GpioPad);
+ }
+ }
+
+ //
+ // Check if Pad Output state is to be changed
+ // If AND and OR masks will indicate that output control
+ // is to be modified it means that there is a need to perform an unlock (if set)
+ //
+ if ((~PadCfgAndMask | PadCfgOrMask) & B_GPIO_PCR_TX_STATE) {
+ GpioGetPadCfgLockTx (GpioPad, &PadCfgLockTx);
+ if (PadCfgLockTx) {
+ GpioUnlockPadCfgTx (GpioPad);
+ }
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + S_GPIO_PCR_PADCFG * PadNumber + 0x4 * DwReg;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ PadCfgAndMask,
+ PadCfgOrMask
+ );
+
+ if (PadCfgLock) {
+ GpioLockPadCfg (GpioPad);
+ }
+ if (PadCfgLockTx) {
+ GpioLockPadCfgTx (GpioPad);
+ }
+}
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ UINT32 PadCfgOrMask;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (PadModeValue != (GPIO_PAD_MODE)GpioHardwareDefault) {
+
+ PadCfgOrMask = (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_GPIO_PCR_PAD_MODE);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_PAD_MODE,
+ PadCfgOrMask
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ UINT32 PadCfgRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgRegValue = GpioReadPadCfgReg (GpioPad, 0);
+
+ *PadModeValue = (GPIO_PAD_MODE)(((PadCfgRegValue & B_GPIO_PCR_PAD_MODE) >> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The function performs GPIO Power Management programming.
+**/
+VOID
+GpioConfigurePm (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ PCH_SBI_PID *GpioComSbiIds;
+ UINT32 NoOfGpioComs;
+ UINT32 GpioComIndex;
+
+ Data32And = (UINT32)~0,
+ //
+ // Enable MISCCFG.GPSIDEDPCGEn, MISCCFG.GPRCOMPCDLCGEn, MISCCFG.GPRTCDLCGEn,
+ // MISCCFG.GPDLCGEn and MISCCFG.GPDPCGEn for GPIO communities
+ //
+ Data32Or = (B_GPIO_PCR_MISCCFG_GPSIDEDPCGEN |
+ B_GPIO_PCR_MISCCFG_GPRCOMPCDLCGEN |
+ B_GPIO_PCR_MISCCFG_GPRTCDLCGEN |
+ B_GPIO_PCR_MISCCFG_GPDLCGEN |
+ B_GPIO_PCR_MISCCFG_GPDPCGEN);
+
+ NoOfGpioComs = GpioGetComSbiPortIds (&GpioComSbiIds);
+
+ //
+ // Configure Clock Gating in each community
+ //
+ for (GpioComIndex = 0; GpioComIndex < NoOfGpioComs; GpioComIndex++) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioComSbiIds[GpioComIndex], R_GPIO_PCR_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+ }
+}
+
+/**
+ This procedure is used to unlock all GPIO pads.
+ This function can only be called when platform is still in HOSTIA_BOOT_SAI.
+**/
+VOID
+GpioUnlockAllPads (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ UINT32 GroupIndex;
+ UINT32 NumberOfGroups;
+ GPIO_GROUP Group;
+ UINT32 LockValue;
+ EFI_STATUS Status;
+
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ for (GroupIndex = 0; GroupIndex < NumberOfGroups; GroupIndex++) {
+ Group = GpioGetGroupFromGroupIndex (GroupIndex);
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &LockValue);
+
+ if (LockValue) {
+ Status = GpioUnlockPadCfgForGroupDw (Group, DwNum, ~0u);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &LockValue);
+
+ if (LockValue) {
+ Status = GpioUnlockPadCfgTxForGroupDw (Group, DwNum, ~0u);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+}
+
+/**
+ Generates GPIO name from GpioPad
+ This function returns pointer to the static buffer
+
+ @param[in] GpioPad GpioPad
+
+ @retval CHAR8* Pointer to the gpio name string
+**/
+CHAR8*
+GpioName (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GpioGetPadName (GpioPad, GpioGetStaticNameBuffer (), GPIO_NAME_LENGTH_MAX);
+}
+
+
+//
+// For GPIO debounce feature glitch filter clock is used
+// which is driven by RTC clock with f = 32kHz (T = 31.25us)
+//
+#define GPIO_DEB_CLK_PERIOD_IN_NS 31250
+
+/**
+ This procedure enables debounce feature on a selected pad configured in input mode
+ Debounce time can be specified in microseconds. GPIO HW supports only certain values
+ according to below formula:
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period).
+ RTC clock with f = 32 KHz is used for glitch filter.
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us).
+ Supported DebounceTime values are following:
+ DebounceTime = 0 -> Debounce feature disabled
+ DebounceTime > 0 && < 250us -> Not supported
+ DebounceTime = 250us - 1024000us -> Supported range (DebounceTime = 250us * 2^n)
+ For values not supported by GPIO HW, function will round down
+ to closest supported
+
+ @param[in] GpioPad GPIO pad
+ @param[in, out] DebounceTime Debounce Time in microseconds
+ If Debounce Time = 0, Debouncer feature will be disabled
+ Function will set DebounceTime argument to rounded supported value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad or unsupported DebounceDuration value
+ @retval EFI_UNSUPPORTED GpioPad is not owned by host
+**/
+EFI_STATUS
+GpioSetDebounceTimer (
+ IN GPIO_PAD GpioPad,
+ IN OUT UINT32 *DebounceTime
+ )
+{
+ UINT32 DebounceEnable;
+ UINT32 DebounceValue;
+ UINT32 InRangeDebounceTime;
+ UINT32 SupportedDebounceTime;
+ UINT32 Temp;
+ BOOLEAN SupportedValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (*DebounceTime > 1024000) {
+ InRangeDebounceTime = 1024000;
+ SupportedValue = FALSE;
+ } else if ((*DebounceTime < 250) && (*DebounceTime > 0)) {
+ InRangeDebounceTime = 0;
+ SupportedValue = FALSE;
+ } else {
+ InRangeDebounceTime = *DebounceTime;
+ SupportedValue = TRUE;
+ }
+
+ //
+ // DebounceValue = log2 (InRangeDebounceTime * f_deb_clk)
+ //
+ DebounceValue = 0;
+ Temp = InRangeDebounceTime * 1000 / GPIO_DEB_CLK_PERIOD_IN_NS;
+
+ //
+ // Check if any rounding occurred
+ //
+ if (InRangeDebounceTime != (Temp * GPIO_DEB_CLK_PERIOD_IN_NS / 1000)) {
+ SupportedValue = FALSE;
+ }
+
+ //
+ // Check if value is power of 2
+ //
+ if ((Temp != 0) && ((Temp & (Temp - 1)) != 0)) {
+ SupportedValue = FALSE;
+ }
+
+ //
+ // DebounceValue = log2 (Temp)
+ //
+ while (Temp > 1) {
+ Temp >>= 1;
+ DebounceValue++;
+ }
+
+ if (DebounceValue > 0) {
+ DebounceEnable = B_GPIO_PCR_DEBEN;
+ SupportedDebounceTime = (1 << DebounceValue) * GPIO_DEB_CLK_PERIOD_IN_NS / 1000;
+ } else {
+ DebounceEnable = 0;
+ SupportedDebounceTime = 0;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 2,
+ (UINT32)~(B_GPIO_PCR_DEBOUNCE | B_GPIO_PCR_DEBEN),
+ (DebounceValue << N_GPIO_PCR_DEBOUNCE) | DebounceEnable
+ );
+
+ if (!SupportedValue) {
+ DEBUG ((DEBUG_WARN, "GPIO WARNING: %a %dus debounce time rounded down to %dus\n",
+ GpioName (GpioPad),
+ *DebounceTime,
+ SupportedDebounceTime));
+ }
+
+ *DebounceTime = SupportedDebounceTime;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLibCnl.c
new file mode 100644
index 0000000000..a6d260f4ad
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLibCnl.c
@@ -0,0 +1,225 @@
+/** @file
+ This file contains specific GPIO information
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Register/PchRegsGpioCnl.h>
+#include <Register/PchRegsPmcCnl.h>
+#include <GpioPinsCnlLp.h>
+#include <GpioPinsCnlH.h>
+#include <GpioConfig.h>
+#include <Register/PchRegsPcr.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_A_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_A_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_A_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_A_PAD_MAX}, //CNL PCH-LP GPP_A
+ {PID_GPIOCOM0, R_CNL_PCH_LP_GPIO_PCR_GPP_B_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_B_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_SMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_B_SMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_NMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_B_NMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_B_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_B_PAD_MAX}, //CNL PCH-LP GPP_B
+ {PID_GPIOCOM4, R_CNL_PCH_LP_GPIO_PCR_GPP_C_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_C_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_SMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_C_SMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_NMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_C_NMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_C_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_C_PAD_MAX}, //CNL PCH-LP GPP_C
+ {PID_GPIOCOM1, R_CNL_PCH_LP_GPIO_PCR_GPP_D_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_D_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_SMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_D_SMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_NMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_D_NMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_D_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_D_PAD_MAX}, //CNL PCH-LP GPP_D
+ {PID_GPIOCOM4, R_CNL_PCH_LP_GPIO_PCR_GPP_E_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_E_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_SMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_E_SMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_NMI_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_E_NMI_EN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_E_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_E_PAD_MAX}, //CNL PCH-LP GPP_E
+ {PID_GPIOCOM1, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_F_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_F_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_F_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_F_PAD_MAX}, //CNL PCH-LP GPP_F
+ {PID_GPIOCOM0, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_G_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_G_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_G_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_G_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_G_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_G_PAD_MAX}, //CNL PCH-LP GPP_G
+ {PID_GPIOCOM1, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_H_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_H_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPP_H_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPP_H_PAD_MAX}, //CNL PCH-LP GPP_H
+ {PID_GPIOCOM2, R_CNL_PCH_LP_GPIO_PCR_GPD_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_GPD_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPD_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_GPD_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_GPD_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPD_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_GPD_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPD_PADCFG_OFFSET, CNL_PCH_LP_GPIO_GPD_PAD_MAX}, //CNL PCH-LP GPD
+ {PID_GPIOCOM1, R_CNL_PCH_LP_GPIO_PCR_VGPIO_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_VGPIO_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_VGPIO_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_VGPIO_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_VGPIO_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_VGPIO_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_VGPIO_0_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_VGPIO_0_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_VGPIO_PADCFG_OFFSET, CNL_PCH_LP_GPIO_VGPIO_PAD_MAX}, //CNL PCH-LP vGPIO
+ {PID_GPIOCOM0, R_CNL_PCH_LP_GPIO_PCR_SPI_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_SPI_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_SPI_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_SPI_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_SPI_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_SPI_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_SPI_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_SPI_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_SPI_PADCFG_OFFSET, CNL_PCH_LP_GPIO_SPI_PAD_MAX}, //CNL PCH-LP SPI
+ {PID_GPIOCOM3, R_CNL_PCH_LP_GPIO_PCR_AZA_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_AZA_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_AZA_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_AZA_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_AZA_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_AZA_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_AZA_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_AZA_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_AZA_PADCFG_OFFSET, CNL_PCH_LP_GPIO_AZA_PAD_MAX}, //CNL PCH-LP AZA
+ {PID_GPIOCOM3, R_CNL_PCH_LP_GPIO_PCR_CPU_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_CPU_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_CPU_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_CPU_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_CPU_PADCFG_OFFSET, CNL_PCH_LP_GPIO_CPU_PAD_MAX}, //CNL PCH-LP CPU
+ {PID_GPIOCOM4, R_CNL_PCH_LP_GPIO_PCR_JTAG_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_JTAG_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_JTAG_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_JTAG_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_JTAG_PADCFG_OFFSET, CNL_PCH_LP_GPIO_JTAG_PAD_MAX}, //CNL PCH-LP JTAG
+ {PID_GPIOCOM4, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PAD_OWN, R_CNL_PCH_LP_GPIO_PCR_HVMOS_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_HVMOS_GPI_IS, R_CNL_PCH_LP_GPIO_PCR_HVMOS_GPI_IE, R_CNL_PCH_LP_GPIO_PCR_HVMOS_GPI_GPE_STS, R_CNL_PCH_LP_GPIO_PCR_HVMOS_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PADCFGLOCK, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PADCFG_OFFSET, CNL_PCH_LP_GPIO_HVMOS_PAD_MAX} //CNL PCH-LP HVMOS
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchHGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_CNL_PCH_H_GPIO_PCR_GPP_A_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_A_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_A_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_A_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_A_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_A_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_A_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_A_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_A_PAD_MAX}, //CNL PCH-H GPP_A
+ {PID_GPIOCOM0, R_CNL_PCH_H_GPIO_PCR_GPP_B_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_B_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_B_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_B_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_B_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_B_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_B_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_B_SMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_B_NMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_B_NMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_B_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_B_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_B_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_B_PAD_MAX}, //CNL PCH-H GPP_B
+ {PID_GPIOCOM1, R_CNL_PCH_H_GPIO_PCR_GPP_C_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_C_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_C_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_C_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_C_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_C_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_C_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_C_SMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_C_NMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_C_NMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_C_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_C_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_C_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_C_PAD_MAX}, //CNL PCH-H GPP_C
+ {PID_GPIOCOM1, R_CNL_PCH_H_GPIO_PCR_GPP_D_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_D_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_D_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_D_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_D_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_D_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_D_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_D_SMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_D_NMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_D_NMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_D_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_D_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_D_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_D_PAD_MAX}, //CNL PCH-H GPP_D
+ {PID_GPIOCOM3, R_CNL_PCH_H_GPIO_PCR_GPP_E_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_E_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_E_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_E_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_E_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_E_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_E_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_E_SMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_E_NMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_E_NMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_E_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_E_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_E_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_E_PAD_MAX}, //CNL PCH-H GPP_E
+ {PID_GPIOCOM3, R_CNL_PCH_H_GPIO_PCR_GPP_F_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_F_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_F_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_F_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_F_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_F_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_F_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_F_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_F_PAD_MAX}, //CNL PCH-H GPP_F
+ {PID_GPIOCOM1, R_CNL_PCH_H_GPIO_PCR_GPP_G_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_G_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_G_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_G_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_G_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_G_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_G_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_G_SMI_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_G_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_G_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_G_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_G_PAD_MAX}, //CNL PCH-H GPP_G
+ {PID_GPIOCOM3, R_CNL_PCH_H_GPIO_PCR_GPP_H_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_H_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_H_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_H_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_H_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_H_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_H_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_H_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_H_PAD_MAX}, //CNL PCH-H GPP_H
+ {PID_GPIOCOM4, R_CNL_PCH_H_GPIO_PCR_GPP_I_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_I_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_I_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_I_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_I_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_I_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_I_SMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_I_SMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_I_NMI_STS, R_CNL_PCH_H_GPIO_PCR_GPP_I_NMI_EN, R_CNL_PCH_H_GPIO_PCR_GPP_I_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_I_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_I_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_I_PAD_MAX}, //CNL PCH-H GPP_I
+ {PID_GPIOCOM4, R_CNL_PCH_H_GPIO_PCR_GPP_J_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_J_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_J_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_J_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_J_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_J_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_J_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_J_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_J_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_J_PAD_MAX}, //CNL PCH-H GPP_J
+ {PID_GPIOCOM3, R_CNL_PCH_H_GPIO_PCR_GPP_K_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_K_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPP_K_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPP_K_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_K_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPP_K_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPP_K_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPP_K_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPP_K_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPP_K_PAD_MAX}, //CNL PCH-H GPP_K
+ {PID_GPIOCOM2, R_CNL_PCH_H_GPIO_PCR_GPD_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_GPD_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_GPD_GPI_IS, R_CNL_PCH_H_GPIO_PCR_GPD_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPD_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_GPD_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_GPD_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_GPD_PADCFG_OFFSET, CNL_PCH_H_GPIO_GPD_PAD_MAX}, //CNL PCH-H GPD
+ {PID_GPIOCOM1, R_CNL_PCH_H_GPIO_PCR_VGPIO_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_VGPIO_HOSTSW_OWN, R_CNL_PCH_H_GPIO_PCR_VGPIO_GPI_IS, R_CNL_PCH_H_GPIO_PCR_VGPIO_GPI_IE, R_CNL_PCH_H_GPIO_PCR_VGPIO_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_VGPIO_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_VGPIO_0_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_VGPIO_0_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_VGPIO_PADCFG_OFFSET, CNL_PCH_H_GPIO_VGPIO_PAD_MAX}, //CNL PCH-H vGPIO
+ {PID_GPIOCOM3, R_CNL_PCH_H_GPIO_PCR_SPI_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_SPI_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_SPI_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_SPI_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_SPI_PADCFG_OFFSET, CNL_PCH_H_GPIO_SPI_PAD_MAX}, //CNL PCH-H SPI
+ {PID_GPIOCOM1, R_CNL_PCH_H_GPIO_PCR_AZA_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_AZA_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_AZA_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_AZA_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_AZA_PADCFG_OFFSET, CNL_PCH_H_GPIO_AZA_PAD_MAX}, //CNL PCH-H AZA
+ {PID_GPIOCOM4, R_CNL_PCH_H_GPIO_PCR_CPU_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_CPU_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_CPU_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_CPU_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_CPU_PADCFG_OFFSET, CNL_PCH_H_GPIO_CPU_PAD_MAX}, //CNL PCH-H CPU
+ {PID_GPIOCOM4, R_CNL_PCH_H_GPIO_PCR_JTAG_PAD_OWN, R_CNL_PCH_H_GPIO_PCR_JTAG_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_CNL_PCH_H_GPIO_PCR_JTAG_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_JTAG_PADCFGLOCKTX, R_CNL_PCH_H_GPIO_PCR_JTAG_PADCFG_OFFSET, CNL_PCH_H_GPIO_JTAG_PAD_MAX} //CNL PCH-H JTAG
+};
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+CONST GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINT32 *GpioGroupInfoTableLength
+ )
+{
+ if (IsPchLp ()) {
+ *GpioGroupInfoTableLength = ARRAY_SIZE (mPchLpGpioGroupInfo);
+ return mPchLpGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = ARRAY_SIZE (mPchHGpioGroupInfo);
+ return mPchHGpioGroupInfo;
+ }
+}
+
+/**
+ Get GPIO Chipset ID specific to PCH generation and series
+**/
+UINT32
+GpioGetThisChipsetId (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_CNL_LP_CHIPSET_ID;
+ } else {
+ return GPIO_CNL_H_CHIPSET_ID;
+ }
+}
+
+/**
+ This internal procedure will check if group is within DeepSleepWell.
+
+ @param[in] Group GPIO Group
+
+ @retval GroupWell TRUE: This is DSW Group
+ FALSE: This is not DSW Group
+**/
+BOOLEAN
+GpioIsDswGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ if ((Group == GPIO_CNL_LP_GROUP_GPD) || (Group == GPIO_CNL_H_GROUP_GPD)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ This procedure will perform special handling of GPP_A_12.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_PAD GpioPad;
+
+ //
+ // PCH BWG 16.6. GPP_A_12 Special Handling
+ //
+ if (IsPchLp ()) {
+ GpioPad = GPIO_CNL_LP_GPP_A12;
+ } else {
+ GpioPad = GPIO_CNL_H_GPP_A12;
+ }
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+
+ //
+ // If the pad is host-own, BIOS has to always lock this pad after being initialized
+ //
+ if (PadOwnVal == GpioPadOwnHost) {
+ //
+ // Set PadCfgLock for GPP_A_12
+ //
+ GpioLockPadCfg (GpioPad);
+ }
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SBI_PID mGpioComSbiIds[] =
+{
+ PID_GPIOCOM0, PID_GPIOCOM1, PID_GPIOCOM2, PID_GPIOCOM3, PID_GPIOCOM4
+};
+
+/**
+ This function provides GPIO Community PortIDs
+
+ @param[out] NativePinsTable Table with GPIO COMMx SBI PortIDs
+
+ @retval Number of communities
+**/
+UINT32
+GpioGetComSbiPortIds (
+ OUT PCH_SBI_PID **GpioComSbiIds
+ )
+{
+ *GpioComSbiIds = mGpioComSbiIds;
+ return ARRAY_SIZE (mGpioComSbiIds);
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchLpGpioGroupToGpeMapping[] = {
+ {GPIO_CNL_LP_GROUP_GPP_A, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_A, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_A},
+ {GPIO_CNL_LP_GROUP_GPP_B, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_B, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_B},
+ {GPIO_CNL_LP_GROUP_GPP_C, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_C, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_C},
+ {GPIO_CNL_LP_GROUP_GPP_D, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_D, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_D},
+ {GPIO_CNL_LP_GROUP_GPP_E, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_E, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_E},
+ {GPIO_CNL_LP_GROUP_GPP_F, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_F, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_F},
+ {GPIO_CNL_LP_GROUP_GPP_G, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_G, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_G},
+ {GPIO_CNL_LP_GROUP_GPP_H, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_H, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_H},
+ {GPIO_CNL_LP_GROUP_GPD, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPD, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPD},
+ {GPIO_CNL_LP_GROUP_VGPIO , 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_VGPIO, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_VGPIO},
+ {GPIO_CNL_LP_GROUP_SPI, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_SPI, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_SPI},
+ {GPIO_CNL_LP_GROUP_AZA, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_AZA, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_AZA},
+ {GPIO_CNL_LP_GROUP_JTAG, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_JTAG, V_CNL_PCH_LP_GPIO_PCR_MISCCFG_GPE0_JTAG}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchHGpioGroupToGpeMapping[] = {
+ {GPIO_CNL_H_GROUP_GPP_A, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_A, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_A},
+ {GPIO_CNL_H_GROUP_GPP_B, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_B, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_B},
+ {GPIO_CNL_H_GROUP_GPP_C, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_C, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_C},
+ {GPIO_CNL_H_GROUP_GPP_D, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_D, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_D},
+ {GPIO_CNL_H_GROUP_GPP_E, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_E, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_E},
+ {GPIO_CNL_H_GROUP_GPP_F, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_F, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_F},
+ {GPIO_CNL_H_GROUP_GPP_G, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_G, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_G},
+ {GPIO_CNL_H_GROUP_GPP_H, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_H, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_H},
+ {GPIO_CNL_H_GROUP_GPP_I, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_I, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_I},
+ {GPIO_CNL_H_GROUP_GPP_J, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_J, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_J},
+ {GPIO_CNL_H_GROUP_GPP_K, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPP_K, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPP_K},
+ {GPIO_CNL_H_GROUP_GPD, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_GPD, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_GPD},
+ {GPIO_CNL_H_GROUP_VGPIO, 0, V_CNL_PCH_H_PMC_PWRM_GPIO_CFG_VGPIO, V_CNL_PCH_H_GPIO_PCR_MISCCFG_GPE0_VGPIO}
+};
+
+/**
+ Get information for GPIO Group required to program GPIO and PMC for desired 1-Tier GPE mapping
+
+ @param[out] GpioGroupToGpeMapping Table with GPIO Group to GPE mapping
+ @param[out] GpioGroupToGpeMappingLength GPIO Group to GPE mapping table length
+**/
+VOID
+GpioGetGroupToGpeMapping (
+ OUT GPIO_GROUP_TO_GPE_MAPPING **GpioGroupToGpeMapping,
+ OUT UINT32 *GpioGroupToGpeMappingLength
+ )
+{
+ if (IsPchLp ()) {
+ *GpioGroupToGpeMapping = mPchLpGpioGroupToGpeMapping;
+ *GpioGroupToGpeMappingLength = ARRAY_SIZE (mPchLpGpioGroupToGpeMapping);
+ } else {
+ *GpioGroupToGpeMapping = mPchHGpioGroupToGpeMapping;
+ *GpioGroupToGpeMappingLength = ARRAY_SIZE (mPchHGpioGroupToGpeMapping);
+ }
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.c
new file mode 100644
index 0000000000..2f9b6a7e6f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi14.c
@@ -0,0 +1,67 @@
+/** @file
+ This file contains functions for PCH DMI SIP14
+
+ 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/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Private/Library/PchDmiLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchRegsDmi.h>
+#include <Register/PchRegsDmi14.h>
+#include <Register/PchRegsPcr.h>
+
+/**
+ This function checks if DMI SIP14 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi14Locked (
+ VOID
+ )
+{
+ return ((PchPcrRead32 (PID_DMI, R_PCH_DMI14_PCR_DMIC) & B_PCH_DMI14_PCR_DMIC_SRL) != 0);
+}
+
+/**
+ Enable PCIe Relaxed Order for DMI SIP14
+**/
+VOID
+PchDmi14EnablePcieRelaxedOrder (
+ VOID
+ )
+{
+ //
+ // Enable Forced Relaxed Ordering to always allow downstream completions to pass posted writes.
+ // Set Completion Relaxed Ordering Attribute Override Value
+ // and Completion Relaxed Ordering Attribute Override Enable
+ //
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI14_PCR_2314, ~0u, (BIT31 | BIT7));
+}
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi14SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ )
+{
+ *SrlRegMask = B_PCH_DMI14_PCR_DMIC_SRL;
+ *SrlRegOffset = R_PCH_DMI14_PCR_DMIC;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.c
new file mode 100644
index 0000000000..c711b3de39
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmi15.c
@@ -0,0 +1,113 @@
+/** @file
+ This file contains functions for PCH DMI SIP15
+
+ 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/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Private/Library/PchDmiLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchRegsDmi.h>
+#include <Register/PchRegsDmi15.h>
+#include <Register/PchRegsPcr.h>
+
+/**
+ This function checks if DMI SIP15 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi15Locked (
+ VOID
+ )
+{
+ return ((PchPcrRead32 (PID_DMI, R_PCH_DMI15_PCR_MPC) & B_PCH_DMI15_PCR_MPC_SRL) != 0);
+}
+
+/**
+ Set DMI thermal throttling to recommended configuration.
+ It's intended only for P-DMI SIP15.
+**/
+VOID
+PchDmi15SetRecommendedThermalThrottling (
+ VOID
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ ///
+ /// DMI recommended Thermal Sensor Target Width
+ /// is the HW default configuration:
+ /// - Thermal Sensor 3 Target Width: 0 (x1)
+ /// - Thermal Sensor 2 Target Width: 1 (x2)
+ /// - Thermal Sensor 1 Target Width: 2 (x4)
+ /// - Thermal Sensor 0 Target Width: 3 (x8)
+ /// Enable Thermal Sensor Autonomous Width
+ ///
+ Data32And = (UINT32)~(B_PCH_DMI15_PCR_UPHWAWC_TS3TW | B_PCH_DMI15_PCR_UPHWAWC_TS2TW |
+ B_PCH_DMI15_PCR_UPHWAWC_TS1TW | B_PCH_DMI15_PCR_UPHWAWC_TS0TW);
+ Data32Or = (0 << N_PCH_DMI15_PCR_UPHWAWC_TS3TW) |
+ (1 << N_PCH_DMI15_PCR_UPHWAWC_TS2TW) |
+ (2 << N_PCH_DMI15_PCR_UPHWAWC_TS1TW) |
+ (3 << N_PCH_DMI15_PCR_UPHWAWC_TS0TW) |
+ B_PCH_DMI15_PCR_UPHWAWC_TSAWEN;
+
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI15_PCR_UPHWAWC, Data32And, Data32Or);
+}
+
+/**
+ Set DMI thermal throttling to custom configuration.
+ This function will configure Thermal Sensor 0/1/2/3 TargetWidth and set
+ DMI Thermal Sensor Autonomous Width Enable.
+ It's intended only for P-DMI SIP15.
+
+ @param[in] DmiThermalThrottling DMI Thermal Throttling structure.
+**/
+VOID
+PchDmi15SetCustomThermalThrottling (
+ IN DMI_THERMAL_THROTTLING DmiThermalThrottling
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ ///
+ /// DMI Throttling action
+ ///
+ Data32And = (UINT32)~(B_PCH_DMI15_PCR_UPHWAWC_TS3TW | B_PCH_DMI15_PCR_UPHWAWC_TS2TW |
+ B_PCH_DMI15_PCR_UPHWAWC_TS1TW | B_PCH_DMI15_PCR_UPHWAWC_TS0TW);
+ Data32Or = (DmiThermalThrottling.ThermalSensor3TargetWidth << N_PCH_DMI15_PCR_UPHWAWC_TS3TW) |
+ (DmiThermalThrottling.ThermalSensor2TargetWidth << N_PCH_DMI15_PCR_UPHWAWC_TS2TW) |
+ (DmiThermalThrottling.ThermalSensor1TargetWidth << N_PCH_DMI15_PCR_UPHWAWC_TS1TW) |
+ (DmiThermalThrottling.ThermalSensor0TargetWidth << N_PCH_DMI15_PCR_UPHWAWC_TS0TW) |
+ B_PCH_DMI15_PCR_UPHWAWC_TSAWEN;
+
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI15_PCR_UPHWAWC, Data32And, Data32Or);
+}
+
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi15SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ )
+{
+ *SrlRegMask = B_PCH_DMI15_PCR_MPC_SRL;
+ *SrlRegOffset = R_PCH_DMI15_PCR_MPC;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiLib.c
new file mode 100644
index 0000000000..f1b2867659
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiLib.c
@@ -0,0 +1,569 @@
+/** @file
+ PCH DMI 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/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Private/Library/PchDmiLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <Register/PchRegsPcr.h>
+#include <Register/PchRegsDmi.h>
+
+#include "PchDmi14.h"
+#include "PchDmi15.h"
+
+/**
+ This function checks if DMI Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmiLocked (
+ VOID
+ )
+{
+ if (IsPchWithPdmi ()) {
+ return IsPchDmi15Locked ();
+ } else {
+ return IsPchDmi14Locked ();
+ }
+}
+
+/**
+ Backward DMI library API compatibility
+ ACPI base address programming is done in PSF
+
+ @param[in] Address Address for ACPI base.
+
+ @retval EFI_UNSUPPORTED NOT supported programming.
+**/
+EFI_STATUS
+PchDmiSetAcpiBase (
+ IN UINT16 Address
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Backward DMI library API compatibility
+ PWRMBASE is a standard BAR and doesn't require
+ additional DMI base decoding programming
+
+ @param[in] Address Address for PWRM base.
+
+ @retval EFI_UNSUPPORTED NOT supported programming.
+**/
+EFI_STATUS
+PchDmiSetPwrmBase (
+ IN UINT32 Address
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Set PCH TCO base address decoding 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
+PchDmiSetTcoBase (
+ IN UINT16 Address
+ )
+{
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [SMBUS PCI offset 50h[15:5], 1].
+ //
+ PchPcrWrite16 (
+ PID_DMI, R_PCH_DMI_PCR_TCOBASE,
+ (Address | BIT1)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH TCO base address.
+
+ @retval Address Address of TCO base address.
+**/
+UINT16
+PchDmiGetTcoBase (
+ VOID
+ )
+{
+ //
+ // Read "TCO Base Address" PCR[DMI] + 2778h[15:5]
+ //
+ return (PchPcrRead16 (PID_DMI, R_PCH_DMI_PCR_TCOBASE) & B_PCH_DMI_PCR_TCOBASE_TCOBA);
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range decoding in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+ @param[in] RangeIndex Index of choosen range
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcGenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length,
+ IN UINT32 RangeIndex
+ )
+{
+ UINT32 Data32;
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Data32 = (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_LPC_CFG_GENX_DEC_EN;
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, (UINT16) (R_PCH_DMI_PCR_LPCLGIR1 + RangeIndex * 4),
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH eSPI eSPI CS1# generic IO range decoding 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_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1GenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length
+ )
+{
+ UINT32 Data32;
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Data32 = (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_LPC_CFG_GENX_DEC_EN;
+ //
+ // Program eSPI Generic IO Range #, PCR[DMI] + 27BCh to the same value programmed in eSPI PCI Offset A4h.
+ //
+ PchPcrWrite32 (PID_DMI, R_PCH_DMI_PCR_SEGIR, Data32);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear PCH LPC/eSPI generic IO range decoding in DMI
+
+ @param[in] RangeIndex Index of chosen range
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiClearLpcGenIoRange (
+ IN UINTN RangeIndex
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, (UINT16) (R_PCH_DMI_PCR_LPCLGIR1 + RangeIndex * 4),
+ 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear PCH eSPI CS1# generic IO range decoding in DMI
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiClearEspiCs1GenIoRange (
+ VOID
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 27BCh to the same value programmed in eSPI PCI Offset A4h.
+ //
+ PchPcrWrite32 (PID_DMI, R_PCH_DMI_PCR_SEGIR, 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcMemRange (
+ IN UINT32 Address
+ )
+{
+ if (IsPchDmiLocked ()) {
+ DEBUG ((DEBUG_ERROR, "PchDmiSetLpcMemRange Error. DMI is locked.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_DMI_PCR_LPCGMR,
+ (Address | B_LPC_CFG_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH eSPI CS1# memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1MemRange (
+ IN UINT32 Address
+ )
+{
+ if (IsPchDmiLocked ()) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRange2Set Error. DMI is locked.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC Memory Range, PCR[DMI] + 27C0h to the same value programmed in eSPI PCI Offset A8h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_DMI_PCR_SEGMR,
+ (Address | B_LPC_CFG_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if Boot BIOS Strap is set for SPI.
+
+ @retval TRUE Boot BIOS Strap set for SPI
+ @retval FALSE Boot BIOS Strap set for LPC/eSPI
+**/
+BOOLEAN
+PchDmiIsBootBiosStrapSetForSpi (
+ VOID
+ )
+{
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ return ((PchPcrRead32 (PID_DMI, R_PCH_DMI_PCR_GCS) & B_PCH_DMI_PCR_BBS) != B_PCH_DMI_PCR_BBS);
+}
+
+/**
+ Set PCH BIOS range decoding in DMI
+ 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
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetBiosDecodeEnable (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCBDE, BiosDecodeEnable);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges in DMI
+ 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
+PchDmiSetLpcIoDecodeRanges (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMI is not locked.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCIOD, LpcIoDecodeRanges);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO enable decoding in DMI
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcIoEnable (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMI is not locked.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2774h[15:0] to the same value programmed in LPC/eSPI PCI offset 82h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCIOE, LpcIoEnableDecoding);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port in DMI
+
+ @param[in] RpNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchDmiSetIoPort80Decode (
+ IN UINTN RpNumber
+ )
+{
+ UINT16 DmiRpDestinationId;
+ PSF_PORT_DEST_ID PsfRpDestinationId;
+
+ if (IsPchDmiLocked ()) {
+ DEBUG ((DEBUG_ERROR, "PchIoPort80DecodeSet Error. DMI is locked.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// IO port 80h is typically used by decoder/LED hardware for debug purposes.
+ /// By default PCH will forward IO port 80h cycles to LPC bus. The Reserved Page Route (RPR) bit
+ /// of General Control and Status register, located at PCR[DMI] + 274Ch[11] , allows software to
+ /// re-direct IO port 80h cycles to PCIe bus so that a target (for example, a debug card) on
+ /// PCIe bus can receive and claim these cycles.
+ /// The "RPR Destination ID", PCR[DMI] + 274Ch[31:16] need to be set accordingly to point
+ /// to the root port that decode this range. Reading from Port 80h may not return valid values
+ /// if the POST-card itself do not shadow the writes. Unlike LPC, PCIe does not shadow the Port 80 writes.
+ ///
+ PsfRpDestinationId = PsfPcieDestinationId ((UINT32)RpNumber);
+
+ DmiRpDestinationId = (UINT16)((0x2 << 12) |
+ (PsfRpDestinationId.Fields.PsfId << 8) |
+ (PsfRpDestinationId.Fields.PortGroupId << 7) |
+ (PsfRpDestinationId.Fields.PortId << 3) |
+ PsfRpDestinationId.Fields.ChannelId);
+
+ //
+ // Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_GCS + 2, DmiRpDestinationId);
+ //
+ // Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'.
+ // Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ //
+ PchPcrAndThenOr8 (PID_DMI, R_PCH_DMI_PCR_GCS + 1, 0xFF, (B_PCH_DMI_PCR_RPR >> 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set DMI thermal throttling to recommended configuration.
+ It's intended only for P-DMI.
+**/
+VOID
+PchDmiSetRecommendedThermalThrottling (
+ VOID
+ )
+{
+ if (IsPchWithPdmi ()) {
+ PchDmi15SetRecommendedThermalThrottling ();
+ }
+}
+
+/**
+ Set DMI thermal throttling to custom configuration.
+ This function will configure Thermal Sensor 0/1/2/3 TargetWidth and set
+ DMI Thermal Sensor Autonomous Width Enable.
+ It's intended only for P-DMI.
+
+ @param[in] DmiThermalThrottling DMI Thermal Throttling structure.
+**/
+VOID
+PchDmiSetCustomThermalThrottling (
+ IN DMI_THERMAL_THROTTLING DmiThermalThrottling
+ )
+{
+ if (IsPchWithPdmi ()) {
+ PchDmi15SetCustomThermalThrottling (DmiThermalThrottling);
+ }
+}
+
+/**
+ Determines where to send the reserved page registers
+ Accesses to the I/O ranges 80h - 8Fh will be forwarded to PCIe Root Port
+ with the destination ID specified in GCS.RPRDID using DMI source decode.
+**/
+VOID
+PchDmiSetReservedPageRegToPcieRootPort (
+ VOID
+ )
+{
+ PchPcrAndThenOr8 (
+ PID_DMI, R_PCH_DMI_PCR_GCS + 1,
+ (UINT8) ~0,
+ (UINT8) (B_PCH_DMI_PCR_RPR >> 8)
+ );
+}
+
+/**
+ Determines where to send the reserved page registers
+ DMI will not perform source decode on the I/O ranges 80h - 8Fh. The cycles hitting these ranges will
+ end up in P2SB which will then forward the cycle to LPC or eSPI through IOSF Sideband.
+**/
+VOID
+PchDmiSetReservedPageRegToLpc (
+ VOID
+ )
+{
+ PchPcrAndThenOr8 (
+ PID_DMI, R_PCH_DMI_PCR_GCS + 1,
+ (UINT8) (~(B_PCH_DMI_PCR_RPR >> 8)),
+ 0
+ );
+}
+
+/**
+ uCode Patch Region Enable (UPRE). Enables memory access targeting the uCode patch region (0xFEF00000 to 0xFEFFFFFF)
+ to be forwarded to SPI Flash. This can only be set if the boot flash is on SPI.
+**/
+VOID
+PchDmiEnableUCodePatchRegion (
+ VOID
+ )
+{
+ ///
+ /// Setup "uCode Patch Region Enable", PCR [DMI] + 2748h[0] to '0b'
+ ///
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI_PCR_UCPR, (UINT32) ~B_PCH_DMI_PCR_UCPR_UPRE, 0);
+}
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c
new file mode 100644
index 0000000000..9778c9a252
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c
@@ -0,0 +1,79 @@
+/** @file
+ PCH DMI library with S3 boot script support.
+
+ 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 <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/PchRegsPcr.h>
+#include <Register/PchRegsDmi.h>
+
+#include "PchDmi14.h"
+#include "PchDmi15.h"
+
+/**
+ Configure PCH DMI Lock
+**/
+VOID
+PchDmiSetLockWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT16 Address;
+
+ Data32And = 0xFFFFFFFF;
+ if (IsPchWithPdmi ()) {
+ PchDmi15SrlRegData (&Address, &Data32Or);
+ } else {
+ PchDmi14SrlRegData (&Address, &Data32Or);
+ }
+
+ PchPcrAndThenOr32 (
+ PID_DMI, Address,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, Address,
+ &Data32Or,
+ &Data32And
+ );
+}
+
+/**
+ Set BIOS interface Lock-Down
+**/
+VOID
+PchDmiSetBiosLockDownWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Set BIOS Lock-Down (BILD)
+ // When set, prevents GCS.BBS from being changed
+ //
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_DMI_PCR_BILD;
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI_PCR_GCS, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_DMI_PCR_GCS,
+ &Data32Or,
+ &Data32And
+ );
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PchInitCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
new file mode 100644
index 0000000000..14bd51ec43
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
@@ -0,0 +1,221 @@
+/** @file
+ Pch common library for PCH INIT PEI/DXE/SMM modules
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/PchRegsPcie.h>
+
+extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[];
+extern CONST UINT32 mPchPcieControllerInfoSize;
+
+#define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us = 1ms timeout for USB3 PortSC PLS polling
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ )
+{
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].Pid;
+}
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ )
+{
+ return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS));
+}
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN ControllerIndex;
+ ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS;
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].DevNum;
+}
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT8 Response;
+ UINT16 Fid;
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigRead,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG((DEBUG_ERROR,"Sideband Read Failed of RpIndex %d Offset 0x%x. Device = %d Fid = 0x%x\n",RpIndex, Offset, RpDevice, Fid));
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT32 Data32;
+ UINT8 Response;
+ UINT16 Fid;
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Status = PchSbiRpPciRead32 (RpIndex, Offset, &Data32);
+ if (Status == EFI_SUCCESS) {
+ Data32 &= Data32And;
+ Data32 |= Data32Or;
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigWrite,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ &Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG((DEBUG_ERROR,"Sideband Write Failed of RpIndex %d Offset 0x%x. Device = %d Fid = 0x%x\n",RpIndex, Offset, RpDevice, Fid));
+ ASSERT (FALSE);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintPciSegmentBase Pci segment base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintPciRegisters (
+ IN UINT64 PrintPciSegmentBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", PciSegmentRead8 (PrintPciSegmentBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..dcb43285b7
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
@@ -0,0 +1,2407 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PchPciExpressHelpersLibrary.h"
+#include <Library/BaseMemoryLib.h>
+
+#define ASPM_L1_NO_LIMIT 0xFF
+#define ASPM_L0s_NO_LIMIT 0x7
+
+#define LINK_RETRAIN_WAIT_TIME 1000 // microseconds
+//
+// This structure conveniently keeps segment:bus:device:function coordinates of a PCIe device
+// in a single variable. PcieCap is offset to PCI Express capabilities. Having it cached together
+// with coordinates is an optimization feature, because code in this file uses it a lot
+//
+typedef struct {
+ UINT32 Seg : 8;
+ UINT32 Bus : 8;
+ UINT32 Dev : 5;
+ UINT32 Func : 3;
+ UINT32 PcieCap : 8;
+} SBDF;
+
+typedef struct {
+ UINT32 MaxSnoopLatencyValue : 10;
+ UINT32 MaxSnoopLatencyScale : 3;
+ UINT32 MaxSnoopLatencyRequirement : 1;
+ UINT32 MaxNoSnoopLatencyValue : 10;
+ UINT32 MaxNoSnoopLatencyScale : 3;
+ UINT32 MaxNoSnoopLatencyRequirement : 1;
+ UINT32 ForceOverride : 1;
+} LTR_OVERRIDE;
+
+typedef struct {
+ UINT32 MaxSnoopLatencyValue : 10;
+ UINT32 MaxSnoopLatencyScale : 3;
+ UINT32 MaxNoSnoopLatencyValue : 10;
+ UINT32 MaxNoSnoopLatencyScale : 3;
+} LTR_LIMIT;
+
+#define MSLV_BIT_OFFSET 0
+#define MSLS_BIT_OFFSET 10
+#define MNSLV_BIT_OFFSET 13
+#define MNSLS_BIT_OFFSET 23
+
+
+typedef struct {
+ UINT32 Size;
+ const PCH_PCIE_DEVICE_OVERRIDE* Table;
+} OVERRIDE_TABLE;
+
+typedef enum {
+ DevTypePci,
+ DevTypePcieEndpoint,
+ DevTypePcieUpstream,
+ DevTypePcieDownstream,
+ DevTypeMax
+} PCI_DEV_TYPE;
+
+//
+// This structure keeps in one place all data relevant to enabling L0s and L1.
+// L0s latencies are encoded in the same way as in hardware registers. The only operation
+// that will be performed on them is comparison
+// L1 latencies are decoded to microseconds, because they will be used in subtractions and additions
+//
+typedef struct {
+ UINT32 L0sSupported : 1;
+ UINT32 L1Supported : 1;
+ UINT32 L0sAcceptableLatency : 3; // encoded as in hardware register
+ UINT32 L1AcceptableLatencyUs : 8; // decoded to microseconds
+ UINT32 LinkL0sExitLatency : 3; // encoded as in hardware register
+ UINT32 LinkL1ExitLatencyUs : 8; // decoded to microseconds
+} ASPM_CAPS;
+
+typedef struct {
+ UINT32 AspmL11 : 1;
+ UINT32 AspmL12 : 1;
+ UINT32 PmL11 : 1;
+ UINT32 PmL12 : 1;
+ UINT32 Cmrt : 8; // Common Mode Restore Time
+ UINT32 TpoScale : 2; // T power_on scale
+ UINT32 TpoValue : 6; // T power_on value
+} L1SS_CAPS;
+
+#define MAX_SBDF_TABLE_SIZE 50 //arbitrary table size; big enough to accomodate even full length TBT chain.
+
+typedef struct {
+ UINT32 Count;
+ SBDF Entry [MAX_SBDF_TABLE_SIZE];
+} SBDF_TABLE;
+
+/**
+ Converts device's segment:bus:device:function coordinates to flat address
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @retval address of device's PCI cfg space
+**/
+STATIC
+UINT64
+SbdfToBase (
+ SBDF Sbdf
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (Sbdf.Seg, Sbdf.Bus, Sbdf.Dev, Sbdf.Func, 0);
+}
+
+/**
+ Get PCIe port number for enabled port.
+ @param[in] RpBase Root Port pci segment base address
+ @retval Root Port number (1 based)
+**/
+UINT32
+PciePortNum (
+ IN UINT64 RpBase
+ )
+{
+ return PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) >> N_PCH_PCIE_CFG_LCAP_PN;
+}
+
+/**
+ Get PCIe root port index
+ @param[in] RpBase Root Port pci segment base address
+ @retval Root Port index (0 based)
+**/
+UINT32
+PciePortIndex (
+ IN UINT64 RpBase
+ )
+{
+ return PciePortNum (RpBase) - 1;
+}
+
+/**
+ Translate PCIe Port/Lane pair to 0-based PCIe lane number.
+
+ @param[in] RpIndex Root Port index
+ @param[in] RpLane Root Port Lane (0-3)
+
+ @retval PCIe lane number (0-based)
+**/
+UINT32
+PchPciePhysicalLane (
+ UINT32 RpIndex,
+ UINT32 RpLane
+ )
+{
+ UINT32 ControllerIndex;
+ UINT32 ControllerLane;
+
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+ ASSERT (((RpIndex % 4) + RpLane) < 4);
+
+ ControllerIndex = (RpIndex / 4);
+ ControllerLane = (RpIndex % 4) + RpLane;
+ if (IsPcieLaneReversalEnabled (RpIndex)) {
+ ControllerLane = 3 - ControllerLane;
+ }
+ return (ControllerIndex * 4) + ControllerLane;
+}
+
+/**
+ Checks if lane reversal is enabled on a given root port
+
+ @param[in] RpIndex Root port index (0-based)
+
+ @retval TRUE if lane reversal is enbabled, FALSE otherwise
+**/
+BOOLEAN
+IsPcieLaneReversalEnabled (
+ IN UINT32 RpIndex
+ )
+{
+ UINT32 Data32;
+ PchSbiRpPciRead32 (PchGetPcieFirstPortIndex (RpIndex), R_PCH_PCIE_CFG_PCIEDBG, &Data32);
+ return !! (Data32 & B_PCH_PCIE_CFG_PCIEDBG_LR);
+}
+
+/**
+ Calculates the index of the first port on the same controller.
+
+ @param[in] RpIndex Root Port Number (0-based)
+
+ @retval Index of the first port on the first controller.
+**/
+UINT32
+PchGetPcieFirstPortIndex (
+ IN UINT32 RpIndex
+ )
+{
+ UINT32 ControllerIndex;
+
+ ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS;
+ return ControllerIndex * PCH_PCIE_CONTROLLER_PORTS;
+}
+
+/*
+ Returns Tpower_on capability of device
+
+ @param[in] DeviceBase device's PCI segment base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+
+ @retval structure containing Tpoweron scale and value
+*/
+T_POWER_ON
+GetTpoCapability (
+ UINT64 DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssCapabilities;
+
+ L1ssCapabilities = PciSegmentRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ Tpo.Scale = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ Tpo.Value = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ return Tpo;
+}
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+
+ @param[in] TpoScale T power on scale
+ @param[in] TpoValue T power on value
+
+ @retval number of microseconds
+*/
+UINT32
+TpoToUs (
+ UINT32 TpoScale,
+ UINT32 TpoValue
+ )
+{
+ static const UINT8 TpoScaleMultiplier[] = {2, 10, 100};
+
+ ASSERT (TpoScale < TpoScaleMax);
+ if (TpoScale >= TpoScaleMax) {
+ return 0;
+ }
+ return (TpoScaleMultiplier[TpoScale] * TpoValue);
+}
+
+/**
+ Finds the Offset to a given Capabilities ID
+ Each capability has an ID and a pointer to next Capability, so they form a linked list.
+ This function walks the list of Capabilities present in device's pci cfg. If requested capability
+ can be found, its offset is returned.
+ If the capability can't be found or if device doesn't exist, function returns 0
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] DeviceBase device's base address
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found (this includes situation where device doesn't exit)
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieBaseFindCapId (
+ IN UINT64 DeviceBase,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINT16 Data16;
+ //
+ // We do not explicitly check if device exists to save time and avoid unnecessary PCI access
+ // If the device doesn't exist, check for CapHeaderId != 0xFF will fail and function will return offset 0
+ //
+ if ((PciSegmentRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
+ ///
+ /// Function has no capability pointer
+ ///
+ return 0;
+ } else {
+ ///
+ /// Check the header layout to determine the Offset of Capabilities Pointer Register
+ ///
+ if ((PciSegmentRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
+ ///
+ /// If CardBus bridge, start at Offset 0x14
+ ///
+ CapHeaderOffset = EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR;
+ } else {
+ ///
+ /// Otherwise, start at Offset 0x34
+ ///
+ CapHeaderOffset = PCI_CAPBILITY_POINTER_OFFSET;
+ }
+ ///
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = PciSegmentRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ Data16 = PciSegmentRead16 (DeviceBase + CapHeaderOffset);
+ CapHeaderId = (UINT8)(Data16 & 0xFF);
+ if (CapHeaderId == CapId) {
+ if (CapHeaderOffset > PCI_MAXLAT_OFFSET) {
+ ///
+ /// Return valid capability offset
+ ///
+ DEBUG ((DEBUG_INFO,"CapId %x,%x->%02x\n", ((UINT32)(DeviceBase&0xFFFFF000)>>12), CapId, CapHeaderOffset));
+ return CapHeaderOffset;
+ } else {
+ ASSERT ((FALSE));
+ return 0;
+ }
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved
+ /// and must be implemented as 00b although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = (UINT8)(Data16 >> 8);
+ }
+ return 0;
+ }
+}
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Segment Pci Segment Number
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT64 DeviceBase;
+
+ DEBUG ((DEBUG_INFO,"PcieFindCapId () SBDF %0x: %0x: %0x :%0x, CapId = %0x \n", Segment, Bus, Device, Function, CapId));
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+ return PcieBaseFindCapId (DeviceBase, CapId);
+}
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Reporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] DeviceBase device base address
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieBaseFindExtendedCapId (
+ IN UINT64 DeviceBase,
+ IN UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+ ///
+ /// Start to search at Offset 0x100
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = R_PCH_PCIE_CFG_EXCAP_OFFSET;
+ while (CapHeaderOffset != 0 && CapHeaderId != MAX_UINT16) {
+ CapHeaderId = PciSegmentRead16 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers are reserved and must be implemented as 00b
+ /// although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = (PciSegmentRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Reporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Segment Pci Segment Number
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ UINT64 DeviceBase;
+
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+ return PcieBaseFindExtendedCapId (DeviceBase, CapId);
+}
+
+/**
+ This function checks whether PHY lane power gating is enabled on the port.
+
+ @param[in] RpBase Root Port base address
+
+ @retval TRUE PHY power gating is enabled
+ @retval FALSE PHY power gating disabled
+**/
+STATIC
+BOOLEAN
+PcieIsPhyLanePgEnabled (
+ IN UINT64 RpBase
+ )
+{
+ UINT32 Data32;
+ Data32 = PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL);
+ return (Data32 & B_PCH_PCIE_CFG_PCIEPMECTL_DLSULPPGE) != 0;
+}
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @retval Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINT64 RpBase
+ )
+{
+ return PciSegmentRead16 (RpBase + R_PCH_PCIE_CFG_LSTS) & B_PCIE_LSTS_CLS;
+}
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @retval Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINT64 RpBase
+ )
+{
+ return PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) & B_PCIE_LCAP_MLS;
+}
+
+/**
+ Get max payload size supported by device.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @retval Max payload size, encoded in the same way as in register (0=128b, 1=256b, etc)
+**/
+STATIC
+UINT8
+GetMps (
+ SBDF Sbdf
+ )
+{
+ return (PciSegmentRead16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS);
+}
+
+/**
+ Sets Maximum Payload Size to be used by device
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in] Mps Max payload size, encoded in the same way as in register (0=128b, 1=256b, etc)
+**/
+STATIC
+VOID
+SetMps (
+ SBDF Sbdf,
+ UINT8 Mps
+ )
+{
+ PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCTL_OFFSET, (UINT16) ~B_PCIE_DCTL_MPS, Mps << N_PCIE_DCTL_MPS);
+}
+
+/**
+ Checks if given PCI device is capable of Latency Tolerance Reporting
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval TRUE if yes
+**/
+STATIC
+BOOLEAN
+IsLtrCapable (
+ SBDF Sbdf
+ )
+{
+ if (Sbdf.PcieCap == 0) {
+ return FALSE;
+ }
+ return !!(PciSegmentRead32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCAP2_OFFSET) & B_PCIE_DCAP2_LTRMS);
+}
+
+/**
+ Enables LTR feature in given device
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+**/
+STATIC
+VOID
+EnableLtr (
+ SBDF Sbdf
+ )
+{
+ if (Sbdf.PcieCap == 0) {
+ return;
+ }
+ PciSegmentOr32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+}
+
+/**
+ Checks if PCI device at given address exists
+
+ @param[in] Base device's base address
+
+ @retval TRUE if exists
+**/
+BOOLEAN
+IsDevicePresent (
+ UINT64 Base
+ )
+{
+ if (PciSegmentRead16 (Base) == 0xFFFF) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Returns information about type of device.
+
+ @param[out] Sbdf device's segment:bus:device:function coordinates
+ @retval one of: not a PCIe device (legacy PCI), PCIe endpoint, PCIe upstream port or PCIe downstream port (including rootport)
+**/
+STATIC
+PCI_DEV_TYPE
+GetDeviceType (
+ SBDF Sbdf
+ )
+{
+ UINT8 DeviceType;
+
+ if (Sbdf.PcieCap == 0) {
+ return DevTypePci;
+ }
+ DeviceType = (UINT8) ((PciSegmentRead16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+ if (DeviceType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) {
+ return DevTypePcieUpstream;
+ } else if (DeviceType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT || DeviceType == PCIE_DEVICE_PORT_TYPE_ROOT_PORT) {
+ return DevTypePcieDownstream;
+ } else {
+ return DevTypePcieEndpoint;
+ }
+}
+
+/**
+ Initializes Dev:Func numbers for use in FindNextPcieChild or FindNextLegalSbdf functions.
+
+ @param[out] Sbdf device's segment:bus:device:function coordinates
+**/
+STATIC
+VOID
+InitChildFinder (
+ OUT SBDF *Sbdf
+ )
+{
+ //
+ // Initialize Dev/Func to maximum values, so that when FindNextLegalSbdf ()
+ // is called on those input parameters, it will return 1st legal address (Dev 0 Func 0).
+ //
+ Sbdf->Dev = PCI_MAX_DEVICE;
+ Sbdf->Func = PCI_MAX_FUNC;
+}
+
+/**
+ Checks the device is a bridge and has non-zero secondary bus number assigned.
+ If so, it returns TRUE and initializes ChildSbdf with such values that
+ allow searching for devices on the secondary bus.
+ ChildSbdf will be mangled even if this function returns FALSE.
+
+ Legal bus assignment is assumed. This function doesn't check subordinate bus numbers of
+ the the device it was called on or any bridges between it and root complex
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[out] ChildSbdf SBDF initialized in such way that calling FindNextPcieChild( ) on it will find all children devices
+
+ @retval TRUE if device is a bridge and has a bus behind it; FALSE otherwise
+**/
+STATIC
+BOOLEAN
+HasChildBus (
+ SBDF Sbdf,
+ SBDF *ChildSbdf
+ )
+{
+ UINT32 Data32;
+ UINT64 Base;
+ UINT8 SecondaryBus;
+
+ ChildSbdf->Seg = Sbdf.Seg;
+ InitChildFinder (ChildSbdf);
+
+ Base = SbdfToBase (Sbdf);
+
+ if (PciSegmentRead8 (Base + R_PCI_BCC_OFFSET) != PCI_CLASS_BRIDGE) {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02:%02:%02: no\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return FALSE;
+ }
+ Data32 = PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
+ SecondaryBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8);
+ ChildSbdf->Bus = SecondaryBus;
+ if (SecondaryBus == 0) {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02x:%02x:%02x: no\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return FALSE;
+ } else {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02x:%02x:%02x: yes, %x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, SecondaryBus));
+ return TRUE;
+ }
+}
+
+/**
+ Checks if device is a multifunction device
+ Besides comparing Multifunction bit (BIT7) it checks if contents of HEADER_TYPE register
+ make sense (header != 0xFF) to prevent false positives when called on devices which do not exist
+
+ @param[in] Base device's base address
+
+ @retval TRUE if multifunction; FALSE otherwise
+**/
+BOOLEAN
+IsMultifunctionDevice (
+ UINT64 Base
+ )
+{
+ UINT8 HeaderType;
+ HeaderType = PciSegmentRead8(Base + PCI_HEADER_TYPE_OFFSET);
+ if ((HeaderType == 0xFF) || ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Returns combination of two LTR override values
+ The resulting LTR override separately chooses stricter limits for snoop and nosnoop
+
+ @param[in] LtrA LTR override values to be combined
+ @param[in] LtrB LTR override values to be combined
+
+ @retval LTR override value
+**/
+STATIC
+LTR_OVERRIDE
+CombineLtr (
+ LTR_OVERRIDE LtrA,
+ LTR_OVERRIDE LtrB
+ )
+{
+ UINT64 DecodedLatencyA;
+ UINT64 DecodedLatencyB;
+ LTR_OVERRIDE Result;
+ static UINT32 ScaleEncoding [8] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0};
+
+ DecodedLatencyA = ScaleEncoding[LtrA.MaxSnoopLatencyScale] * LtrA.MaxSnoopLatencyValue;
+ DecodedLatencyB = ScaleEncoding[LtrB.MaxSnoopLatencyScale] * LtrB.MaxSnoopLatencyValue;
+ if ((!LtrB.MaxSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedLatencyB) && LtrA.MaxSnoopLatencyRequirement)) {
+ Result.MaxSnoopLatencyValue = LtrA.MaxSnoopLatencyValue;
+ Result.MaxSnoopLatencyScale = LtrA.MaxSnoopLatencyScale;
+ Result.MaxSnoopLatencyRequirement = LtrA.MaxSnoopLatencyRequirement;
+ } else {
+ Result.MaxSnoopLatencyValue = LtrB.MaxSnoopLatencyValue;
+ Result.MaxSnoopLatencyScale = LtrB.MaxSnoopLatencyScale;
+ Result.MaxSnoopLatencyRequirement = LtrB.MaxSnoopLatencyRequirement;
+ }
+ DecodedLatencyA = ScaleEncoding[LtrA.MaxNoSnoopLatencyScale] * LtrA.MaxNoSnoopLatencyValue;
+ DecodedLatencyB = ScaleEncoding[LtrB.MaxNoSnoopLatencyScale] * LtrB.MaxNoSnoopLatencyValue;
+ if ((!LtrB.MaxNoSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedLatencyB) && LtrA.MaxNoSnoopLatencyRequirement)) {
+ Result.MaxNoSnoopLatencyValue = LtrA.MaxNoSnoopLatencyValue;
+ Result.MaxNoSnoopLatencyScale = LtrA.MaxNoSnoopLatencyScale;
+ Result.MaxNoSnoopLatencyRequirement = LtrA.MaxNoSnoopLatencyRequirement;
+ } else {
+ Result.MaxNoSnoopLatencyValue = LtrB.MaxNoSnoopLatencyValue;
+ Result.MaxNoSnoopLatencyScale = LtrB.MaxNoSnoopLatencyScale;
+ Result.MaxNoSnoopLatencyRequirement = LtrB.MaxNoSnoopLatencyRequirement;
+ }
+ Result.ForceOverride = FALSE;
+ if (LtrA.ForceOverride || LtrB.ForceOverride) {
+ Result.ForceOverride = TRUE;
+ }
+ DEBUG ((DEBUG_INFO, "CombineLtr: A(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ LtrA.MaxSnoopLatencyValue, LtrA.MaxSnoopLatencyScale, LtrA.MaxSnoopLatencyRequirement,
+ LtrA.MaxNoSnoopLatencyValue, LtrA.MaxNoSnoopLatencyScale, LtrA.MaxNoSnoopLatencyRequirement,
+ LtrA.ForceOverride
+ ));
+ DEBUG ((DEBUG_INFO, " : B(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ LtrB.MaxSnoopLatencyValue, LtrB.MaxSnoopLatencyScale, LtrB.MaxSnoopLatencyRequirement,
+ LtrB.MaxNoSnoopLatencyValue, LtrB.MaxNoSnoopLatencyScale, LtrB.MaxNoSnoopLatencyRequirement,
+ LtrB.ForceOverride
+ ));
+ DEBUG ((DEBUG_INFO, " : R(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ Result.MaxSnoopLatencyValue, Result.MaxSnoopLatencyScale, Result.MaxSnoopLatencyRequirement,
+ Result.MaxNoSnoopLatencyValue, Result.MaxNoSnoopLatencyScale, Result.MaxNoSnoopLatencyRequirement,
+ Result.ForceOverride
+ ));
+ return Result;
+}
+
+/**
+ Returns LTR override value for given device
+ The value is extracted from Device Override table. If the device is not found,
+ the returned value will have Requirement bits clear
+
+ @param[in] Base device's base address
+ @param[in] Override device override table
+
+ @retval LTR override value
+**/
+STATIC
+LTR_OVERRIDE
+GetOverrideLtr (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DevId;
+ UINT16 VenId;
+ UINT16 RevId;
+ UINT32 Index;
+ LTR_OVERRIDE ReturnValue = {0};
+
+ VenId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DevId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ RevId = PciSegmentRead16 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieLtrOverride) == PchPcieLtrOverride) &&
+ (Override->Table[Index].VendorId == VenId) &&
+ ((Override->Table[Index].DeviceId == DevId) || (Override->Table[Index].DeviceId == 0xFFFF)) &&
+ ((Override->Table[Index].RevId == RevId) || (Override->Table[Index].RevId == 0xFF))) {
+ if (Override->Table[Index].SnoopLatency & 0x8000) {
+ ReturnValue.MaxSnoopLatencyRequirement = 1;
+ ReturnValue.MaxSnoopLatencyValue = Override->Table[Index].SnoopLatency & 0x3FF;
+ ReturnValue.MaxSnoopLatencyScale = (Override->Table[Index].SnoopLatency & 0x1C00) >> 10;
+ }
+ if (Override->Table[Index].NonSnoopLatency & 0x8000) {
+ ReturnValue.MaxNoSnoopLatencyRequirement = 1;
+ ReturnValue.MaxNoSnoopLatencyValue = Override->Table[Index].NonSnoopLatency & 0x3FF;
+ ReturnValue.MaxNoSnoopLatencyScale = (Override->Table[Index].NonSnoopLatency & 0x1C00) >> 10;
+ }
+ ReturnValue.ForceOverride = Override->Table[Index].ForceLtrOverride;
+ break;
+ }
+ }
+ return ReturnValue;
+}
+
+/**
+ Sets LTR limit in a device.
+
+ @param[in] Base device's base address
+ @param[in] Ltr LTR limit
+**/
+STATIC
+VOID
+SetLtrLimit (
+ UINT64 Base,
+ LTR_LIMIT Ltr
+ )
+{
+ UINT16 LtrCapOffset;
+ UINT16 Data16;
+
+ LtrCapOffset = PcieBaseFindExtendedCapId (Base, R_PCH_PCIE_LTRECH_CID);
+ if (LtrCapOffset == 0) {
+ return;
+ }
+ Data16 = (UINT16)((Ltr.MaxSnoopLatencyValue << N_PCH_PCIE_LTRECH_MSLR_VALUE) | (Ltr.MaxSnoopLatencyScale << N_PCH_PCIE_LTRECH_MSLR_SCALE));
+ PciSegmentWrite16(Base + LtrCapOffset + R_PCH_PCIE_LTRECH_MSLR_OFFSET, Data16);
+
+ Data16 = (UINT16)((Ltr.MaxNoSnoopLatencyValue << N_PCH_PCIE_LTRECH_MNSLR_VALUE) | (Ltr.MaxNoSnoopLatencyScale << N_PCH_PCIE_LTRECH_MNSLR_SCALE));
+ PciSegmentWrite16(Base + LtrCapOffset + R_PCH_PCIE_LTRECH_MNSLR_OFFSET, Data16);
+}
+
+/**
+ Checks if device at given address exists and is a PCI Express device.
+ PCI express devices are distinguished from PCI by having Capability ID 0x10
+ If the device is PCI express then its SDBF structure gets updated with pointer to
+ the PCIe Capability. This is an optimization feature. It greatly decreases the number
+ of bus accesses, since most features configured by this library depend on registers
+ whose location is relative to PCIe capability.
+
+ @param[in,out] Sbdf on entry, segment:bus:device:function coordinates
+ on exit, PcieCap offset is updated
+ @retval TRUE when PCIe device exists; FALSE if it's not PCIe or there's no device at all
+**/
+STATIC
+BOOLEAN
+IsPcieDevice (
+ SBDF *Sbdf
+ )
+{
+ UINT8 PcieCapOffset;
+ UINT64 Base;
+
+ Base = SbdfToBase (*Sbdf);
+
+ if (PciSegmentRead16 (Base) == 0xFFFF) {
+ return FALSE;
+ }
+
+
+ PcieCapOffset = PcieBaseFindCapId (Base, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (PcieCapOffset == 0) {
+ DEBUG ((DEBUG_INFO, "IsPcieDevice %02x:%02x:%02x - legacy\n", Sbdf->Bus, Sbdf->Dev, Sbdf->Func));
+ return FALSE;
+ } else {
+ Sbdf->PcieCap = PcieCapOffset;
+ DEBUG ((DEBUG_INFO, "IsPcieDevice %02x:%02x:%02x - yes\n", Sbdf->Bus, Sbdf->Dev, Sbdf->Func));
+ return TRUE;
+ }
+}
+
+/**
+ Returns TRUE and Dev:Func numbers where a PCIe device could legally be located, or FALSE if there
+ no such coordinates left.
+
+ Segment and Bus fields of SBDF structure are input only and determine which bus will be scanned.
+ This function should be called in a while() loop. It replaces the less efficient method of
+ using nested FOR loops that iterate over all device and function numbers. It is optimized for
+ the amount of bus access. If function0 doesn't exist or doesn't have Multifunction bit set,
+ then higher function numbers are skipped. If parent of this bus is a downstream port, then
+ Device numbers 1-31 get skipped too (there can be only Dev0 behind downstream ports)
+ If device/function number == 0x1F/0x7, this function returns first possible address, that is 0:0
+ Any other device number means Dev:Func contain address of last found child device
+ and this function should search for next one
+
+ @param[in] ParentDevType type of bridge who's partent of this bus
+ @param[in,out] Sbdf On entry: location returned previously from this function
+ Dev:Func value of 1F:07 means search should start from the beginning
+ On exit: if legal Dev:Func combination was found, that Dev:Func is returned
+ otherwise, Dev:Func are initialized to 1F:07 for convenience
+ @retval TRUE when next legal Dev:Func address was found; FALSE otherwise
+**/
+STATIC
+BOOLEAN
+FindNextLegalSbdf (
+ IN PCI_DEV_TYPE ParentDevType,
+ IN OUT SBDF *Sbdf
+ )
+{
+ UINT8 MaxDev;
+ UINT64 Func0Base;
+
+ if (ParentDevType == DevTypePcieEndpoint) {
+ return FALSE;
+ }
+ if (ParentDevType == DevTypePcieUpstream) {
+ MaxDev = PCI_MAX_DEVICE;
+ } else {
+ MaxDev = 0;
+ }
+ Func0Base = PCI_SEGMENT_LIB_ADDRESS (Sbdf->Seg, Sbdf->Bus, Sbdf->Dev, 0, 0);
+ if ((Sbdf->Dev == PCI_MAX_DEVICE) && Sbdf->Func == PCI_MAX_FUNC) {
+ Sbdf->Dev = 0;
+ Sbdf->Func = 0;
+ return TRUE;
+ } else if ((Sbdf->Func == PCI_MAX_FUNC) || (Sbdf->Func == 0 && !IsMultifunctionDevice (Func0Base))) {
+ //
+ // if it's the last function of a device, then return Func0 of new device or FALSE in case there are no more devices
+ //
+ if (Sbdf->Dev == MaxDev) {
+ InitChildFinder (Sbdf);
+ return FALSE;
+ }
+ (Sbdf->Dev)++;
+ Sbdf->Func = 0;
+ return TRUE;
+ } else {
+ (Sbdf->Func)++;
+ return TRUE;
+ }
+}
+
+/**
+ Finds next PCIe (not legacy PCI) device behind given device
+ If device/function number == 0x1F/0x7, this function searches for children from scratch
+ Any other device number means Dev:Func contain address of last found child device
+ and this function should search for next one
+
+ @param[in] ParentDevType type of bridge who's partent of this bus
+ @param[in,out] Sbdf On entry: location returned previously from this function
+ Dev:Func value of 0x1F:0x07 means search should start from the beginning
+ On exit: if PCIe device was found, its SBDF coordinates are returned
+ otherwise, Dev:Func are initialized to 0x1F:0x07 for convenience
+ @retval TRUE when next PCIe device was found; FALSE otherwise
+**/
+STATIC
+BOOLEAN
+FindNextPcieChild (
+ IN PCI_DEV_TYPE ParentDevType,
+ IN OUT SBDF *Sbdf
+ )
+{
+ while ( FindNextLegalSbdf (ParentDevType, Sbdf)) {
+ if (IsPcieDevice (Sbdf)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks device's Slot Clock Configuration
+
+ @param[in] Base device's base address
+
+ @retval TRUE when device uses slot clock, FALSE otherwise
+**/
+BOOLEAN
+GetScc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ )
+{
+ return !!(PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC);
+}
+
+/**
+ Sets Common Clock Configuration bit for given device.
+
+ @param[in] Base device's base address
+**/
+VOID
+EnableCcc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ )
+{
+ PciSegmentOr8 (Base + PcieCapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+}
+
+/**
+ Retrains link behind given device.
+ It only makes sense to call it for downstream ports. If called for upstream port nothing will happen.
+ If WaitUntilDone is TRUE function will wait until link retrain had finished, otherwise it will return immediately.
+ Link must finish retrain before software can access the device on the other side. If it's not going to access it
+ then considerable time can be saved by not waiting here.
+
+ @param[in] Sbdf Device's Segment:Bus:Device:Function coordinates
+ @param[in] WaitUntilDone when TRUE, function waits until link has retrained
+**/
+VOID
+RetrainLink (
+ UINT64 Base,
+ UINT8 PcieCapOffset,
+ BOOLEAN WaitUntilDone
+ )
+{
+ UINT16 LinkTraining;
+ UINT32 TimeoutUs;
+
+ TimeoutUs = LINK_RETRAIN_WAIT_TIME;
+ //
+ // Before triggering link retrain make sure it's not already retraining. Otherwise
+ // settings recently entered in LCTL register might go unnoticed
+ //
+ do {
+ LinkTraining = (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT);
+ TimeoutUs--;
+ } while (LinkTraining && (TimeoutUs != 0));
+
+ PciSegmentOr8 (Base + PcieCapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL);
+
+ TimeoutUs = LINK_RETRAIN_WAIT_TIME;
+ if (WaitUntilDone) {
+ do {
+ LinkTraining = (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT);
+ TimeoutUs--;
+ } while (LinkTraining && (TimeoutUs != 0));
+ }
+}
+
+/**
+ Checks if given device supports Clock Power Management
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+
+ @retval TRUE when device supports it, FALSE otherwise
+**/
+STATIC
+BOOLEAN
+IsCpmSupported (
+ SBDF Sbdf
+ )
+{
+ return !!(PciSegmentRead32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM);
+}
+
+/**
+ Sets Enable Clock Power Management bit for given device
+
+ @param[in] Base device's base address
+**/
+STATIC
+VOID
+EnableCpm (
+ SBDF Sbdf
+ )
+{
+ PciSegmentOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_ECPM);
+}
+
+/**
+ Checks if given device is an IoAPIC
+
+ @param[in] Base device's base address
+
+ @retval TRUE if it's an IoAPIC
+**/
+BOOLEAN
+IsIoApicDevice (
+ UINT64 Base
+ )
+{
+ UINT8 BaseClassCode;
+ UINT8 SubClassCode;
+ UINT8 ProgInterface;
+
+ BaseClassCode = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 2);
+ SubClassCode = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 1);
+ ProgInterface = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET);
+ if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) &&
+ (SubClassCode == PCI_SUBCLASS_PIC) &&
+ ((ProgInterface == PCI_IF_APIC_CONTROLLER) ||
+ (ProgInterface == PCI_IF_APIC_CONTROLLER2))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ There are some devices which support L1 substates, but due to silicon bugs the corresponding register
+ cannot be found by scanning PCIe capabilities. This function checks list of such devices and if one
+ is found, returns its L1ss capability register offset
+
+ @param[in] Base base address of device
+ @param[in] Override table of devices that need override
+ @retval offset to L1ss capability register
+**/
+UINT16
+GetOverrideL1ssCapsOffset (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFF)) {
+ return Override->Table[Index].L1SubstatesCapOffset;
+ }
+ }
+ return 0;
+}
+
+/**
+ There are some devices whose implementation of L1 substates is partially broken. This function checks
+ list of such devices and if one is found, overrides their L1ss-related capabilities
+
+ @param[in] Base base address of device
+ @param[in] Override table of devices that need override
+ @param[in,out] L1ss on entry, capabilities read from register; on exit, capabilities modified according ot override table
+**/
+STATIC
+VOID
+OverrideL1ssCaps (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override,
+ L1SS_CAPS *L1ss
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFF)) {
+ L1ss->PmL12 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_PPL12S);
+ L1ss->PmL11 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_PPL11S);
+ L1ss->AspmL12 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_AL12S);
+ L1ss->AspmL11 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_AL1SS);
+ if (Override->Table[Index].L1sTpowerOnValue != 0) {
+ L1ss->Cmrt = Override->Table[Index].L1sCommonModeRestoreTime;
+ L1ss->TpoScale = Override->Table[Index].L1sTpowerOnScale;
+ L1ss->TpoValue = Override->Table[Index].L1sTpowerOnValue;
+ }
+ return;
+ }
+ }
+}
+
+/**
+ Returns L1 sub states capabilities of a device
+
+ @param[in] Base base address of a device
+
+ @retval L1SS_CAPS structure filled with device's capabilities
+**/
+STATIC
+L1SS_CAPS
+GetL1ssCaps (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ L1SS_CAPS Capabilities = {0};
+ UINT16 PcieCapOffset;
+ UINT32 CapsRegister;
+
+ PcieCapOffset = GetOverrideL1ssCapsOffset (Base, Override);
+ if (PcieCapOffset == 0) {
+ PcieCapOffset = PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID);
+ }
+ if (PcieCapOffset == 0) {
+ return Capabilities;
+ }
+ CapsRegister = PciSegmentRead32 (Base + PcieCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ if (CapsRegister & B_PCIE_EX_L1SCAP_L1PSS) {
+ Capabilities.PmL11 = !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL11S);
+ Capabilities.PmL12 = !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL12S);
+ Capabilities.AspmL12 = !!(CapsRegister & B_PCIE_EX_L1SCAP_AL12S);
+ Capabilities.AspmL11 = !!(CapsRegister & B_PCIE_EX_L1SCAP_AL1SS);
+ Capabilities.Cmrt = (CapsRegister & B_PCIE_EX_L1SCAP_CMRT) >> N_PCIE_EX_L1SCAP_CMRT;
+ Capabilities.TpoValue = (CapsRegister & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ Capabilities.TpoScale = (CapsRegister & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ }
+ OverrideL1ssCaps (Base, Override, &Capabilities);
+ return Capabilities;
+}
+
+/**
+ Returns combination of two sets of L1 substate capabilities
+ Given feature is supported by the link only if both sides support it
+ Time parameters for link (Cmrt and Tpo) depend on the bigger value between two sides
+
+ @param[in] L1ssA L1 substate capabilities of first device
+ @param[in] L1ssB L1 substate capabilities of second device
+
+ @retval Link's L1 substate capabilities
+**/
+STATIC
+L1SS_CAPS
+CombineL1ss (
+ L1SS_CAPS L1ssA,
+ L1SS_CAPS L1ssB
+ )
+{
+ L1SS_CAPS Combined;
+
+ Combined.PmL12 = L1ssA.PmL12 && L1ssB.PmL12;
+ Combined.PmL11 = L1ssA.PmL11 && L1ssB.PmL11;
+ Combined.AspmL12 = L1ssA.AspmL12 && L1ssB.AspmL12;
+ Combined.AspmL11 = L1ssA.AspmL11 && L1ssB.AspmL11;
+ Combined.Cmrt = MAX (L1ssA.Cmrt, L1ssB.Cmrt);
+ if (TpoToUs (L1ssA.TpoScale, L1ssA.TpoValue) > TpoToUs (L1ssB.TpoScale, L1ssB.TpoValue)) {
+ Combined.TpoScale = L1ssA.TpoScale;
+ Combined.TpoValue = L1ssA.TpoValue;
+ } else {
+ Combined.TpoScale = L1ssB.TpoScale;
+ Combined.TpoValue = L1ssB.TpoValue;
+ }
+ return Combined;
+}
+
+/**
+ Configures L1 substate feature in a device
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+ @param[in] L1ss configuration to be programmed
+ @param[in] Override table of devices that require special handling
+**/
+STATIC
+VOID
+SetL1ss (
+ SBDF Sbdf,
+ L1SS_CAPS L1ss,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 PcieCapOffset;
+ UINT32 Ctrl1Register;
+ UINT32 Ctrl2Register;
+ UINT64 Base;
+
+ Base = SbdfToBase(Sbdf);
+ Ctrl1Register = 0;
+ Ctrl2Register = 0;
+
+ PcieCapOffset = GetOverrideL1ssCapsOffset (Base, Override);
+ if (PcieCapOffset == 0) {
+ PcieCapOffset = PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID);
+ }
+ if (PcieCapOffset == 0) {
+ return;
+ }
+ Ctrl1Register |= (L1ss.PmL12 ? B_PCIE_EX_L1SCAP_PPL12S : 0);
+ Ctrl1Register |= (L1ss.PmL11 ? B_PCIE_EX_L1SCAP_PPL11S : 0);
+ Ctrl1Register |= (L1ss.AspmL12 ? B_PCIE_EX_L1SCAP_AL12S : 0);
+ Ctrl1Register |= (L1ss.AspmL11 ? B_PCIE_EX_L1SCAP_AL1SS : 0);
+ if (GetDeviceType (Sbdf) == DevTypePcieDownstream) {
+ Ctrl1Register |= (L1ss.Cmrt << N_PCIE_EX_L1SCAP_CMRT);
+ }
+ ///
+ /// Set L1.2 LTR threshold to 80us (value = 0x50, scale = 0x2 = 1024ns), in accordance to BWG
+ /// BUG BUG BUG It shouldn't be hardcoded, it should consider Tpoweron, otherwise we risk situation where
+ /// BUG BUG BUG threshold is lower than Tpo, and every L1 entry turns into L1.2 entry with no possibility
+ /// BUG BUG BUG to exit before LTR elapses, because exit can take no less than Tpo
+ ///
+ Ctrl1Register |= (0x50 << N_PCIE_EX_L1SCTL1_L12LTRTLV);
+ Ctrl1Register |= (2 << N_PCIE_EX_L1SCTL1_L12LTRTLSV);
+
+ Ctrl2Register |= (L1ss.TpoScale);
+ Ctrl2Register |= (L1ss.TpoValue << N_PCIE_EX_L1SCTL2_POWT);
+
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, 0);
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, Ctrl2Register);
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, Ctrl1Register);
+}
+
+/**
+ Converts L1 latency from enumerated register value to microseconds
+
+ @param[in] L1Latency latency value retrieved from register; see PCIE specification for encoding
+ @retval L1 latency converted to microseconds
+**/
+UINT32
+L1LatencyToUs (
+ UINT32 L1Latency
+ )
+{
+ if (L1Latency < 7) {
+ return 1 * (BIT0 << L1Latency);
+ } else {
+ return ASPM_L1_NO_LIMIT;
+ }
+}
+
+/**
+ Modifies L1 latency by provided value
+
+ @param[in] Aspm Structure that contains ASPM capabilities of a link, including L1 acceptable latency
+ @param[in] Value Value, in microseconds, to be added to L1 acceptable latency. Can be negative.
+ @retval Aspm structure with modified L1 acceptable latency
+**/
+STATIC
+ASPM_CAPS
+PatchL1AcceptableLatency (
+ ASPM_CAPS Aspm,
+ INT8 Value
+ )
+{
+ if (Aspm.L1AcceptableLatencyUs != ASPM_L1_NO_LIMIT) {
+ if (Value > 0) {
+ Aspm.L1AcceptableLatencyUs += Value;
+ } else {
+ if (Aspm.L1AcceptableLatencyUs > (UINT32)(-1*Value)) {
+ Aspm.L1AcceptableLatencyUs = Aspm.L1AcceptableLatencyUs + Value;
+ } else {
+ Aspm.L1AcceptableLatencyUs = 0;
+ }
+ }
+ }
+ return Aspm;
+}
+
+/**
+ Reads ASPM capabilities of a device
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+
+@retval structure containing device's ASPM capabilities
+**/
+STATIC
+ASPM_CAPS
+GetAspmCaps (
+ SBDF Sbdf
+ )
+{
+
+ UINT32 LinkCapRegister;
+ UINT32 DevCapRegister;
+ UINT64 Base;
+ ASPM_CAPS Aspm = {0};
+
+ Base = SbdfToBase (Sbdf);
+
+ LinkCapRegister = PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_LCAP_OFFSET);
+ DevCapRegister = PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_DCAP_OFFSET);
+
+ ///
+ /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit. Don't report L0s support for old devices
+ ///
+ if (DevCapRegister & B_PCIE_DCAP_RBER) {
+ Aspm.L0sSupported = !!(LinkCapRegister & B_PCIE_LCAP_APMS_L0S);
+ }
+ Aspm.L1Supported = !!(LinkCapRegister & B_PCIE_LCAP_APMS_L1);
+
+ Aspm.LinkL0sExitLatency = (LinkCapRegister & B_PCIE_LCAP_EL0) >> N_PCIE_LCAP_EL0;
+ Aspm.LinkL1ExitLatencyUs = L1LatencyToUs( (LinkCapRegister & B_PCIE_LCAP_EL1) >> N_PCIE_LCAP_EL1);
+
+ if (GetDeviceType (Sbdf) == DevTypePcieEndpoint) {
+ Aspm.L0sAcceptableLatency = (DevCapRegister & B_PCIE_DCAP_E0AL) >> N_PCIE_DCAP_E0AL;
+ Aspm.L1AcceptableLatencyUs = L1LatencyToUs( (DevCapRegister & B_PCIE_DCAP_E1AL) >> N_PCIE_DCAP_E1AL);
+ DEBUG ((DEBUG_INFO, "GetAspmCaps %02x:%02x:%02x L0s%c %d:%d L1%c %d:%d\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func,
+ Aspm.L0sSupported?'+':'-', Aspm.LinkL0sExitLatency, Aspm.L0sAcceptableLatency,
+ Aspm.L1Supported?'+':'-', Aspm.LinkL1ExitLatencyUs, Aspm.L1AcceptableLatencyUs));
+ } else {
+ Aspm.L0sAcceptableLatency = ASPM_L0s_NO_LIMIT;
+ Aspm.L1AcceptableLatencyUs = ASPM_L1_NO_LIMIT;
+ DEBUG ((DEBUG_INFO, "GetAspmCaps %02x:%02x:%02x L0s%c %d:x L1%c %d:x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func,
+ Aspm.L0sSupported?'+':'-', Aspm.LinkL0sExitLatency,
+ Aspm.L1Supported?'+':'-', Aspm.LinkL1ExitLatencyUs));
+ }
+ return Aspm;
+}
+
+/**
+ Get ASPM L0s and L1 override of given device.
+
+ @param[in] Sbdf Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in,out] MyAspm Current device's ASPM capabilities structure
+ @param[in] Override Pch Pcie devices OverrideTable
+**/
+STATIC
+VOID
+GetOverrideAspm (
+ SBDF Sbdf,
+ ASPM_CAPS *MyAspm,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+ UINT64 Base;
+
+ Base = SbdfToBase (Sbdf);
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFF)) {
+ DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, original L0sSupported = 0x%x, L1Supported = 0x%x\n",
+ Sbdf.Bus, Sbdf.Dev, Sbdf.Func, MyAspm->L0sSupported, MyAspm->L1Supported));
+ if (MyAspm->L0sSupported) {
+ //
+ // If L0s is supported in capability, apply platform override.
+ //
+ MyAspm->L0sSupported = Override->Table[Index].EndPointAspm & BIT0;
+ }
+ if (MyAspm->L1Supported) {
+ //
+ // If L1 is supported in capability, apply platform override.
+ //
+ MyAspm->L1Supported = (Override->Table[Index].EndPointAspm & BIT1) >> 1;
+ }
+ DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, override L0sSupported = 0x%x, L1Supported = 0x%x\n",
+ Sbdf.Bus, Sbdf.Dev, Sbdf.Func, MyAspm->L0sSupported, MyAspm->L1Supported));
+ }
+ }
+}
+
+/**
+ Combines ASPM capabilities of two devices on both ends of a link to determine link's ASPM capabilities
+
+ @param[in] AspmA, AspmB ASPM capabilities of two devices
+
+@retval ASPM_CAPS structure containing combined ASPM capabilities
+**/
+STATIC
+ASPM_CAPS
+CombineAspm (
+ ASPM_CAPS AspmA,
+ ASPM_CAPS AspmB,
+ BOOLEAN DownstreamPort
+ )
+{
+ ASPM_CAPS Combined;
+
+ if (DownstreamPort) {
+ //
+ // When combining ASPM in downstream ports, combination must reflect state of link just below
+ // and consider all acceptable latencies of all endpoints anywhere down below that port
+ //
+ Combined.L0sSupported = AspmA.L0sSupported & AspmB.L0sSupported;
+ Combined.L1Supported = AspmA.L1Supported & AspmB.L1Supported;
+ Combined.LinkL0sExitLatency = MAX (AspmA.LinkL0sExitLatency, AspmB.LinkL0sExitLatency);
+ Combined.LinkL1ExitLatencyUs = MAX (AspmA.LinkL1ExitLatencyUs, AspmB.LinkL1ExitLatencyUs);
+ Combined.L0sAcceptableLatency = MIN (AspmA.L0sAcceptableLatency, AspmB.L0sAcceptableLatency);
+ Combined.L1AcceptableLatencyUs = MIN (AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs);
+ } else {
+ //
+ // When combining ASPM in switch upstream ports,
+ // Supported and ExitLatency must only reflect capabilities of upstream port itself
+ // But acceptable latencies must consider all endpoints anywhere below
+ //
+ Combined.L0sSupported = AspmA.L0sSupported;
+ Combined.L1Supported = AspmA.L1Supported;
+ Combined.LinkL0sExitLatency = AspmA.LinkL0sExitLatency;
+ Combined.LinkL1ExitLatencyUs = AspmA.LinkL1ExitLatencyUs;
+ Combined.L0sAcceptableLatency = MIN (AspmA.L0sAcceptableLatency, AspmB.L0sAcceptableLatency);
+ Combined.L1AcceptableLatencyUs = MIN (AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs);
+ }
+ DEBUG ((DEBUG_INFO, "CombineAspm %x:%x -> %x\n", AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs, Combined.L1AcceptableLatencyUs));
+ return Combined;
+}
+
+/**
+ Checks if L1 can be enabled on given link, according to ASPM parameters of that link
+
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+ @retval TRUE if L1 can be enabled
+**/
+STATIC
+BOOLEAN
+IsL1Allowed (
+ ASPM_CAPS Aspm
+ )
+{
+ return (Aspm.L1Supported && (Aspm.L1AcceptableLatencyUs >= Aspm.LinkL1ExitLatencyUs));
+}
+
+/**
+ Checks if L0s can be enabled on given link, according to ASPM parameters of that link
+
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+ @retval TRUE if L0s can be enabled
+**/
+STATIC
+BOOLEAN
+IsL0sAllowed (
+ ASPM_CAPS Aspm
+ )
+{
+ return (Aspm.L0sSupported && (Aspm.L0sAcceptableLatency >= Aspm.LinkL0sExitLatency));
+}
+
+/**
+ Enables L0s and L1 for given port, if possible.
+ L0s/L1 can be enabled if it's supported on both sides of a link and if link's latency doesn't exceed
+ acceptable latency of any endpoint below this link
+
+ @param[in] Base device's base address
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+**/
+STATIC
+VOID
+SetAspm (
+ SBDF Sbdf,
+ ASPM_CAPS Aspm
+ )
+{
+ UINT16 DataOr;
+
+ DataOr = 0;
+ if (IsL0sAllowed (Aspm)) {
+ DataOr |= V_PCIE_LCTL_ASPM_L0S;
+ }
+ if (IsL1Allowed (Aspm)) {
+ DataOr |= V_PCIE_LCTL_ASPM_L1;
+ }
+ DEBUG ((DEBUG_INFO, "SetAspm on %02x:%02x:%02x to %d\n", Sbdf.Bus,Sbdf.Dev,Sbdf.Func, DataOr));
+ PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCTL_OFFSET, (UINT16)~B_PCIE_LCTL_ASPM, DataOr);
+}
+
+/**
+ Adds device entry to a list of devices.
+
+ @param[in,out] Table array of devices
+ @param[in] Sbdf segment:bus:device:function coordinates of device to be added to table
+**/
+STATIC
+VOID
+AddToDeviceTable (
+ SBDF_TABLE *Table,
+ SBDF Sbdf
+ )
+{
+ if (Table->Count < MAX_SBDF_TABLE_SIZE) {
+ Table->Entry[Table->Count++] = Sbdf;
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ Remove device entry from a list and clear its bus assignment
+
+ @param[in,out] Table array of devices
+**/
+STATIC
+VOID
+ClearBusFromTable (
+ SBDF_TABLE *Table
+ )
+{
+ while (Table->Count > 0) {
+ PciSegmentWrite32 (SbdfToBase (Table->Entry[Table->Count - 1]) + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0);
+ Table->Count--;
+ }
+}
+
+/**
+ Attempts to assign secondary and subordinate bus numbers to uninitialized bridges in PCIe tree
+ If the device is a bridge and already has bus numbers assigned, they won't be changed
+ Otherwise new bus number will be assigned below this bridge.
+ This function can be called from SMM, where BIOS must not modify bus numbers to prevent
+ conflict with OS enumerator. To prevent this, this function returns list of bridges whose
+ bus numbers were changed. All devices from that list must have buses cleared afterwards.
+
+ @param[in] Sbdf segment:bus:device:function coordinates of device to be added to table
+ @param[in] MinBus minimum Bus number that can be assigned below this port
+ @param[in] MaxBus maximum Bus number that can be assigned below this port
+ @param[in] BridgeCleanupList list of bridges where bus numbers were modified
+
+ @retval maximum bus number assigned anywhere below this device
+**/
+STATIC
+UINT8
+RecursiveBusAssignment (
+ SBDF Sbdf,
+ UINT8 MinBus,
+ UINT8 MaxBus,
+ SBDF_TABLE *BridgeCleanupList
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+ UINT32 Data32;
+ UINT8 BelowBus;
+ UINT8 SecondaryBus;
+ UINT8 SubordinateBus;
+
+ ChildSbdf.Seg = Sbdf.Seg;
+ InitChildFinder (&ChildSbdf);
+ Base = SbdfToBase (Sbdf);
+
+ //
+ // On way down:
+ // assign secondary bus, then increase it by one before stepping down; temporarily assign max subordinate bus
+ // On way up:
+ // fix subordinate bus assignment to equal max bus number assigned anywhere below; return that number
+ //
+ DevType = GetDeviceType (Sbdf);
+ if ((Sbdf.Bus >= MaxBus) || (DevType == DevTypePcieEndpoint) || (DevType == DevTypePci)) {
+ return (UINT8) Sbdf.Bus;
+ } else {
+ Data32 = PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
+ SecondaryBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8);
+ SubordinateBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SBBN) >> 16);
+ if (SecondaryBus != 0) {
+ ChildSbdf.Bus = SecondaryBus;
+ MinBus = SecondaryBus + 1;
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentP %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, MinBus, SubordinateBus));
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ BelowBus = RecursiveBusAssignment (ChildSbdf, MinBus, SubordinateBus, BridgeCleanupList);
+ MinBus = BelowBus + 1;
+ }
+ return SubordinateBus;
+ } else {
+ Data32 = Sbdf.Bus + (MinBus << 8) + (MaxBus << 16);
+ PciSegmentWrite32(Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Data32);
+ AddToDeviceTable (BridgeCleanupList, Sbdf);
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentE %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, MinBus, MaxBus));
+ BelowBus = MinBus;
+ ChildSbdf.Bus = MinBus;
+ MinBus++;
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ BelowBus = RecursiveBusAssignment (ChildSbdf, MinBus, MaxBus, BridgeCleanupList);
+ MinBus = BelowBus + 1;
+ }
+ Data32 &= ~B_PCI_BRIDGE_BNUM_SBBN;
+ Data32 |= (BelowBus << 16);
+ PciSegmentWrite32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Data32);
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentL %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, (Data32&0xFF00)>>8, BelowBus));
+ return BelowBus;
+ }
+ }
+}
+
+/**
+ Enables L0s and/or L1 for PCIE links in the hierarchy below
+ L0s/L1 can be enabled when both sides of a link support it and link latency is smaller than acceptable latency
+ ASPM of a given link is independend from any other link (except 1ms L1 adjustment, read below), so it's possible to
+ have a hierarchy when RP link has no ASPM but links below do.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Depth How many links there are between this port and root complex
+ @param[in] Override Pch Pcie devices OverrideTable
+
+ @retval structure that describes acceptable latencies of all endpoints below plus ASPM parameters of last link
+**/
+STATIC
+ASPM_CAPS
+RecursiveAspmConfiguration (
+ SBDF Sbdf,
+ UINT8 Depth,
+ OVERRIDE_TABLE *Override
+ )
+{
+ SBDF ChildSbdf;
+ ASPM_CAPS MyAspm;
+ ASPM_CAPS ChildAspm;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveAspmConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ //
+ // On way down:
+ // pass number of links traversed; increase it per upstream port visited (not endpoint)
+ // On way up:
+ // EndPoint: read Acceptable Latencies; subtract Depth From L1AcceptableLat to account for "1us per switch additional delay"
+ // Downstreamport: AND L0s/L1 caps; calculate LinkLatency; enable L0s/L1 if supported and if acceptable latency is bigger than link latency;
+ // if L1 not enabled, add back 1us to Acceptable Latency to cancel earlier Depth subtraction
+ // UpstreamPort: calculate minimum of below Acceptable Latencies; return that, with upper link's Latency and L0s/L1 support
+ //
+ DevType = GetDeviceType(Sbdf);
+ if (DevType == DevTypePcieUpstream) {
+ Depth++;
+ }
+ MyAspm = GetAspmCaps (Sbdf);
+ //
+ // Get ASPM L0s and L1 override
+ //
+ GetOverrideAspm (Sbdf, &MyAspm, Override);
+ if (DevType == DevTypePcieEndpoint) {
+ //
+ // Every switch between endpoint and CPU introduces 1us additional latency on L1 exit. This is reflected by
+ // subtracting 1us per switch from endpoint's acceptable L1 latency.
+ // In case L1 doesn't get enabled in one of switches, that 1us will be added back.
+ // This calculation is not precise. It ignores that some switches' added delay may be shadowed by
+ // other links' exit latency. But it guarantees that acceptable latency won't be exceeded and is simple
+ // enough to perform in a single iteration without backtracking.
+ //
+ return PatchL1AcceptableLatency (MyAspm, (-1 * Depth));
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildAspm = RecursiveAspmConfiguration (ChildSbdf, Depth, Override);
+ MyAspm = CombineAspm (MyAspm, ChildAspm, (DevType == DevTypePcieDownstream));
+ }
+ if (DevType == DevTypePcieDownstream) {
+ SetAspm (Sbdf, MyAspm);
+ //
+ // ASPM config must be consistent across all functions of a device. That's why there's while loop.
+ //
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ SetAspm (ChildSbdf, MyAspm);
+ }
+ if (!IsL1Allowed (MyAspm)) {
+ MyAspm = PatchL1AcceptableLatency (MyAspm, 1);
+ }
+ }
+ }
+ return MyAspm;
+}
+
+/**
+ Enables L1 substates for PCIE links in the hierarchy below
+ L1.1 / L1.2 can be enabled if both sides of a link support it.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval structure that describes L1ss capabilities of the device
+**/
+STATIC
+L1SS_CAPS
+RecursiveL1ssConfiguration (
+ SBDF Sbdf,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ L1SS_CAPS CombinedCaps;
+ L1SS_CAPS ChildCaps;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveL1ssConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase (Sbdf);
+ //
+ // On way down:
+ // do nothing
+ // On way up:
+ // In downstream ports, combine L1ss capabilities of that port and device behind it, then enable L1.1 and/or L1.2 if possible
+ // Return L1ss capabilities
+ //
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildCaps = RecursiveL1ssConfiguration (ChildSbdf, Override);
+ if (DevType == DevTypePcieDownstream && ChildSbdf.Func == 0) {
+ CombinedCaps = CombineL1ss (GetL1ssCaps (Base, Override), ChildCaps);
+ SetL1ss (Sbdf, CombinedCaps, Override);
+ SetL1ss (ChildSbdf, CombinedCaps, Override);
+ }
+ }
+ }
+ return GetL1ssCaps (Base, Override);
+}
+
+/**
+ Checks if there is an IoAPIC device in the PCIe hierarchy.
+ If one is found, this function doesn't check for more and returns
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval TRUE if IoAPIC device was found
+**/
+STATIC
+BOOLEAN
+RecursiveIoApicCheck (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ UINT8 IoApicPresent;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveIoApicCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ IoApicPresent = FALSE;
+
+ if (IsIoApicDevice (SbdfToBase (Sbdf))) {
+ DEBUG ((DEBUG_INFO, "IoApicFound @%x:%x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return TRUE;
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ IoApicPresent = RecursiveIoApicCheck (ChildSbdf);
+ if (IoApicPresent) {
+ break;
+ }
+ }
+ }
+ DEBUG ((DEBUG_INFO, "IoApic status %d @%x:%x:%x:%x\n", IoApicPresent, Sbdf.Seg, Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return IoApicPresent;
+}
+
+/**
+ Calculates Maximum Payload Size supported by PCIe hierarchy.
+ Starting from a device, it finds the minimum MPS supported by devices below it.
+ There are many valid strategies for setting MPS. This implementation chooses
+ one that is safest, but doesn't guarantee maximum performance:
+ Find minimum MPS under given rootport, then program that minimum value everywhere below that rootport
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval MPS supported by PCIe hierarchy, calculated as MIN(MPS of all devices below)
+**/
+STATIC
+UINT8
+RecursiveMpsCheck (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ UINT8 MyMps;
+ UINT8 SubtreeMps;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveMpsCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ MyMps = GetMps (Sbdf);
+ if (MyMps == 0) {
+ return MyMps;
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ SubtreeMps = RecursiveMpsCheck (ChildSbdf);
+ MyMps = MIN(MyMps, SubtreeMps);
+ }
+ }
+ return MyMps;
+}
+
+/**
+ Sets Maximum Payload Size in PCIe hierarchy.
+ Starting from a device, it programs the same MPS value to it and all devices below it.
+ There are many valid strategies for setting MPS. This implementation chooses
+ one that is safest, but doesn't guarantee maximum performance:
+ Find minimum MPS under given rootport, then program that minimum value everywhere below that rootport
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Mps Maximum Payload Size to be programmed
+**/
+STATIC
+VOID
+RecursiveMpsConfiguration (
+ SBDF Sbdf,
+ UINT8 Mps
+ )
+{
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveMpsConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ RecursiveMpsConfiguration (ChildSbdf, Mps);
+ }
+ }
+ SetMps (Sbdf, Mps);
+}
+
+/**
+ Sets Enable Clock Power Management bit for devices that support it.
+ A device supports CPM only if all function of this device report CPM support.
+ Downstream ports never report CPM capability, so it's only relevant for upstream ports.
+ When this function executes on upstream component, it will check CPM & set ECPM of downstream component
+ When this function executes on downstream component, all devices below it are guaranteed to
+ return CPM=0 so it will do nothing
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval TRUE = this device supports CPM, FALSE = it doesn't
+**/
+STATIC
+BOOLEAN
+RecursiveCpmConfiguration (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ BOOLEAN ChildCpm;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveCpmConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ ChildCpm = FALSE;
+
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ ChildCpm = TRUE;
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildCpm &= RecursiveCpmConfiguration (ChildSbdf);
+ }
+ if (ChildCpm) {
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ EnableCpm (ChildSbdf);
+ }
+ }
+ }
+ return IsCpmSupported (Sbdf);
+}
+
+/**
+ Sets Common Clock Configuration bit for devices that share common clock across link
+ Devices on both sides of a PCIE link share common clock if both upstream component
+ and function 0 of downstream component report Slot Clock Configuration bit = 1.
+ When this function executes on upstream component, it checks SCC of both sides of the link
+ If they both support it, sets CCC for both sides (this means all functions of downstream component)
+ When this function executes on downstream component, it only returns SCC capability
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] WaitForRetrain decides if this function should busy-wait for link retrain
+
+ @retval TRUE = this device supports SCC, FALSE = it doesn't
+**/
+STATIC
+BOOLEAN
+RecursiveCccConfiguration (
+ SBDF Sbdf,
+ BOOLEAN WaitForRetrain
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ BOOLEAN MyScc;
+ BOOLEAN ChildScc;
+ BOOLEAN LinkScc;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveCccConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ ChildScc = 0;
+ Base = SbdfToBase(Sbdf);
+ MyScc = GetScc (SbdfToBase(Sbdf), (UINT8)Sbdf.PcieCap);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildScc |= RecursiveCccConfiguration (ChildSbdf, WaitForRetrain);
+ }
+ if (DevType == DevTypePcieDownstream) {
+ LinkScc = MyScc & ChildScc;
+ if (LinkScc) {
+ EnableCcc (SbdfToBase(Sbdf), (UINT8)Sbdf.PcieCap);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ EnableCcc (SbdfToBase(ChildSbdf), (UINT8)ChildSbdf.PcieCap);
+ }
+ RetrainLink(Base, (UINT8)Sbdf.PcieCap, WaitForRetrain);
+ }
+ }
+ }
+ return MyScc;
+}
+
+/**
+ Configures Latency Tolerance Reporting in given device and in PCIe tree below it.
+ This function configures Maximum LTR and enables LTR mechanism. It visits devices using depth-first search
+ and skips branches behind devices which do not support LTR.
+ Maximum LTR:
+ This function will set LTR's upper bound for every visited device. Max LTR value is provided as a parameter
+ Enable LTR:
+ LTR should be enabled top-to-bottom in every visited device that supports LTR. This function does not
+ iterate down behind devices with no LTR support. In effect, LTR will be enabled in given device if that device
+ and all devices above it on the way to RootComplex do support LTR.
+
+ This function expects that bridges have bus numbers already configured
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] LtrLimit Ltr to be programmed to every endpoint
+
+ @retval MaxLTR programmed in this device
+**/
+STATIC
+VOID
+RecursiveLtrConfiguration (
+ SBDF Sbdf,
+ LTR_LIMIT LtrLimit
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveLtrConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase(Sbdf);
+
+ if (!IsLtrCapable (Sbdf)) {
+ DEBUG ((DEBUG_INFO, "Not LtrCapable %02x:%02x:%02x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return;
+ }
+ EnableLtr (Sbdf);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ RecursiveLtrConfiguration (ChildSbdf, LtrLimit);
+ }
+ }
+ SetLtrLimit (Base, LtrLimit);
+}
+
+/**
+ In accordance with PCIe spec, devices with no LTR support are considered to have no LTR requirements
+ which means infinite latency tolerance. This was found to cause problems with HID and Audio devices without LTR
+ support placed behind PCIe switches with LTR support, as Switch's upstream link would be allowed to enter L1.2
+ and cause large latency downstream. To work around such issues and to fix some devices with broken
+ LTR reporting, Device Override table was introduced.
+ This function scans PCIe tree for devices mentioned in override table and calculates the strictest
+ LTR requirement between them. That value will be programmed into rootport's LTR override register
+
+ This function expects that bridges have bus numbers already configured
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] AspmOverride Device specific ASPM policy override items
+
+ @retval MaxLTR programmed in this device
+**/
+STATIC
+LTR_OVERRIDE
+RecursiveLtrOverrideCheck (
+ SBDF Sbdf,
+ OVERRIDE_TABLE *AspmOverride
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ LTR_OVERRIDE MyLtrOverride;
+ LTR_OVERRIDE ChildLtr;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveLtrOverrideCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase(Sbdf);
+
+ MyLtrOverride = GetOverrideLtr (Base, AspmOverride);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildLtr = RecursiveLtrOverrideCheck (ChildSbdf, AspmOverride);
+ MyLtrOverride = CombineLtr (MyLtrOverride, ChildLtr);
+ }
+ }
+ return MyLtrOverride;
+}
+
+/**
+ Configures rootport packet split.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Mps maximum packet size
+**/
+STATIC
+VOID
+ConfigureRpPacketSplit (
+ SBDF RpSbdf,
+ UINT8 Mps
+ )
+{
+ UINT64 RpBase;
+
+ RpBase = SbdfToBase (RpSbdf);
+ PciSegmentAndThenOr32 (RpBase + R_PCH_PCIE_CFG_CCFG, (UINT32) ~(B_PCH_PCIE_CFG_CCFG_UNRS), Mps << N_PCH_PCIE_CFG_CCFG_UNRS);
+}
+
+/**
+ Configures LTR override in rootport's proprietary registers.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] RpConfig rootport configuration
+ @param[in] TreeLtr combination of LTR override values from all devices under this rootport
+**/
+STATIC
+VOID
+ConfigureRpLtrOverride (
+ SBDF RpSbdf,
+ PCH_PCIE_ROOT_PORT_CONFIG *RpConfig,
+ OVERRIDE_TABLE *AspmOverride
+ )
+{
+ UINT64 RpBase;
+ UINT32 OvrEn;
+ UINT32 OvrVal;
+ LTR_OVERRIDE TreeLtr;
+
+ OvrEn = 0;
+ OvrVal = 0;
+ RpBase = SbdfToBase (RpSbdf);
+ //
+ // LTR settings from LTROVR register only get acknowledged on rising edge of LTROVR2[1:0]
+ // If those bits were already set (that can happen on a plug-hotUnplug-hotPlug scenario),
+ // they need to be toggled
+ //
+ if (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LTROVR2) != 0) {
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR2, 0);
+ }
+ //
+ // (*)LatencyOverrideMode = 0 -> no override
+ // 1 -> override with RP policy values
+ // 2 -> override with endpoint's override values
+ //
+
+ TreeLtr = RecursiveLtrOverrideCheck (RpSbdf, AspmOverride);
+
+ if (RpConfig->ForceLtrOverride || TreeLtr.ForceOverride) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_FORCE_OVERRIDE;
+ }
+ if (RpConfig->LtrConfigLock == TRUE) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LOCK;
+ }
+
+ if (RpConfig->SnoopLatencyOverrideMode == 1) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN;
+ OvrVal |= RpConfig->SnoopLatencyOverrideValue;
+ OvrVal |= RpConfig->SnoopLatencyOverrideMultiplier << 10;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRSROVR;
+ } else if (RpConfig->SnoopLatencyOverrideMode == 2) {
+ if (TreeLtr.MaxSnoopLatencyRequirement) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN;
+ OvrVal |= TreeLtr.MaxSnoopLatencyValue;
+ OvrVal |= TreeLtr.MaxSnoopLatencyScale << 10;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRSROVR;
+ }
+ }
+ if (RpConfig->NonSnoopLatencyOverrideMode == 1) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN;
+ OvrVal |= RpConfig->NonSnoopLatencyOverrideValue << 16;
+ OvrVal |= RpConfig->NonSnoopLatencyOverrideMultiplier << 26;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRNSROVR;
+ } else if (RpConfig->NonSnoopLatencyOverrideMode == 2) {
+ if (TreeLtr.MaxNoSnoopLatencyRequirement) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN;
+ OvrVal |= TreeLtr.MaxNoSnoopLatencyValue << 16;
+ OvrVal |= TreeLtr.MaxNoSnoopLatencyScale << 26;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRNSROVR;
+ }
+ }
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR, OvrVal);
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR2, OvrEn);
+ DEBUG ((DEBUG_INFO, "ConfigureRpLtrOverride %x:%x Val %x En %x\n", RpSbdf.Dev, RpSbdf.Func, OvrVal, OvrEn));
+}
+
+/**
+ This function configures EOI message forwarding for PCIe port.
+ If there's an IoAPIC behind this port, forwarding will be enabled
+ Otherwise it will be disabled to minimize bus traffic
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] IoApicPresent TRUE if there's IoAPIC behind this rootprot
+**/
+VOID
+ConfigureEoiForwarding (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ BOOLEAN IoApicPresent
+ )
+{
+ UINT64 RpBase;
+ UINT32 RpIndex;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ RpIndex = PciePortIndex (RpBase);
+
+ if (IoApicPresent == FALSE) {
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_MPC2, B_PCH_PCIE_CFG_MPC2_EOIFD);
+ } else {
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to PCH BWG PSF EOI Multicast Configuration
+ ///
+ PciSegmentAnd32 (RpBase + R_PCH_PCIE_CFG_MPC2, (UINT32)~B_PCH_PCIE_CFG_MPC2_EOIFD);
+ PsfConfigurEoiForPciePort (RpIndex);
+ }
+}
+
+/**
+ Configures proprietary parts of L1 substates configuration in rootport
+
+ @param[in] RpSbdf segment:bus:device:function coordinates of rootport
+**/
+STATIC
+VOID
+L1ssProprietaryConfiguration (
+ SBDF RpSbdf
+ )
+{
+ BOOLEAN ClkreqSupported;
+ BOOLEAN L1ssEnabled;
+ UINT16 PcieCapOffset;
+ UINT32 Data32;
+ BOOLEAN L1LowSupported;
+ UINT64 RpBase;
+
+ RpBase = SbdfToBase (RpSbdf);
+ ClkreqSupported = PcieIsPhyLanePgEnabled (RpBase);
+
+ PcieCapOffset = PcieBaseFindExtendedCapId (RpBase, V_PCIE_EX_L1S_CID);
+ if (PcieCapOffset == 0) {
+ L1ssEnabled = FALSE;
+ } else {
+ Data32 = PciSegmentRead32 (RpBase + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET);
+ L1ssEnabled = Data32 & (B_PCIE_EX_L1SCAP_AL1SS | B_PCIE_EX_L1SCAP_AL12S | B_PCIE_EX_L1SCAP_PPL11S |B_PCIE_EX_L1SCAP_PPL12S);
+ }
+ L1LowSupported = ClkreqSupported && IsLtrCapable (RpSbdf) && !L1ssEnabled;
+
+ ///
+ /// If L1.SNOOZ and L1.OFF (L1 Sub-States) are not supported and per-port CLKREQ# is supported, and LTR is supported:
+ /// Enable L1.LOW by setting Dxx:Fn:420[17] = 1b
+ ///
+ if (L1LowSupported) {
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) B_PCH_PCIE_CFG_PCIEPMECTL_L1LE);
+ } else {
+ PciSegmentAnd32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) ~B_PCH_PCIE_CFG_PCIEPMECTL_L1LE);
+ }
+
+ if (L1LowSupported || L1ssEnabled) {
+ ///
+ /// f. Set Dxx:Fn:420h[0] to 1b prior to L1 enabling if any L1substate is enabled (including L1LOW)
+ ///
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, B_PCH_PCIE_CFG_PCIEPMECTL_L1FSOE);
+ }
+}
+
+/**
+ Initializes the following features in rootport and devices behind it:
+ Maximum Payload Size (generic)
+ Rootport packet split (proprietary)
+ EonOfInterrupt forwarding (proprietary)
+ Common Clock Configuration (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ CCC requires link retrain, which takes a while. CCC must happen before L0s/L1 programming.
+ If there was guarantee no code would access PCI while links retrain, it would be possible to skip this waiting
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusMin minimum Bus number that can be assigned below this rootport
+ @param[in] BusMax maximum Bus number that can be assigned below this rootport
+**/
+VOID
+RootportDownstreamConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax
+ )
+{
+ UINT8 Mps;
+ BOOLEAN IoApicPresent;
+ UINT64 RpBase;
+ SBDF RpSbdf;
+ SBDF_TABLE BridgeCleanupList;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ if (!(IsDevicePresent (RpBase))) {
+ return;
+ }
+ RpSbdf.Seg = RpSegment;
+ RpSbdf.Bus = RpBus;
+ RpSbdf.Dev = RpDevice;
+ RpSbdf.Func = RpFunction;
+ RpSbdf.PcieCap = PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIEXP);
+
+ DEBUG ((DEBUG_INFO, "RootportDownstreamConfiguration %x:%x\n", RpDevice, RpFunction));
+ BridgeCleanupList.Count = 0;
+ RecursiveBusAssignment (RpSbdf, BusMin, BusMax, &BridgeCleanupList);
+
+ Mps = RecursiveMpsCheck (RpSbdf);
+ RecursiveMpsConfiguration (RpSbdf, Mps);
+ ConfigureRpPacketSplit (RpSbdf, Mps);
+ IoApicPresent = RecursiveIoApicCheck (RpSbdf);
+ ConfigureEoiForwarding (RpSegment, RpBus, RpDevice, RpFunction, IoApicPresent);
+ RecursiveCccConfiguration (RpSbdf, TRUE);
+
+ ClearBusFromTable (&BridgeCleanupList);
+}
+
+/**
+ Configures the following power-management related features in rootport and devices behind it:
+ LTR limit (generic)
+ LTR override (proprietary)
+ Clock Power Management (generic)
+ L1 substates (generic except for the override table)
+ L1.LOW substate (proprietary)
+ L0s and L1 (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusLimit maximum Bus number that can be assigned below this rootport
+ @param[in] AspmOverrideTableSize size of override array
+ @param[in] AspmOverrideTable array of device that need exceptions in configuration
+ @param[in] PerformAspmConfiguration enables/disables ASPM programming
+**/
+VOID
+RootportDownstreamPmConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax,
+ PCH_PCIE_ROOT_PORT_CONFIG *RpConfig,
+ UINT32 AspmOverrideTableSize,
+ PCH_PCIE_DEVICE_OVERRIDE *AspmOverrideTable
+ )
+{
+ LTR_LIMIT PolicyLtr;
+ OVERRIDE_TABLE PmOverrideTable;
+ UINT64 RpBase;
+ SBDF RpSbdf;
+ SBDF_TABLE BridgeCleanupList;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ if (!(IsDevicePresent (RpBase))) {
+ return;
+ }
+ PmOverrideTable.Size = AspmOverrideTableSize;
+ PmOverrideTable.Table = AspmOverrideTable;
+
+ DEBUG ((DEBUG_INFO, "RootportDownstreamPmConfiguration %x:%x\n", RpDevice, RpFunction));
+ PolicyLtr.MaxNoSnoopLatencyScale = (RpConfig->LtrMaxNoSnoopLatency & 0x1c00) >> 10;
+ PolicyLtr.MaxNoSnoopLatencyValue = RpConfig->LtrMaxNoSnoopLatency & 0x3FF;
+ PolicyLtr.MaxSnoopLatencyScale = (RpConfig->LtrMaxSnoopLatency & 0x1c00) >> 10;
+ PolicyLtr.MaxSnoopLatencyValue = RpConfig->LtrMaxSnoopLatency & 0x3FF;
+
+ RpSbdf.Seg = RpSegment;
+ RpSbdf.Bus = RpBus;
+ RpSbdf.Dev = RpDevice;
+ RpSbdf.Func = RpFunction;
+ RpSbdf.PcieCap = PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ //
+ // This code could execute either before or after enumeration. If before, then buses would not yet be assigned to bridges,
+ // making devices deeper in the hierarchy inaccessible.
+ // RecursiveBusAssignment will scan whole PCie tree and assign bus numbers to uninitialized bridges, if there are any
+ // List of such bridges will be kept in CleanupList, so that after PM programming is done, bus numbers can brought to original state
+ //
+ BridgeCleanupList.Count = 0;
+ RecursiveBusAssignment(RpSbdf, BusMin, BusMax, &BridgeCleanupList);
+ //
+ // The 'Recursive...' functions below expect bus numbers to be already assigned
+ //
+ RecursiveLtrConfiguration (RpSbdf, PolicyLtr);
+ ConfigureRpLtrOverride (RpSbdf, RpConfig, &PmOverrideTable);
+ if (RpConfig->EnableCpm) {
+ RecursiveCpmConfiguration (RpSbdf);
+ }
+ //
+ // L1 substates can be modified only when L1 is disabled, so this function must execute
+ // before Aspm configuration which enables L1
+ //
+ RecursiveL1ssConfiguration (RpSbdf, &PmOverrideTable);
+ L1ssProprietaryConfiguration (RpSbdf);
+ RecursiveAspmConfiguration (RpSbdf, 0, &PmOverrideTable);
+ ClearBusFromTable (&BridgeCleanupList);
+}
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
new file mode 100644
index 0000000000..f2d20c625a
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
@@ -0,0 +1,542 @@
+/** @file
+ This file contains PSF routines for RC usage
+
+ 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/BaseMemoryLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/SaPlatformLib.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegsPsf.h>
+#include <Register/PchRegsPcie.h>
+#include "PchPsfPrivateLibInternal.h"
+
+/**
+ Disable device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDevice (
+ IN PSF_PORT PsfPort
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PSFX_PCR_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide PciCfgSpace of device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfHideDevice (
+ IN PSF_PORT PsfPort
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ // If there is PCI access right after the PSF hide device, the device might
+ // still be accessible since the PSF cycle is not completed yet, and causes
+ // the race condition between sideband and primary cycles.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PSFX_PCR_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ Unhide PciCfgSpace of device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfUnhideDevice (
+ IN PSF_PORT PsfPort
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PSFX_PCR_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ Disable device BARs at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarDisMask BIT0-BAR0, BIT1-BAR1,...
+ Mask corresponds to 32bit wide BARs
+**/
+VOID
+PsfDisableDeviceBar (
+ IN PSF_PORT PsfPort,
+ IN UINT32 BarDisMask
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // BAR0-5 supported
+ //
+ ASSERT (BarDisMask < BIT6);
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_PCIEN,
+ ~0u,
+ BarDisMask << N_PCH_PSFX_PCR_T0_SHDW_PCIEN_BARXDIS
+ );
+}
+
+/**
+ Enable device BARs at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarEnMask BIT0-BAR0, BIT1-BAR1,...
+ Mask corresponds to 32bit wide BARs
+**/
+VOID
+PsfEnableDeviceBar (
+ IN PSF_PORT PsfPort,
+ IN UINT32 BarEnMask
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // BAR0-5 supported
+ //
+ ASSERT (BarEnMask < BIT6);
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_PCIEN,
+ (UINT32)~(BarEnMask << N_PCH_PSFX_PCR_T0_SHDW_PCIEN_BARXDIS),
+ 0
+ );
+}
+
+/**
+ Disable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_PCIEN,
+ ~(UINT32)(B_PCH_PSFX_PCR_T0_SHDW_PCIEN_IOEN),
+ 0
+ );
+}
+
+/**
+ Enable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ )
+{
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PSFX_PCR_T0_SHDW_PCIEN_IOEN
+ );
+}
+
+/**
+ Set device BARx address at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1, ...)
+ @param[in] BarValue 32bit BAR value
+**/
+VOID
+PsfSetDeviceBarValue (
+ IN PSF_PORT PsfPort,
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ )
+{
+ ASSERT (BarNum < 6);
+
+ if (PSF_IS_PORT_NULL (PsfPort)) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Read back is needed to enforce the sideband and primary ordering.
+ //
+ PchPcrAndThenOr32WithReadback (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR0 + BarNum * 0x4,
+ 0,
+ BarValue
+ );
+}
+
+/**
+ Hide PMC device at PSF level
+**/
+VOID
+PsfHidePmcDevice (
+ VOID
+ )
+{
+ PsfHideDevice (PsfPmcPort ());
+}
+
+/**
+ Set PMC ABASE value in PSF
+
+ @param[in] Address Address for ACPI base address.
+**/
+VOID
+PsfSetPmcAbase (
+ IN UINT16 Address
+ )
+{
+ PSF_PORT PsfPort;
+
+ PsfPort = PsfPmcPort ();
+
+ ASSERT (PchPcrRead32 (PsfPort.PsfPid, PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR4) != 0xFFFFFFFF);
+
+ //
+ // Disable IOSpace before changing the address
+ //
+ PsfDisableDeviceIoSpace (PsfPort);
+
+ //
+ // Program ABASE in PSF PMC space BAR4
+ //
+ PsfSetDeviceBarValue (PsfPort, 4, Address);
+
+ //
+ // Enable IOSpace
+ //
+ PsfEnableDeviceIoSpace (PsfPort);
+}
+
+/**
+ Get PMC ABASE value from PSF
+
+ @retval Address Address for ACPI base.
+**/
+UINT16
+PsfGetPmcAbase (
+ VOID
+ )
+{
+ UINT16 Address;
+ PSF_PORT PsfPort;
+
+ PsfPort = PsfPmcPort ();
+ //
+ // Read ABASE from PSF PMC space BAR4
+ //
+ Address = PchPcrRead16 (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR4
+ );
+
+ ASSERT (Address != 0xFFFF);
+
+ return Address;
+}
+
+/**
+ Get PMC PWRMBASE value from PSF
+
+ @retval Address Address for PWRM base.
+**/
+UINT32
+PsfGetPmcPwrmBase (
+ VOID
+ )
+{
+ UINT32 Address;
+ PSF_PORT PsfPort;
+
+ PsfPort = PsfPmcPort ();
+ //
+ // Read PWRMBASE from PSF PMC space BAR0
+ //
+ Address = PchPcrRead32 (
+ PsfPort.PsfPid,
+ PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR0
+ );
+
+ ASSERT (Address != 0xFFFFFFFF);
+
+ return Address;
+}
+
+/**
+ Get PSF SideBand Port ID from PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @retval PSF SideBand Port ID
+**/
+PCH_SBI_PID
+PsfSbPortId (
+ UINT32 PsfId
+ )
+{
+ UINT32 PsfTableIndex;
+ PSF_SEGMENT *PsfTable;
+ UINT32 PsfTableSize;
+
+ PsfSegments (&PsfTable, &PsfTableSize);
+
+ for (PsfTableIndex = 0; PsfTableIndex < PsfTableSize; PsfTableIndex++) {
+ if (PsfTable[PsfTableIndex].Id == PsfId) {
+ return PsfTable[PsfTableIndex].SbPid;
+ }
+ }
+
+ ASSERT (FALSE);
+ return 0;
+}
+
+
+/**
+ Get PCH Root PSF ID. This is the PSF segment to which OPDMI/DMI is connected.
+
+ @retval PsfId Root PSF ID
+**/
+UINT32
+PsfRootId (
+ VOID
+ )
+{
+ PSF_SEGMENT *PsfTable;
+ UINT32 PsfTableSize;
+
+ PsfSegments (&PsfTable, &PsfTableSize);
+
+ return PsfTable[0].Id;
+}
+
+/**
+ Add EOI Target in a given PSF
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[in] TargetId EOI Target ID
+**/
+STATIC
+VOID
+PsfAddEoiTarget (
+ UINT32 PsfId,
+ PSF_PORT_DEST_ID TargetId
+ )
+{
+ UINT16 EoiTargetBase;
+ UINT16 EoiControlBase;
+ UINT8 NumOfEnabledTargets;
+ UINT8 MaximalNumberOfTargets;
+ PCH_SBI_PID PsfSbiPortId;
+ UINT32 Data32;
+ UINT8 TargetIndex;
+
+ MaximalNumberOfTargets = PsfEoiRegData (PsfId, &EoiTargetBase, &EoiControlBase);
+ PsfSbiPortId = PsfSbPortId (PsfId);
+
+ //
+ // Get number of enabled agents from PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI register
+ //
+ Data32 = PchPcrRead32 (PsfSbiPortId, EoiControlBase);
+ NumOfEnabledTargets = (UINT8) (Data32 >> N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMMC);
+
+ //
+ // Check if target was not already enabled
+ // Targets from a different PSF segment are aggregated into single destination on
+ // current PSF segment.
+ //
+ for (TargetIndex = 0; TargetIndex < NumOfEnabledTargets; TargetIndex++) {
+ Data32 = PchPcrRead32 (PsfSbiPortId, EoiTargetBase + TargetIndex * 4);
+ //
+ // If target already added don't add it again
+ //
+ if (Data32 == TargetId.RegVal) {
+ ASSERT (FALSE);
+ return;
+ }
+ //
+ // If target is from different PSF segment than currently being analyzed
+ // it is enough that its PsfID is matching
+ //
+ if ((Data32 & B_PCH_PSFX_PCR_TARGET_PSFID) >> N_PCH_PSFX_PCR_TARGET_PSFID == TargetId.Fields.PsfId) {
+ return;
+ }
+ }
+
+ //
+ // Check if next one can be added
+ //
+ if (NumOfEnabledTargets >= MaximalNumberOfTargets) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Add next target
+ // Configure Multicast Destination ID register with target device on PSF.
+ // Configuration must be done in next available PSF_MC_AGENT_MCAST0_RS0_TGT<x>_EOI register
+ // so that other targets are not overridden. <x> is known from the number of multicast agents
+ // in Multicast Control Register. Value programmed is based on
+ // PsfID, PortGroupID, PortID and ChannelID of the target
+ //
+ PchPcrWrite32 (PsfSbiPortId, EoiTargetBase + NumOfEnabledTargets * 4, TargetId.RegVal);
+
+ //
+ // Enable new target
+ // Configure PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI, increase NumMc and set MultCEn
+ //
+ NumOfEnabledTargets++;
+ Data32 = (NumOfEnabledTargets << N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMMC) | B_PCH_PSFX_PCR_MC_CONTROL_MCASTX_MULTCEN;
+ PchPcrWrite32 (PsfSbiPortId, EoiControlBase, Data32);
+}
+
+/**
+ Enable EOI Target
+
+ @param[in] TargetId Target ID
+**/
+STATIC
+VOID
+PsfEnableEoiTarget (
+ PSF_PORT_DEST_ID TargetId
+ )
+{
+ UINT32 RootLevelPsf;
+
+ RootLevelPsf = PsfRootId ();
+
+ //
+ // Enable EOI target in root PSF
+ //
+ PsfAddEoiTarget (RootLevelPsf, TargetId);
+
+ //
+ // Enable EOI target on other PSF segment if target
+ // is not located on root PSF
+ //
+ if (TargetId.Fields.PsfId != RootLevelPsf) {
+ PsfAddEoiTarget (TargetId.Fields.PsfId, TargetId);
+ }
+}
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ //
+ // If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ // accordingly to PCH BWG PSF EOI Multicast Configuration
+ // Since there is a device behind RootPort to which EOI needs to be forwarded
+ // enable multicast (MULTCEN) and increase the number of multicast agents (NUMMC)
+ // in Multicast Control Register.
+ //
+ PsfEnableEoiTarget (PsfPcieDestinationId (RpIndex));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibCnl.c
new file mode 100644
index 0000000000..d1c87a9e84
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibCnl.c
@@ -0,0 +1,338 @@
+/** @file
+ This file contains internal PSF routines for PCH PSF lib usage
+
+ 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/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/PchRegsPsf.h>
+#include <Register/PchRegsPsfCnl.h>
+#include <Register/PchRegsPcie.h>
+#include "PchPsfPrivateLibInternal.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoI2cPsfRegs[] =
+{
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C0_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C1_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C2_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C3_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C4_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_I2C5_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoI2cPsfRegs[] =
+{
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_I2C0_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_I2C1_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_I2C2_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_I2C3_REG_BASE
+};
+
+/**
+ Return PSF_PORT for SerialIO I2C device
+
+ @param[in] I2cNum Serial IO I2C device (I2C0, I2C1, ....)
+
+ @retval PsfPort PSF PORT structure for SerialIO I2C device
+**/
+PSF_PORT
+PsfSerialIoI2cPort (
+ IN UINT32 I2cNum
+ )
+{
+ PSF_PORT PsfPort;
+
+ PsfPort.PsfPid = PID_PSF3;
+
+ if (IsPchLp ()) {
+ if (I2cNum < ARRAY_SIZE(mPchLpSerialIoI2cPsfRegs)) {
+ PsfPort.RegBase = mPchLpSerialIoI2cPsfRegs[I2cNum];
+ return PsfPort;
+ }
+ } else {
+ if (I2cNum < ARRAY_SIZE(mPchHSerialIoI2cPsfRegs)) {
+ PsfPort.RegBase = mPchHSerialIoI2cPsfRegs[I2cNum];
+ return PsfPort;
+ }
+ }
+
+ ASSERT(FALSE);
+ return PSF_PORT_NULL;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoSpiPsfRegs[] =
+{
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_SPI0_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_SPI1_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_SPI2_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoSpiPsfRegs[] =
+{
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_SPI0_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_SPI1_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_SPI2_REG_BASE
+};
+
+/**
+ Return PSF_PORT for SerialIO SPI device
+
+ @param[in] SpiNum Serial IO SPI device (SPI0, SPI1, ....)
+
+ @retval PsfPort PSF PORT structure for SerialIO SPI device
+**/
+PSF_PORT
+PsfSerialIoSpiPort (
+ IN UINT32 SpiNum
+ )
+{
+ PSF_PORT PsfPort;
+
+ PsfPort.PsfPid = PID_PSF3;
+
+ if (IsPchLp ()) {
+ if (SpiNum < ARRAY_SIZE(mPchLpSerialIoSpiPsfRegs)) {
+ PsfPort.RegBase = mPchLpSerialIoSpiPsfRegs[SpiNum];
+ return PsfPort;
+ }
+ } else {
+ if (SpiNum < ARRAY_SIZE(mPchHSerialIoSpiPsfRegs)) {
+ PsfPort.RegBase = mPchHSerialIoSpiPsfRegs[SpiNum];
+ return PsfPort;
+ }
+ }
+
+ ASSERT(FALSE);
+ return PSF_PORT_NULL;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoUartPsfRegs[] =
+{
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_UART0_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_UART1_REG_BASE,
+ R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_UART2_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoUartPsfRegs[] =
+{
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_UART0_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_UART1_REG_BASE,
+ R_CNL_PCH_H_PSF3_PCR_T0_SHDW_UART2_REG_BASE
+};
+
+/**
+ Return PSF_PORT for SerialIO UART device
+
+ @param[in] UartNum Serial IO UART device (UART0, UART1, ....)
+
+ @retval PsfPort PSF PORT structure for SerialIO UART device
+**/
+PSF_PORT
+PsfSerialIoUartPort (
+ IN UINT32 UartNum
+ )
+{
+ PSF_PORT PsfPort;
+
+ PsfPort.PsfPid = PID_PSF3;
+
+ if (IsPchLp ()) {
+ if (UartNum < ARRAY_SIZE(mPchLpSerialIoUartPsfRegs)) {
+ PsfPort.RegBase = mPchLpSerialIoUartPsfRegs[UartNum];
+ return PsfPort;
+ }
+ } else {
+ if (UartNum < ARRAY_SIZE(mPchHSerialIoUartPsfRegs)) {
+ PsfPort.RegBase = mPchHSerialIoUartPsfRegs[UartNum];
+ return PsfPort;
+ }
+ }
+
+ ASSERT(FALSE);
+ return PSF_PORT_NULL;
+}
+
+/**
+ Get EOI register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] EoiTargetBase EOI Target register
+ @param[out] EoiControlBase EOI Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfEoiRegData (
+ UINT32 PsfId,
+ UINT16 *EoiTargetBase,
+ UINT16 *EoiControlBase
+ )
+{
+ UINT8 MaxTargets;
+
+ MaxTargets = 0;
+ *EoiTargetBase = 0;
+ *EoiControlBase = 0;
+
+ switch (PsfId) {
+ case 1:
+ if (IsPchLp ()) {
+ *EoiTargetBase = R_CNL_PCH_LP_PSF1_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_LP_PSF1_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 17;
+ } else {
+ *EoiTargetBase = R_CNL_PCH_H_PSF1_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_H_PSF1_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 7;
+ }
+ break;
+
+ case 3:
+ *EoiTargetBase = R_CNL_PCH_PSF3_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_PSF3_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 1;
+ break;
+
+ case 6:
+ if (IsPchH ()) {
+ *EoiTargetBase = R_CNL_PCH_H_PSF6_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_H_PSF6_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 8;
+ }
+ break;
+
+ case 7:
+ if (IsPchH ()) {
+ *EoiTargetBase = R_CNL_PCH_H_PSF7_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_H_PSF7_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 8;
+ }
+ break;
+
+ case 8:
+ if (IsPchH ()) {
+ *EoiTargetBase = R_CNL_PCH_H_PSF8_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ *EoiControlBase = R_CNL_PCH_H_PSF8_PCR_PSF_MC_CONTROL_MCAST0_EOI;
+ MaxTargets = 8;
+ }
+ break;
+ }
+ return MaxTargets;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_PORT_DEST_ID PchLpRpDestId[] =
+{
+ {0x18000}, {0x18001}, {0x18002}, {0x18003}, // SPA: PSF1, PortID = 0
+ {0x18200}, {0x18201}, {0x18202}, {0x18203}, // SPB: PSF1, PortID = 2
+ {0x18400}, {0x18401}, {0x18402}, {0x18403}, // SPC: PSF1, PortID = 4
+ {0x18600}, {0x18601}, {0x18602}, {0x18603} // SPD: PSF1, PortID = 6
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_PORT_DEST_ID PchHRpDestId[] =
+{
+ {0x68000}, {0x68001}, {0x68002}, {0x68003}, // SPA: PSF6, PortID = 0
+ {0x88000}, {0x88001}, {0x88002}, {0x88003}, // SPB: PSF8, PortID = 0
+ {0x68100}, {0x68101}, {0x68102}, {0x68103}, // SPC: PSF6, PortID = 1
+ {0x78000}, {0x78001}, {0x78002}, {0x78003}, // SPD: PSF7, PortID = 0
+ {0x78100}, {0x78101}, {0x78102}, {0x78103}, // SPE: PSF7, PortID = 1
+ {0x88100}, {0x88101}, {0x88102}, {0x88103} // SPF: PSF8, PortID = 1
+};
+
+/**
+ PCIe PSF port destination ID (psf_id:port_group_id:port_id:channel_id)
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Destination ID
+**/
+PSF_PORT_DEST_ID
+PsfPcieDestinationId (
+ IN UINT32 RpIndex
+ )
+{
+ if (IsPchLp ()) {
+ if (RpIndex < ARRAY_SIZE(PchLpRpDestId)) {
+ return PchLpRpDestId[RpIndex];
+ }
+ } else {
+ if (RpIndex < ARRAY_SIZE(PchHRpDestId)) {
+ return PchHRpDestId[RpIndex];
+ }
+ }
+ ASSERT (FALSE);
+ return (PSF_PORT_DEST_ID){0};
+}
+
+
+/**
+ Return PSF_PORT for PMC device
+
+ @retval PsfPort PSF PORT structure for PMC device
+**/
+PSF_PORT
+PsfPmcPort (
+ VOID
+ )
+{
+ PSF_PORT PsfPort;
+
+ PsfPort.PsfPid = PID_PSF3;
+
+ if (IsPchLp ()) {
+ PsfPort.RegBase = R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_PMC_REG_BASE;
+ } else {
+ PsfPort.RegBase = R_CNL_PCH_H_PSF3_PCR_T0_SHDW_PMC_REG_BASE;
+ }
+ return PsfPort;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_SEGMENT mPchLpPsfTable[] =
+{
+ {1, PID_PSF1},
+ {2, PID_PSF2},
+ {3, PID_PSF3},
+ {4, PID_PSF4},
+ {5, PID_CSME_PSF}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_SEGMENT mPchHPsfTable[] =
+{
+ {1, PID_PSF1},
+ {2, PID_PSF2},
+ {3, PID_PSF3},
+ {4, PID_PSF4},
+ {5, PID_CSME_PSF},
+ {6, PID_PSF6},
+ {7, PID_PSF7},
+ {8, PID_PSF8}
+};
+
+/**
+ Get list of supported PSF segments.
+
+ @param[out] PsfTable Array of supported PSF segments
+ @param[out] PsfTableLength Length of PsfTable
+**/
+VOID
+PsfSegments (
+ OUT PSF_SEGMENT **PsfTable,
+ OUT UINT32 *PsfTableLength
+ )
+{
+ if (IsPchLp ()) {
+ *PsfTable = mPchLpPsfTable;
+ *PsfTableLength = ARRAY_SIZE(mPchLpPsfTable);
+ } else {
+ *PsfTable = mPchHPsfTable;
+ *PsfTableLength = ARRAY_SIZE(mPchHPsfTable);
+ }
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLib.c
new file mode 100644
index 0000000000..f88febfa48
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLib.c
@@ -0,0 +1,92 @@
+/** @file
+ PCH private PEI PMC Library for all PCH generations.
+
+ 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/PeiServicesLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchEspiLib.h>
+#include <Private/Library/GpioPrivateLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Register/PchRegsPmc.h>
+#include <Register/PchRegsClk.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLan.h>
+#include "PmcPrivateLibInternal.h"
+
+/**
+ Check if PCH PM Timer enabled based on platform policy
+
+ @retval TRUE PCH PM Timer is enabled.
+ @retval FALSE PCH PM Timer is disabled.
+**/
+BOOLEAN
+PmcIsPchPmTimerEnabled (
+ VOID
+ )
+{
+ BOOLEAN PchPmTimerEnabled;
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicy;
+ PCH_PM_CONFIG *PmConfig;
+
+ Status = PeiServicesLocatePpi (
+ &gSiPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SiPolicy
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ PchPmTimerEnabled = TRUE;
+ if (!PmConfig->EnableTcoTimer) {
+ PchPmTimerEnabled = FALSE;
+ }
+
+ DEBUG ((DEBUG_INFO, "PmcIsPchPmTimerEnabled () = %x\n", PchPmTimerEnabled));
+
+ return PchPmTimerEnabled;
+}
+
+/**
+ Lock down PMC settings
+
+ @param[in] SiPolicy The SI Policy PPI instance
+**/
+VOID
+PmcLockSettings (
+ IN SI_POLICY_PPI *SiPolicy
+ )
+{
+
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ ///
+ /// Set PWRMBASE Offset 0x1048 [24]
+ ///
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_ETR3, BIT24);
+
+ ///
+ /// PM_SYNC_LOCK
+ /// Set PWRMBASE Offset 0x18C8 [15]
+ ///
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_PMSYNC_MISC_CFG, B_PMC_PWRM_PMSYNC_PM_SYNC_LOCK);
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
new file mode 100644
index 0000000000..a6ccf4b96b
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
@@ -0,0 +1,1033 @@
+/** @file
+ PCH private PMC Library for all PCH generations.
+ 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/PmcLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TimerLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Private/Library/PchPsfPrivateLib.h>
+#include <PchReservedResources.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsPmc.h>
+#include <Register/PchRegsItss.h>
+#include <IndustryStandard/Pci30.h>
+
+#include "PmcPrivateLibInternal.h"
+
+/**
+ Send PMC IPC1 Normal Read/Write command
+
+ @param[in] Command Command to be issued to PMC IPC 1 interface
+ @param[in] SubCmdId SUB_CMD_ID for provided Command
+ @param[in] CmdSize Total size in byte to be sent via PMC IPC 1 interface
+ @param[in] WriteBufPtr Pointer to Structure of 4 DWORDs to be issued to PMC IPC 1 interface
+ @param[out] ReadBufPtr Pointer to Structure of 4 DWORDs to be filled by PMC IPC 1 interface
+
+ @retval EFI_SUCCESS Command was executed successfully
+ @retval EFI_INVALID_PARAMETER Invalid command size
+ @retval EFI_DEVICE_ERROR IPC command failed with an error
+ @retval EFI_TIMEOUT IPC command did not complete after 1s
+**/
+EFI_STATUS
+PmcSendCommand (
+ IN UINT8 Command,
+ IN UINT8 SubCmdId,
+ IN UINT8 CmdSize,
+ IN PMC_IPC_COMMAND_BUFFER *WriteBufPtr,
+ OUT PMC_IPC_COMMAND_BUFFER *ReadBufPtr
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PchPwrmBase;
+ UINT32 IpcSts;
+ UINTN Timeout;
+
+ DEBUG ((DEBUG_INFO, "PmcSendCommand(): IPC_COMMAND=0x%02X, IPC_SUB_CMD = 0x%02X, IPC_SIZE=0x%02X \n", Command, SubCmdId, CmdSize));
+ DEBUG ((DEBUG_INFO, "WBUF0=0x%08X, WBUF1=0x%08X, WBUF2=0x%08X, WBUF3=0x%08X \n", WriteBufPtr->Buf0, WriteBufPtr->Buf1, WriteBufPtr->Buf2, WriteBufPtr->Buf3));
+
+ if (CmdSize > 16) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Program the Write Buffer 0 with the Data that needs to be written to PMC
+ //
+ PchPwrmBase = PmcGetPwrmBase ();
+ MmioWrite32 ((PchPwrmBase + R_PMC_PWRM_IPC_WBUF0), WriteBufPtr->Buf0);
+ MmioWrite32 ((PchPwrmBase + R_PMC_PWRM_IPC_WBUF1), WriteBufPtr->Buf1);
+ MmioWrite32 ((PchPwrmBase + R_PMC_PWRM_IPC_WBUF2), WriteBufPtr->Buf2);
+ MmioWrite32 ((PchPwrmBase + R_PMC_PWRM_IPC_WBUF3), WriteBufPtr->Buf3);
+ //
+ // Program the command register with command and size
+ //
+ MmioWrite32 (
+ PchPwrmBase + R_PMC_PWRM_IPC_CMD,
+ (UINT32) ((CmdSize << N_PMC_PWRM_IPC_CMD_SIZE) |
+ (SubCmdId << N_PMC_PWRM_IPC_CMD_CMD_ID) |
+ (Command << N_PMC_PWRM_IPC_CMD_COMMAND))
+ );
+
+ //
+ // Read the IPC_STS register to get BUSY or Error status
+ //
+ Timeout = 0;
+ Status = EFI_SUCCESS;
+ while (TRUE) {
+ IpcSts = MmioRead32 (PchPwrmBase + R_PMC_PWRM_IPC_STS);
+ if ((IpcSts & B_PMC_PWRM_IPC_STS_BUSY) == 0) {
+ break;
+ }
+
+ if (Timeout > (1000 * 100)) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ MicroSecondDelay (10);
+ Timeout++;
+ }
+
+ if ((IpcSts & B_PMC_PWRM_IPC_STS_ERROR) != 0) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "PmcSendCommand() Error: IPC_STS=0x%08X\n", IpcSts));
+ return Status;
+ }
+
+ if (ReadBufPtr != NULL) {
+ //
+ // Fill the ReadBuffer contents with the Data that needs to be read from PMC
+ //
+ ReadBufPtr->Buf0 = MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF0);
+ ReadBufPtr->Buf1 = MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF1);
+ ReadBufPtr->Buf2 = MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF2);
+ ReadBufPtr->Buf3 = MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF3);
+
+ DEBUG ((DEBUG_INFO, "RBUF0=0x%08X, RBUF1=0x%08X, RBUF2=0x%08X, RBUF3=0x%08X \n", ReadBufPtr->Buf0, ReadBufPtr->Buf1, ReadBufPtr->Buf2, ReadBufPtr->Buf3));
+ }
+
+ return Status;
+}
+
+/**
+ This function checks if SCI interrupt is enabled
+
+ @retval SCI Enable state
+**/
+BOOLEAN
+PmcIsSciEnabled (
+ VOID
+ )
+{
+ return ((IoRead8 (PmcGetAcpiBase () + R_ACPI_IO_PM1_CNT) & B_ACPI_IO_PM1_CNT_SCI_EN) != 0);
+}
+
+/**
+ This function triggers Software GPE
+**/
+VOID
+PmcTriggerSwGpe (
+ VOID
+ )
+{
+ IoOr32 (PmcGetAcpiBase () + R_ACPI_IO_GPE_CNTL, B_ACPI_IO_GPE_CNTL_SWGPE_CTRL);
+}
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes aligned. It is IO space, so must not exceed 0xFFFF.
+ Only address matching PcdAcpiBaseAddress is the acceptable value for ACPI IO Base
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PmcSetAcpiBase (
+ IN UINT16 Address
+ )
+{
+
+ if (Address != PcdGet16 (PcdAcpiBaseAddress)) {
+ DEBUG ((DEBUG_ERROR, "PmcSetAcpiBase Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PsfSetPmcAbase (Address);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH PWRM base address.
+ Only 0xFE000000 (PCH_PWRM_BASE_ADDRESS) is the acceptable value for PWRMBASE
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PmcSetPwrmBase (
+ IN UINT32 Address
+ )
+{
+ UINT64 PmcBase;
+
+ if (Address != PCH_PWRM_BASE_ADDRESS) {
+ DEBUG ((DEBUG_ERROR, "PmcSetPwrmBase Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC,
+ 0
+ );
+ if (PciSegmentRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Disable PWRMBASE in PMC Device first before changing PWRM base address.
+ //
+ PciSegmentAnd16 (
+ PmcBase + PCI_COMMAND_OFFSET,
+ (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE
+ );
+
+ //
+ // Program PWRMBASE in PMC Device
+ //
+ PciSegmentAndThenOr32 (
+ PmcBase + R_PMC_CFG_BASE,
+ (UINT32) (~B_PMC_CFG_PWRM_BASE_MASK),
+ Address
+ );
+
+ //
+ // Enable PWRMBASE in PMC Device
+ //
+ PciSegmentOr16 (
+ PmcBase + PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ This function checks if function disable (static and non-static power gating)
+ configuration is locked
+
+ @retval lock state
+**/
+BOOLEAN
+PmcIsFunctionDisableConfigLocked (
+ VOID
+ )
+{
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1) & B_PMC_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK) != 0);
+}
+
+/**
+ Check if MODPHY SUS PG is supported
+
+ @retval Status of MODPHY SUS PG support
+**/
+BOOLEAN
+PmcIsModPhySusPgSupported (
+ VOID
+ )
+{
+ if (IsPchLp ()) {
+ //
+ // MPHY SUS PG supported on PCH-LP only:
+ //
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if ISH is function disabled
+ by static power gating
+
+ @retval ISH device state
+**/
+BOOLEAN
+PmcIsIshFunctionDisabled (
+ VOID
+ )
+{
+ //
+ // Get PG info from PWRMBASE + ST_PG_FDIS_PMC_1
+ //
+ return ((MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1)) & B_PMC_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC) != 0);
+}
+
+/**
+ This function checks if ISH device is supported (not disabled by fuse)
+
+ @retval ISH support state
+**/
+BOOLEAN
+PmcIsIshSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_DIS_RD_2
+ //
+ return ((MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2)) & B_PMC_PWRM_FUSE_DIS_RD_2_ISH_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function disables ISH device by static power gating.
+ For static power gating to take place Global Reset, G3 or DeepSx transition must happen.
+**/
+VOID
+PmcStaticDisableIsh (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_1[5] = 1b to statically disable ISH Controller
+ //
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1, B_PMC_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC);
+}
+
+/**
+ This function enables ISH device by disabling static power gating.
+ Static power gating disabling takes place after Global Reset, G3 or DeepSx transition.
+**/
+VOID
+PmcEnableIsh (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_1[5] = 0b to enable ISH controller
+ //
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1, (UINT32) (~B_PMC_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC));
+}
+
+/**
+ This function checks if GbE is function disabled
+ by static power gating
+
+ @retval GbE device state
+**/
+BOOLEAN
+PmcIsGbeFunctionDisabled (
+ VOID
+ )
+{
+ //
+ // Get PG info from PWRMBASE + ST_PG_FDIS_PMC_1
+ //
+ return ((MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1)) & B_PMC_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC) != 0);
+}
+
+/**
+ This function disables GbE device by static power gating and enables ModPHY SPD gating (PCH-LP only).
+ For static power gating to take place Global Reset, G3 or DeepSx transition must happen.
+**/
+VOID
+PmcStaticDisableGbe (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_1[0] = 1b to statically disable GbE Controller
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1, B_PMC_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set MSPDRTREQ:
+ // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[13] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ PmcGbeModPhyPowerGating ();
+ }
+}
+
+/**
+ This function enables GbE device by disabling static power gating.
+ Static power gating disabling takes place after Global Reset, G3 or DeepSx transition.
+**/
+VOID
+PmcEnableGbe (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_1[0] = 0b to enable GbE controller
+ //
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1, (UINT32) ~B_PMC_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC);
+}
+
+/**
+ This function checks if GbE device is supported (not disabled by fuse)
+
+ @retval GbE support state
+**/
+BOOLEAN
+PmcIsGbeSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function disables (non-static power gating) HDA device
+**/
+VOID
+PmcDisableHda (
+ VOID
+ )
+{
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_NST_PG_FDIS_1, B_PMC_PWRM_NST_PG_FDIS_1_ADSP_FDIS_PMC);
+}
+
+/**
+ This function checks if Cnvi device is supported (not disabled by fuse)
+
+ @retval Cnvi support state
+**/
+BOOLEAN
+PmcIsCnviSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_CNVI_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function checks if CNVi is function disabled
+ by static power gating
+
+ @retval GbE device state
+**/
+BOOLEAN
+PmcIsCnviFunctionDisabled (
+ VOID
+ )
+{
+ //
+ // Get PG info from PWRMBASE + ST_PG_FDIS_PMC_1
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1) & B_PMC_PWRM_ST_PG_FDIS_PMC_1_CNVI_FDIS_PMC) != 0);
+}
+
+/**
+ This function enables CNVi device by disabling static power gating.
+ Static power gating disabling takes place after Global Reset, G3 or DeepSx transition.
+**/
+VOID
+PmcEnableCnvi (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_1 to enable CNVi controller
+ //
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1, (UINT32) ~B_PMC_PWRM_ST_PG_FDIS_PMC_1_CNVI_FDIS_PMC);
+}
+
+/**
+ This function disables CNVi device by static power gating.
+ For static power gating to take place Global Reset, G3 or DeepSx transition must happen.
+**/
+VOID
+PmcStaticDisableCnvi (
+ VOID
+ )
+{
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_1, B_PMC_PWRM_ST_PG_FDIS_PMC_1_CNVI_FDIS_PMC);
+}
+
+/**
+ This function disables (non-static power gating) PCIe Root Port and enables ModPHY SPD gating (PCH-LP only).
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+**/
+VOID
+PmcDisablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ UINT32 NstPgFdis1Mask;
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+ //
+ // Set PchPwrmBase + NST_PG_FDIS_1 to function disable PCIE port in PMC
+ //
+ if (IsPchH () && RpIndex >= 20) {
+ NstPgFdis1Mask = B_PCH_H_PMC_PWRM_NST_PG_FDIS_1_PCIE_F0_FDIS_PMC << (RpIndex % 20);
+ } else {
+ NstPgFdis1Mask = B_PMC_PWRM_NST_PG_FDIS_1_PCIE_A0_FDIS_PMC << RpIndex;
+ }
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, NstPgFdis1Mask);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set MSPDRTREQ:
+ // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[26:0] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ if (RpIndex <= 11) {
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_A0 << RpIndex);
+ } else {
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_D0 << (RpIndex - 12));
+ }
+ }
+}
+
+/**
+ This function disables (non-static power gating) xHCI and enables ModPHY SPD gating (PCH-LP only).
+**/
+VOID
+PmcDisableXhci (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 [0] = 1b
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, B_PMC_PWRM_NST_PG_FDIS_1_XHCI_FDIS_PMC);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set MSPDRTREQ:
+ // PchPwrmBase + R_PWRM_MODPHY_PM_CFG5[14] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_XHCI);
+ }
+}
+
+/**
+ This function disables (non-static power gating) XDCI and enables ModPHY SPD gating (PCH-LP only).
+**/
+VOID
+PmcDisableXdci (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 [26] = 1b to disable XDCI Controller in PMC
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, B_PMC_PWRM_NST_PG_FDIS_1_XDCI_FDIS_PMC);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set MSPDRTREQ:
+ // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[15] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_XDCI);
+ }
+}
+
+/**
+ This function checks if XDCI device is supported (not disabled by fuse)
+
+ @retval XDCI support state
+**/
+BOOLEAN
+PmcIsXdciSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_OTG_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function locks HOST SW power gating control
+**/
+VOID
+PmcLockHostSwPgCtrl (
+ VOID
+ )
+{
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_HSWPGCR1, B_PMC_PWRM_SW_PG_CTRL_LOCK);
+}
+
+/**
+ This function checks if HOST SW Power Gating Control is locked
+
+ @retval lock state
+**/
+BOOLEAN
+PmcIsHostSwPgCtrlLocked (
+ VOID
+ )
+{
+ //
+ // Get lock info from PWRMBASE + HSWPGCR1
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_HSWPGCR1) & B_PMC_PWRM_SW_PG_CTRL_LOCK) != 0);
+}
+
+/**
+ This function checks if LAN wake from DeepSx is enabled
+
+ @retval Lan Wake state
+**/
+BOOLEAN
+PmcIsLanDeepSxWakeEnabled (
+ VOID
+ )
+{
+ //
+ // Get wake info from PWRMBASE + DSX_CFG
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_DSX_CFG) & (UINT32) B_PMC_PWRM_DSX_CFG_LAN_WAKE_EN) != 0);
+}
+
+/**
+ Disables USB2 Core PHY PowerGating during power on for Chipsetinit table update
+**/
+VOID
+PmcUsb2CorePhyPowerGatingDisable (
+ VOID
+ )
+{
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_CFG, (UINT32) ~B_PMC_PWRM_CFG_ALLOW_USB2_CORE_PG);
+}
+
+
+/**
+ This function reads CPU Early Power-on Configuration (EPOC)
+
+ @retval CPU EPOC value
+**/
+UINT32
+PmcGetCpuEpoc (
+ VOID
+ )
+{
+ return MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_CPU_EPOC);
+}
+
+/**
+ This function sets CPU Early Power-on Configuration (EPOC)
+
+ @param[in] CpuEpocValue CPU EPOC value
+**/
+VOID
+PmcSetCpuEpoc (
+ IN UINT32 CpuEpocValue
+ )
+{
+ MmioWrite32 (PmcGetPwrmBase () + R_PMC_PWRM_CPU_EPOC, CpuEpocValue);
+}
+
+/**
+ This function sets DRAM_RESET# Control Pin value
+
+ @param[in] DramResetVal 0: Pin output is low
+ 1: Pin output is tri-stated
+**/
+VOID
+PmcSetDramResetCtlState (
+ IN UINT32 DramResetVal
+ )
+{
+ ASSERT (DramResetVal < 2);
+
+ MmioAndThenOr32 (
+ PmcGetPwrmBase () + R_PMC_PWRM_CFG2,
+ (UINT32)~B_PMC_PWRM_CFG2_DRAM_RESET_CTL,
+ DramResetVal << N_PMC_PWRM_CFG2_DRAM_RESET_CTL
+ );
+}
+
+/**
+ This function enables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh
+**/
+VOID
+PmcEnableCf9GlobalReset (
+ VOID
+ )
+{
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_ETR3, (UINT32) (B_PMC_PWRM_ETR3_CF9GR));
+}
+
+/**
+ This function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+**/
+VOID
+PmcDisableCf9GlobalReset (
+ VOID
+ )
+{
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ETR3, (UINT32) ~B_PMC_PWRM_ETR3_CF9GR);
+}
+
+/**
+ This function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+ Global Reset configuration is locked after programming
+**/
+VOID
+PmcDisableCf9GlobalResetWithLock (
+ VOID
+ )
+{
+ MmioAndThenOr32 (
+ PmcGetPwrmBase () + R_PMC_PWRM_ETR3,
+ (UINT32) ~B_PMC_PWRM_ETR3_CF9GR,
+ (UINT32) B_PMC_PWRM_ETR3_CF9LOCK
+ );
+}
+
+/**
+ This function disables CF9 reset without Resume Well reset.
+ Cf9 0x6/0xE reset will also reset resume well logic.
+**/
+VOID
+PmcDisableCf9ResetWithoutResumeWell (
+ VOID
+ )
+{
+
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ETR3, (UINT32) ~B_PMC_PWRM_ETR3_CWORWRE);
+}
+
+/**
+ This function clears RTC Power Failure status (RTC_PWR_FLR)
+**/
+VOID
+PmcClearRtcPowerFailureStatus (
+ VOID
+ )
+{
+ //
+ // Set B_PMC_PWRM_GEN_PMCON_B_RTC_PWR_STS to 0 to clear it.
+ //
+ MmioAnd8 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B), (UINT8) (~B_PMC_PWRM_GEN_PMCON_B_RTC_PWR_STS));
+}
+
+/**
+ This function enables PCI Express* PME events
+**/
+VOID
+PmcEnablePciExpressPmeEvents (
+ VOID
+ )
+{
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B, B_PMC_PWRM_GEN_PMCON_B_BIOS_PCI_EXP_EN);
+}
+
+/**
+ This function sets eSPI SMI Lock
+**/
+VOID
+PmcLockEspiSmi (
+ VOID
+ )
+{
+ MmioAndThenOr8 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
+ (UINT8) ~((B_PMC_PWRM_GEN_PMCON_A_PWR_FLR | B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS) >> 8),
+ B_PMC_PWRM_GEN_PMCON_A_ESPI_SMI_LOCK >> 8
+ );
+}
+
+/**
+ This function checks if eSPI SMI Lock is set
+
+ @retval eSPI SMI Lock state
+**/
+BOOLEAN
+PmcIsEspiSmiLockSet (
+ VOID
+ )
+{
+ return ((MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A)) & B_PMC_PWRM_GEN_PMCON_A_ESPI_SMI_LOCK) != 0);
+}
+
+/**
+ This function sets SW SMI Rate.
+
+ @param[in] SwSmiRate Refer to PMC_SWSMI_RATE for possible values
+**/
+VOID
+PmcSetSwSmiRate (
+ IN PMC_SWSMI_RATE SwSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 SwSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_1_5MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_16MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_32MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_64MS
+ };
+
+ ASSERT (SwSmiRate <= PmcSwSmiRate64ms);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // SWSMI_RATE_SEL BIT (PWRMBASE offset 1020h[7:6]) bits are in RTC well
+ //
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL,
+ SwSmiRateRegVal[SwSmiRate]
+ );
+}
+
+/**
+ This function sets Periodic SMI Rate.
+
+ @param[in] PeriodicSmiRate Refer to PMC_PERIODIC_SMI_RATE for possible values
+**/
+VOID
+PmcSetPeriodicSmiRate (
+ IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 PeriodicSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_8S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_16S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_32S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_64S
+ };
+
+ ASSERT (PeriodicSmiRate <= PmcPeriodicSmiRate64s);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_PER_SMI_SEL,
+ PeriodicSmiRateRegVal[PeriodicSmiRate]
+ );
+}
+
+/**
+ This function reads Power Button Level
+
+ @retval State of PWRBTN# signal (0: Low, 1: High)
+**/
+UINT8
+PmcGetPwrBtnLevel (
+ VOID
+ )
+{
+ if (MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B) & B_PMC_PWRM_GEN_PMCON_B_PWRBTN_LVL) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ This function gets Group to GPE0 configuration
+
+ @param[out] GpeDw0Value GPIO Group to GPE_DW0 assignment
+ @param[out] GpeDw1Value GPIO Group to GPE_DW1 assignment
+ @param[out] GpeDw2Value GPIO Group to GPE_DW2 assignment
+**/
+VOID
+PmcGetGpioGpe (
+ OUT UINT32 *GpeDw0Value,
+ OUT UINT32 *GpeDw1Value,
+ OUT UINT32 *GpeDw2Value
+ )
+{
+ UINT32 Data32;
+
+ Data32 = MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GPIO_CFG));
+
+ *GpeDw0Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW0) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW0);
+ *GpeDw1Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW1) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW1);
+ *GpeDw2Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW2) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW2);
+}
+
+/**
+ This function sets Group to GPE0 configuration
+
+ @param[out] GpeDw0Value GPIO Group to GPE_DW0 assignment
+ @param[out] GpeDw1Value GPIO Group to GPE_DW1 assignment
+ @param[out] GpeDw2Value GPIO Group to GPE_DW2 assignment
+**/
+VOID
+PmcSetGpioGpe (
+ IN UINT32 GpeDw0Value,
+ IN UINT32 GpeDw1Value,
+ IN UINT32 GpeDw2Value
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Program GPIO_CFG register
+ //
+ Data32And = (UINT32) ~(B_PMC_PWRM_GPIO_CFG_GPE0_DW2 | B_PMC_PWRM_GPIO_CFG_GPE0_DW1 | B_PMC_PWRM_GPIO_CFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GpeDw2Value << N_PMC_PWRM_GPIO_CFG_GPE0_DW2) |
+ (GpeDw1Value << N_PMC_PWRM_GPIO_CFG_GPE0_DW1) |
+ (GpeDw0Value << N_PMC_PWRM_GPIO_CFG_GPE0_DW0));
+
+ MmioAndThenOr32 (
+ (PmcGetPwrmBase () + R_PMC_PWRM_GPIO_CFG),
+ Data32And,
+ Data32Or
+ );
+}
+
+/**
+ Disable SLP_S0# assertion when system is in debug mode
+**/
+VOID
+PmcDisableSlpS0AssertionInDebugMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+
+ Status = PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_SLP_CTRL, 0, 4, &Wbuf, NULL);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Enable SLP_S0# assertion even when system is in debug mode
+**/
+VOID
+PmcEnableSlpS0AssertionInDebugMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+
+ Wbuf.Buf0 = 1;
+ Status = PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_SLP_CTRL, 0, 4, &Wbuf, NULL);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function gets NMI regsiter.
+
+ @retval NMI register setting
+**/
+UINT32
+PmcGetNmiControl (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+ PMC_IPC_COMMAND_BUFFER Rbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+ ZeroMem (&Rbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+ //
+ // WBUF0 = 2 for NMI delivery control and status register (entire register PCR[ITSS] 0x3330)
+ //
+ Wbuf.Buf0 = V_PMC_PWRM_IPC_CMD_WBUF0_PROXY_NMI;
+ Status = PmcSendCommand (
+ V_PMC_PWRM_IPC_CMD_COMMAND_PROXY,
+ V_PMC_PWRM_IPC_CMD_CMD_ID_PROXY_READ,
+ 4,
+ &Wbuf,
+ &Rbuf
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Rbuf.Buf0;
+}
+
+/**
+ This function sets the NMI register
+
+ @param[in] NmiRegister The whole NMI register
+**/
+VOID
+PmcSetNmiControl (
+ UINT32 NmiRegister
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+ //
+ // WBUF0 = 2 for NMI delivery control and status register (entire register PCR[ITSS] 0x3330)
+ //
+ Wbuf.Buf0 = V_PMC_PWRM_IPC_CMD_WBUF0_PROXY_NMI;
+ Wbuf.Buf1 = NmiRegister;
+ Status = PmcSendCommand (
+ V_PMC_PWRM_IPC_CMD_COMMAND_PROXY,
+ V_PMC_PWRM_IPC_CMD_CMD_ID_PROXY_WRITE,
+ 8,
+ &Wbuf,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function enables GBE ModPHY SPD gating.
+**/
+VOID
+PmcGbeModPhyPowerGating (
+ VOID
+ )
+{
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set B_PCH_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_GBE ModPHY SPD RT Request
+ //
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_GBE);
+ }
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibClient.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibClient.c
new file mode 100644
index 0000000000..2411a2be23
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibClient.c
@@ -0,0 +1,73 @@
+/** @file
+ PCH PMC Private Library implementation 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
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Library/SataLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchRegsPmc.h>
+
+#include "PmcPrivateLibInternal.h"
+
+/**
+ This function disables (non-static power gating) SATA and enables ModPHY SPD gating (PCH-LP only).
+
+ @param[in] SataCtrlIndex SATA controller index
+**/
+VOID
+PmcDisableSata (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 [22] = 1b to disable SATA Controller in PMC
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, B_PMC_PWRM_NST_PG_FDIS_1_SATA_FDIS_PMC);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // MPHY SUS PG supported on PCH-LP only:
+ //
+ // Set MSPDRTREQ:
+ // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[12] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_SATA);
+ }
+}
+
+/**
+ This function checks if SATA device is supported (not disabled by fuse)
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA support state
+**/
+BOOLEAN
+PmcIsSataSupported (
+ UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
+
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_SATA_FUSE_SS_DIS) == 0);
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibCnl.c
new file mode 100644
index 0000000000..847be42937
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibCnl.c
@@ -0,0 +1,360 @@
+/** @file
+ PCH PMC Private Library implementation 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
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+#include <Library/SataLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchRegsPmc.h>
+
+#include "PmcPrivateLibInternal.h"
+
+/**
+ This function disables Trace Hub by enabling power gating
+**/
+VOID
+PmcDisableTraceHub (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+
+ Wbuf.Buf0 = BIT0;
+ Status = PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_NPK_STATE, 0, 4, &Wbuf, NULL);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function enables Trace Hub by disabling power gating
+**/
+VOID
+PmcEnableTraceHub (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PMC_IPC_COMMAND_BUFFER Wbuf;
+
+ ZeroMem (&Wbuf, sizeof (PMC_IPC_COMMAND_BUFFER));
+
+ Wbuf.Buf0 = BIT1;
+ Status = PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_NPK_STATE, 0, 4, &Wbuf, NULL);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function is part of PMC init and configures which clock wake signals should
+ set the SLOW_RING, SA, FAST_RING_CF and SLOW_RING_CF indication sent up to the CPU/PCH
+**/
+VOID
+PmcInitClockWakeEnable (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+ if (IsPchLp () && (PchStepping () < PCH_B0)) {
+ ///
+ /// PWRMBASE + 0x1880 = 0x0
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING, 0x0);
+ } else {
+ ///
+ /// PWRMBASE + 0x1880 = 0x2F8FBB01
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING, 0x2F8FBB01);
+ }
+
+ if (IsPchLp ()) {
+ if (PchStepping () < PCH_B0) {
+ ///
+ /// PWRMBASE + 0x1884 = 0x0
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING2, 0x0);
+ } else {
+ ///
+ /// PWRMBASE + 0x1884
+ /// PCH-LP: 0x0280C7E1
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING2, 0x0280C7E1);
+ }
+ } else {
+ ///
+ /// PWRMBASE + 0x1884
+ /// PCH-H: 0x0280D7E1
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING2, 0x0280D7E1);
+ }
+
+ if (IsPchLp () && (PchStepping () < PCH_B0)) {
+ ///
+ /// PWRMBASE + 0x1888 = 0x0
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA, 0x0);
+ ///
+ /// PWRMBASE + 0x188C = 0x0
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA2, 0x0);
+ } else {
+ ///
+ /// PWRMBASE + 0x1888 = 0x2F8FAB01
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA, 0x2F8FAB01);
+
+ ///
+ /// PWRMBASE + 0x188C
+ /// PCH-LP: 0x0280C7E1
+ /// PCH-H: 0x0280D7E1
+ ///
+ if (IsPchLp ()) {
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA2, 0x0280C7E1);
+ } else {
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA2, 0x0280D7E1);
+ }
+ }
+
+ if (IsPchLp () && (PchStepping () < PCH_B0)) {
+ ///
+ /// PWRMBASE + 0x1898 = 0x0
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING_CF, 0x0);
+ } else {
+ ///
+ /// PWRMBASE + 0x1898 = 0x00018000
+ ///
+ MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING_CF, 0x00018000);
+ }
+}
+
+/**
+ This function configures PWRMBASE + 0x1E00 register
+**/
+VOID
+PmcConfigureRegPwrm1E00 (
+ VOID
+ )
+{
+ ///
+ /// PWRMBASE + 0x1E00[31,30] = 1,1
+ /// PWRMBASE + 0x1E00[29] = 0
+ /// PWRMBASE + 0x1E00[10:6] = 0
+ /// PWRMBASE + 0x1E00[3:0] = 2
+ ///
+ MmioAndThenOr32 (
+ PmcGetPwrmBase () + R_PMC_PWRM_1E00,
+ (UINT32) ~(BIT29 | (0x1F << 6) | 0xF),
+ BIT31 | BIT30 | 2
+ );
+}
+
+/**
+ This function configures Misc PM_SYNC events settings
+**/
+VOID
+PmcConfigurePmSyncEventsSettings (
+ VOID
+ )
+{
+ ///
+ /// PWRMBASE + 0x18C0 = 0x00000A20
+ ///
+ MmioWrite32 (PmcGetPwrmBase () + R_PMC_PWRM_EN_MISC_EVENT, 0x00000A20);
+}
+
+/**
+ This function enables all SerailIo devices.
+ Static power gating disabling takes place after Global Reset, G3 or DeepSx transition.
+**/
+VOID
+PmcEnableSerialIo (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_2
+ //
+ MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_2, (UINT32)~B_PMC_PWRM_ST_PG_FDIS_PMC_2_SERIALIO);
+}
+
+/**
+ This function disables (static power gating) all SerailIo devices.
+ For SerialIo controllers they can be power gated only if all of them are to be disabled.
+ They cannot be statically power gated separately.
+ For static power gating to take place Global Reset, G3 or DeepSx transition must happen.
+**/
+VOID
+PmcStaticDisableSerialIo (
+ VOID
+ )
+{
+ //
+ // Set PWRMBASE + ST_PG_FDIS_PMC_2
+ //
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_2, B_PMC_PWRM_ST_PG_FDIS_PMC_2_SERIALIO);
+}
+
+/**
+ This function checks if all SerialIo devices are statically disabled (static power gating)
+
+ @retval SerialIo disable state
+**/
+BOOLEAN
+PmcIsSerialIoStaticallyDisabled (
+ VOID
+ )
+{
+ //
+ // Check if all SerialIo controllers are statically disabled in PMC
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_2) & B_PMC_PWRM_ST_PG_FDIS_PMC_2_SERIALIO) == B_PMC_PWRM_ST_PG_FDIS_PMC_2_SERIALIO);
+}
+
+/**
+ This function checks if SerialIo device is supported (not disabled by fuse)
+
+ @retval SerialIo support state
+**/
+BOOLEAN
+PmcIsSerialIoSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_SERIALIO_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function disables (non-static power gating) SCS eMMC controller and enables ModPHY SPD gating (PCH-LP only).
+**/
+VOID
+PmcDisableScsEmmc (
+ VOID
+ )
+{
+ ASSERT (IsPchLp ());
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 to disable SCS Controller in PMC
+ //
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_NST_PG_FDIS_1, B_PCH_LP_PMC_PWRM_NST_PG_FDIS_1_EMMC_FDIS_PMC);
+}
+
+/**
+ This function disables (non-static power gating) SCS SD Card controller and enables ModPHY SPD gating (PCH-LP only).
+**/
+VOID
+PmcDisableScsSdCard (
+ VOID
+ )
+{
+ UINT32 ScsDevicePgMask;
+
+ if (IsPchLp ()) {
+ ScsDevicePgMask = B_PCH_LP_PMC_PWRM_NST_PG_FDIS_1_SDCARD_FDIS_PMC;
+ } else {
+ ScsDevicePgMask = B_PCH_H_PMC_PWRM_NST_PG_FDIS_1_SDCARD_FDIS_PMC;
+ }
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 to disable SCS Controller in PMC
+ //
+ MmioOr32 (PmcGetPwrmBase () + R_PMC_PWRM_NST_PG_FDIS_1, ScsDevicePgMask);
+}
+
+/**
+ This function disables (non-static power gating) SCS UFS controller and enables ModPHY SPD gating (PCH-LP only).
+
+ @param[in] UfsNum SCS UFS Device
+**/
+VOID
+PmcDisableScsUfs (
+ IN UINT32 UfsNum
+ )
+{
+ UINT32 PchPwrmBase;
+
+ ASSERT ((UfsNum == 0) && IsPchLp ());
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // Set PWRMBASE + NST_PG_FDIS_1 to disable SCS Controller in PMC
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, B_PCH_LP_PMC_PWRM_NST_PG_FDIS_1_UFS_FDIS_PMC);
+
+ if (PmcIsModPhySusPgSupported ()) {
+ //
+ // Set MSPDRTREQ:
+ // PchPwrmBase + R_PWRM_MODPHY_PM_CFG5[16] = 1 to enable ASL code trigger request for ModPHY SPD gating.
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_PM_CFG5_MSPDRTREQ_UFS2);
+ }
+}
+
+/**
+ This function checks if SCS eMMC device is supported (not disabled by fuse)
+
+ @retval SCS device support state
+**/
+BOOLEAN
+PmcIsScsEmmcSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_EMMC_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function checks if SCS SD Card device is supported (not disabled by fuse)
+
+ @retval SCS device support state
+**/
+BOOLEAN
+PmcIsScsSdCardSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_SDX_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function checks if SCS UFS device is supported (not disabled by fuse)
+
+ @param[in] UfsNum SCS UFS Device
+
+ @retval SCS device support state
+**/
+BOOLEAN
+PmcIsScsUfsSupported (
+ IN UINT32 UfsNum
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_UFSX2_FUSE_SS_DIS) == 0);
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c
new file mode 100644
index 0000000000..bbe944da5c
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c
@@ -0,0 +1,194 @@
+/** @file
+ PCH private 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/PchCycleDecodingLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PmcLib.h>
+#include <Private/Library/PmcPrivateLib.h>
+
+/**
+ This function locks down PMC (DebugModeLock)
+**/
+VOID
+PmcLockWithS3BootScript (
+ VOID
+ )
+{
+
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // Set PWRM_CFG[27] prior to OS.
+ //
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_CFG, B_PMC_PWRM_CFG_DBG_MODE_LOCK);
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (PchPwrmBase + R_PMC_PWRM_CFG),
+ 1,
+ (VOID *) ((UINTN) PchPwrmBase + R_PMC_PWRM_CFG)
+ );
+
+}
+
+/**
+ This S3 BootScript only function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+**/
+VOID
+PmcDisableCf9GlobalResetInS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data;
+
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ Data = MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3);
+
+ Data &= (UINT32) ~B_PMC_PWRM_ETR3_CF9GR;
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PchPwrmBase +
+ R_PMC_PWRM_ETR3,
+ 1,
+ &Data
+ );
+}
+
+/**
+ This S3 BootScript only function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+ Global Reset configuration is locked after programming
+**/
+VOID
+PmcDisableCf9GlobalResetWithLockInS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data;
+
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ Data = MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3);
+
+ Data &= (UINT32) ~B_PMC_PWRM_ETR3_CF9GR;
+ Data |= (UINT32) B_PMC_PWRM_ETR3_CF9LOCK;
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PchPwrmBase +
+ R_PMC_PWRM_ETR3,
+ 1,
+ &Data
+ );
+}
+
+/**
+ This function sets SLP_SX Stretching Policy and adds
+ lock setting to S3 Boot Script
+**/
+VOID
+PmcLockSlpSxStretchingPolicyWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioOr8 (
+ (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B + 2),
+ (UINT8) ((B_PMC_PWRM_GEN_PMCON_B_SLPSX_STR_POL_LOCK) >> 16)
+ );
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B + 2),
+ 1,
+ (VOID *) ((UINTN) PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B + 2)
+ );
+}
+
+/**
+ This function sets SMI Lock with S3 Boot Script programming
+**/
+VOID
+PmcLockSmiWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioOr8 ((PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B), B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK);
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B),
+ 1,
+ (VOID *) ((UINTN) PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B)
+ );
+}
+
+/**
+ This function locks static power gating configuration with S3 Boot Script programming
+**/
+VOID
+PmcLockFunctionDisableConfigWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioOr32 (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1, (UINT32) (B_PMC_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK));
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1),
+ 1,
+ (VOID *) (UINTN) (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1)
+ );
+}
+
+/**
+ This function locks PMC Set Strap Message interface with S3 Boot Script programming
+**/
+VOID
+PmcLockSetStrapMsgInterfaceWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioOr32 ((UINTN) (PchPwrmBase + R_PMC_PWRM_SSML), B_PMC_PWRM_SSML_SSL);
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PchPwrmBase + R_PMC_PWRM_SSML),
+ 1,
+ (VOID *) (UINTN) (PchPwrmBase + R_PMC_PWRM_SSML)
+ );
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.c
new file mode 100644
index 0000000000..9c722bce07
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.c
@@ -0,0 +1,356 @@
+/** @file
+ This file contains routines for PEI GPIO Helpers Lib
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/HobLib.h>
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+#include <Private/Library/GpioHelpersLib.h>
+
+extern EFI_GUID gGpioLibUnlockHobGuid;
+
+//
+// GPIO Lock HOB
+// Stores information on GPIO pads that should be left unlocked
+//
+typedef struct {
+ //
+ // GPIO PadConfig unlock data
+ //
+ UINT32 PadConfig;
+ //
+ // GPIO Output unlock data
+ //
+ UINT32 OutputState;
+} GPIO_UNLOCK_HOB_DATA;
+
+/**
+ This procedure will get index of GPIO Unlock HOB structure for selected GroupIndex and DwNum.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+
+ @retval GpioUnlockHobIndex
+**/
+STATIC
+UINT32
+GpioUnlockDataIndex (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ UINT32 GpioUnlockDataIndex;
+ UINT32 Index;
+
+ GpioUnlockDataIndex = 0;
+
+ for (Index = 0; Index < GroupIndex; Index++) {
+ GpioUnlockDataIndex += GPIO_GET_DW_NUM (GpioGetPadPerGroup (GpioGetGroupFromGroupIndex (Index))) + 1;
+ }
+
+ GpioUnlockDataIndex += DwNum;
+ return GpioUnlockDataIndex;
+}
+
+/**
+ This procedure will create GPIO HOB for storing unlock data
+
+ @retval Pointer to GPIO Unlock data structure
+**/
+STATIC
+GPIO_UNLOCK_HOB_DATA*
+GpioCreateUnlockData (
+ VOID
+ )
+{
+ VOID *HobData;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+ UINT32 GpioUnlockDataRecords;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+ GpioUnlockDataRecords = 0;
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ GpioUnlockDataRecords += GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)) + 1;
+ }
+
+ HobData = BuildGuidHob (&gGpioLibUnlockHobGuid, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
+ if (HobData == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (HobData, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
+
+ return (GPIO_UNLOCK_HOB_DATA*)HobData;
+}
+
+/**
+ This procedure will Get GPIO Unlock data structure for storing unlock data.
+ If HOB doesn't exist it will be created.
+
+ @param[out] GpioUnlockData pointer to GPIO Unlock data structure
+
+ @retval Length number of GPIO unlock data records
+**/
+STATIC
+UINT32
+GpioGetUnlockData (
+ GPIO_UNLOCK_HOB_DATA **GpioUnlockData
+ )
+{
+ VOID *Hob;
+
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ if (Hob == NULL) {
+ //
+ // It is the first time this function is used so create the HOB
+ //
+ *GpioUnlockData = GpioCreateUnlockData ();
+ if (*GpioUnlockData == NULL) {
+ return 0;
+ }
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ } else {
+ *GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
+ }
+ return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
+}
+
+/**
+ This procedure will get pointer to GPIO Unlock data structure.
+
+ @param[out] GpioUnlockData pointer to GPIO Unlock data structure
+
+ @retval Length number of GPIO unlock data records
+**/
+STATIC
+UINT32
+GpioLocateUnlockData (
+ GPIO_UNLOCK_HOB_DATA **GpioUnlockData
+ )
+{
+ VOID *Hob;
+
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ if (Hob == NULL) {
+ *GpioUnlockData = NULL;
+ return 0;
+ }
+
+ *GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
+ return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
+}
+
+/**
+ This procedure stores GPIO pad unlock information
+
+ @param[in] GpioPad GPIO pad
+ @param[in] GpioLockConfig GPIO Lock Configuration
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_LOCK_CONFIG GpioLockConfig
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 Index;
+
+ if (GpioLockConfig == GpioLockDefault) {
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ Index = GpioUnlockDataIndex (GroupIndex, GPIO_GET_DW_NUM (PadNumber));
+
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) == GpioPadConfigUnlock) {
+ GpioUnlockData[Index].PadConfig |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
+ }
+
+ if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioOutputStateUnlock) {
+ GpioUnlockData[Index].OutputState |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ if (UnlockedPads == 0) {
+ //
+ // No pads to be left unlocked
+ //
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioUnlockData[Index].PadConfig |= UnlockedPads;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ if (UnlockedPads == 0) {
+ //
+ // No pads to be left unlocked
+ //
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioUnlockData[Index].OutputState |= UnlockedPads;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ Length = GpioLocateUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return 0;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return 0;
+ }
+
+ return GpioUnlockData[Index].PadConfig;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ Length = GpioLocateUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return 0;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return 0;
+ }
+
+ return GpioUnlockData[Index].OutputState;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/GpioNameBufferPei.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/GpioNameBufferPei.c
new file mode 100644
index 0000000000..1b05378799
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBufferLib/GpioNameBufferPei.c
@@ -0,0 +1,68 @@
+/** @file
+ This file contains GpioMemLib implementation for PEI phase
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Private/Library/GpioNameBufferLib.h>
+
+STATIC CONST EFI_GUID mGpioNamesPrivateHobGuid = {0x9AE3138D, 0x4EBF, 0x4E90, {0x87, 0x96, 0x11, 0xD3, 0x10, 0x04, 0x60, 0x0A}};
+
+STATIC volatile BOOLEAN mGlobalMemoryWorking = FALSE;
+
+STATIC CHAR8 mGpioNameBuffer[GPIO_NAME_LENGTH_MAX];
+
+/**
+ Returns pointer to the buffer taken from GpioLib private HOB
+
+ @retval CHAR8* Pointer to the buffer
+**/
+STATIC
+CHAR8*
+GetBufferFromHob (
+ VOID
+ )
+{
+ VOID *Hob;
+ CHAR8 *GpioNameBuffer;
+
+ Hob = NULL;
+ GpioNameBuffer = NULL;
+
+ Hob = GetFirstGuidHob (&mGpioNamesPrivateHobGuid);
+ if (Hob != NULL){
+ GpioNameBuffer = (CHAR8*) GET_GUID_HOB_DATA (Hob);
+ } else {
+ GpioNameBuffer = (CHAR8*) BuildGuidHob (&mGpioNamesPrivateHobGuid, GPIO_NAME_LENGTH_MAX);
+ if (GpioNameBuffer == NULL){
+ DEBUG ((DEBUG_ERROR, "Failed to setup HOB for GPIO names lib\n"));
+ ASSERT (FALSE);
+ }
+ }
+ return GpioNameBuffer;
+}
+
+/**
+ Returns pointer to the global buffer to be used by GpioNamesLib
+
+ @retval CHAR8* Pointer to the buffer
+**/
+CHAR8*
+GpioGetStaticNameBuffer (
+ VOID
+ )
+{
+ mGlobalMemoryWorking = TRUE;
+
+ if (mGlobalMemoryWorking) {
+ return mGpioNameBuffer;
+ } else {
+ return GetBufferFromHob ();
+ }
+}
+
--
2.16.2.windows.1
next prev parent reply other threads:[~2019-08-17 0:53 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
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 [this message]
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=02A34F284D1DA44BB705E61F7180EF0AAEE12AA1@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