From: "Chiu, Chasel" <chasel.chiu@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>,
"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: Re: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI library instances
Date: Sat, 17 Aug 2019 01:13:33 +0000 [thread overview]
Message-ID: <3C3EFB470A303B4AB093197B6777CCEC5046234E@PGSMSX111.gar.corp.intel.com> (raw)
In-Reply-To: <20190817001603.30632-20-michael.a.kubacki@intel.com>
Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
> -----Original Message-----
> From: Kubacki, Michael A
> Sent: Saturday, August 17, 2019 8:16 AM
> To: devel@edk2.groups.io
> Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Chiu, Chasel
> <chasel.chiu@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Sinha, Ankit
> <ankit.sinha@intel.com>
> Subject: [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI
> library instances
>
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082
>
> Adds PCH PEI library class instances. These libraries may also be
> compatible in other boot phases as indicated by the library type.
>
> * PeiDxeSmmBiosLockLib
> * PeiDxeSmmGpioLib
> * PeiDxeSmmPchCycleDecodingLib
> * PeiDxeSmmPchDmiWithS3Lib
> * PeiDxeSmmPchEspiLib
> * PeiDxeSmmPchGbeLib
> * PeiDxeSmmPchHsioLib
> * PeiDxeSmmPchInfoLib
> * PeiDxeSmmPchPcieRpLib
> * PeiDxeSmmPchPcrLib
> * PeiDxeSmmPchPmcLib
> * PeiDxeSmmPchSbiAccessLib
> * PeiDxeSmmPchSerialIoLib
> * PeiDxeSmmPchSerialIoUartLib
> * PeiDxeSmmPchWdtCommonLib
> * PeiDxeSmmPmcLib
> * PeiDxeSmmSataLib
> * PeiOcWdtLib
> * PeiOcWdtLibNull
> * PeiPchPolicyLib
> * PeiPchResetLib
> * PeiResetSystemLib
> * PeiSpiLib
>
> Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
> Cc: Chasel Chiu <chasel.chiu@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ankit Sinha <ankit.sinha@intel.com>
> Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
> ---
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/PeiDx
> eSmmBiosLockLib.inf | 40 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSm
> mGpioLib.inf | 48 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingL
> ib/PeiDxeSmmPchCycleDecodingLib.inf | 42 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiDxe
> SmmPchEspiLib.inf | 38 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxe
> SmmPchGbeLib.inf | 38 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxe
> SmmPchHsioLib.inf | 37 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxe
> SmmPchInfoLibCnl.inf | 42 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiD
> xeSmmPchPcieRpLib.inf | 37 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeS
> mmPchPcrLib.inf | 35 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxe
> SmmPchPmcLib.inf | 36 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/P
> eiDxeSmmPchSbiAccessLib.inf | 35 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pei
> DxeSmmPchSerialIoLibCnl.inf | 39 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib
> /PeiDxeSmmPchSerialIoUartLib.inf | 35 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLi
> b/PeiDxeSmmPchWdtCommonLib.inf | 31 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeSm
> mPmcLib.inf | 43 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeSm
> mSataLibCnl.inf | 32 +
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
> | 39 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLib
> Null.inf | 24 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLi
> bCnl.inf | 86 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLi
> b.inf | 41 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSy
> stemLib.inf | 49 +
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf
> | 42 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibra
> ry.h | 117 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo
> LibPrivate.h | 45 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch
> SerialIoLibInternal.h | 16 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLi
> brary.h | 35 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/BiosLo
> ckLib.c | 98 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c
> | 553 ++++
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c
> | 2710 ++++++++++++++++++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNam
> es.c | 87 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativ
> eLib.c | 234 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingL
> ib/PchCycleDecodingLib.c | 1136 ++++++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchEsp
> iLib.c | 505 ++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGb
> eLib.c | 82 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsi
> oLib.c | 127 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo
> Lib.c | 272 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo
> LibClient.c | 87 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfo
> LibCnl.c | 386 +++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchP
> cieRpLib.c | 183 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLi
> b.c | 279 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPm
> cLib.c | 101 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/P
> chSbiAccessLib.c | 270 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch
> SerialIoLib.c | 516 ++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/Pch
> SerialIoLibCnl.c | 181 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartLib
> /PeiDxeSmmPchSerialIoUartLib.c | 372 +++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLi
> b/WdtCommon.c | 242 ++
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib.c
> | 330 +++
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.c
> | 41 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCdf
> .c | 101 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibCnl
> .c | 88 +
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
> | 130 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLib
> Null.c | 23 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPr
> intPolicy.c | 307 +++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy
> .c | 778 ++++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLi
> b.c | 739 ++++++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLi
> bCnl.c | 169 ++
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMe
> mPolicyLib.c | 318 +++
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
> | 109 +
>
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSy
> stemLib.c | 257 ++
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c
> | 217 ++
> 60 files changed, 13130 insertions(+)
>
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Pei
> DxeSmmBiosLockLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Pei
> DxeSmmBiosLockLib.inf
> new file mode 100644
> index 0000000000..6db81f6cf3
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Pei
> DxeSmmBiosLockLib.inf
> @@ -0,0 +1,40 @@
> +## @file
> +# BIOS LOCK library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmBiosLockLib
> +FILE_GUID = 64EBA6B1-CC36-4C2E-A0F5-D90199432E6C
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = BiosLockLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +DebugLib
> +PcdLib
> +PciSegmentLib
> +S3BootScriptLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +BiosLockLib.c
> +
> +
> +[Pcd]
> +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeS
> mmGpioLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeS
> mmGpioLib.inf
> new file mode 100644
> index 0000000000..00d06591fc
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeS
> mmGpioLib.inf
> @@ -0,0 +1,48 @@
> +## @file
> +# Component description file for the PeiDxeSmmGpioLib
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmGpioLib
> +FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = GpioLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF EBC
> +#
> +
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PrintLib
> +PchCycleDecodingLib
> +PchSbiAccessLib
> +PmcPrivateLib
> +GpioPrivateLib
> +SataLib
> +GpioHelpersLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +GpioLib.c
> +GpioLibrary.h
> +GpioNativeLib.c
> +GpioInit.c
> +GpioNames.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PeiDxeSmmPchCycleDecodingLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PeiDxeSmmPchCycleDecodingLib.inf
> new file mode 100644
> index 0000000000..2a53f42004
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PeiDxeSmmPchCycleDecodingLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +# PCH cycle decoding Lib.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchCycleDecodingLib
> +FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchCycleDecodingLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PciSegmentLib
> +PchInfoLib
> +PchPcrLib
> +PchDmiLib
> +PchEspiLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +PcAtChipsetPkg/PcAtChipsetPkg.dec
> +
> +[Sources]
> +PchCycleDecodingLib.c
> +
> +[Pcd]
> +gSiPkgTokenSpaceGuid.PcdSiHpetBaseAddress ## CONSUMES
> +gPcAtChipsetPkgTokenSpaceGuid.PcdIoApicBaseAddress ## CONSUMES
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiD
> xeSmmPchEspiLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiD
> xeSmmPchEspiLib.inf
> new file mode 100644
> index 0000000000..a775210984
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PeiD
> xeSmmPchEspiLib.inf
> @@ -0,0 +1,38 @@
> +## @file
> +# Component description file for the PeiDxeSmmPchEspiLib
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchEspiLib
> +FILE_GUID = 7F25F990-7989-4413-B414-1EDE557E9389
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchEspiLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF EBC
> +#
> +
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PchPcrLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchEspiLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiD
> xeSmmPchGbeLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiD
> xeSmmPchGbeLib.inf
> new file mode 100644
> index 0000000000..a685104249
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiD
> xeSmmPchGbeLib.inf
> @@ -0,0 +1,38 @@
> +## @file
> +# PCH Gbe Library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchGbeLib
> +FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchGbeLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PciSegmentLib
> +PchInfoLib
> +PchPcrLib
> +PchCycleDecodingLib
> +PmcPrivateLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchGbeLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiD
> xeSmmPchHsioLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiD
> xeSmmPchHsioLib.inf
> new file mode 100644
> index 0000000000..7c67e0fa20
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiD
> xeSmmPchHsioLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +# PCH HSIO Library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchHsioLib
> +FILE_GUID = 6B2D3D0D-9A04-4E7C-AE84-1C2EF2E00E2E
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchHsioLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +MmPciLib
> +PchInfoLib
> +PchPcrLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchHsioLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDx
> eSmmPchInfoLibCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiD
> xeSmmPchInfoLibCnl.inf
> new file mode 100644
> index 0000000000..b9781de810
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiD
> xeSmmPchInfoLibCnl.inf
> @@ -0,0 +1,42 @@
> +## @file
> +# PCH information library for PCH.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchInfoLibCnl
> +FILE_GUID = 455CD363-0E78-46B7-8DD3-634003F1614F
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchInfoLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PrintLib
> +PciSegmentLib
> +PchPcrLib
> +PmcPrivateLib
> +PcdLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchInfoLib.c
> +PchInfoLibClient.c
> +PchInfoLibCnl.c
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pe
> iDxeSmmPchPcieRpLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pe
> iDxeSmmPchPcieRpLib.inf
> new file mode 100644
> index 0000000000..b1ee095423
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pe
> iDxeSmmPchPcieRpLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +# PCH PCIE root port Library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchPcieRpLib
> +FILE_GUID = B4129C2C-E0C5-4E04-A82A-C61D4F0B2C75
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchPcieRpLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PciSegmentLib
> +PchInfoLib
> +PchPcrLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchPcieRpLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDx
> eSmmPchPcrLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDx
> eSmmPchPcrLib.inf
> new file mode 100644
> index 0000000000..0244e1c0c8
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDx
> eSmmPchPcrLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +# PCH PCR Library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchPcrLib
> +FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchPcrLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PchInfoLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchPcrLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiD
> xeSmmPchPmcLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiD
> xeSmmPchPmcLib.inf
> new file mode 100644
> index 0000000000..3b1f1e467b
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiD
> xeSmmPchPmcLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +# PEI/DXE/SMM PCH PMC Lib.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchPmcLib
> +FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchPmcLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +MmPciLib
> +PchCycleDecodingLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchPmcLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PeiDxeSmmPchSbiAccessLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PeiDxeSmmPchSbiAccessLib.inf
> new file mode 100644
> index 0000000000..ceb109168b
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PeiDxeSmmPchSbiAccessLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +# PCH SBI access library.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchSbiAccessLib
> +FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchSbiAccessLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PciSegmentLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchSbiAccessLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> eiDxeSmmPchSerialIoLibCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> eiDxeSmmPchSerialIoLibCnl.inf
> new file mode 100644
> index 0000000000..3bfada0b22
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> eiDxeSmmPchSerialIoLibCnl.inf
> @@ -0,0 +1,39 @@
> +## @file
> +# Component description file for PEI/DXE/SMM PCH Serial IO Lib.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchSerialIoLibCnl
> +FILE_GUID = 613A22A2-5736-40f8-909B-DF10EA389C72
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchSerialIoLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PcdLib
> +PciSegmentLib
> +GpioPrivateLib
> +PchPcrLib
> +PchSerialIoUartLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchSerialIoLib.c
> +PchSerialIoLibCnl.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.inf
> new file mode 100644
> index 0000000000..1becfc7a96
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +# Component description file for PCH Serial IO UART Lib.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchSerialIoUartLib
> +FILE_GUID = 55463A54-FD0D-4e8e-8D57-D54FAAEFDC2F
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PchSerialIoUartLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PchSerialIoLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PeiDxeSmmPchSerialIoUartLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/PeiDxeSmmPchWdtCommonLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/PeiDxeSmmPchWdtCommonLib.inf
> new file mode 100644
> index 0000000000..8a01a749bf
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/PeiDxeSmmPchWdtCommonLib.inf
> @@ -0,0 +1,31 @@
> +## @file
> +# Component description file for the PchWdtCommonLib
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = PeiDxeSmmPchWdtCommonLib
> + FILE_GUID = 171F78D2-0A52-4692-8830-AB693791EA23
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = PchWdtCommonLib
> +
> +[Sources]
> + WdtCommon.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + CoffeelakeSiliconPkg/SiPkg.dec
> +
> +[LibraryClasses]
> + IoLib
> + DebugLib
> + PmcLib
> +
> +[Pcd]
> + gSiPkgTokenSpaceGuid.PcdOcEnableWdtforDebug ## CONSUMES
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeS
> mmPmcLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeS
> mmPmcLib.inf
> new file mode 100644
> index 0000000000..78e212eeb0
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PeiDxeS
> mmPmcLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> +# PEI/DXE/SMM PCH PMC Lib.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPmcLib
> +FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = PmcLib
> +
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +PciSegmentLib
> +PchCycleDecodingLib
> +PchPcrLib
> +PchInfoLib
> +PmcPrivateLib
> +BaseMemoryLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Pcd]
> +gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
> +
> +
> +[Sources]
> +PmcLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeS
> mmSataLibCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeS
> mmSataLibCnl.inf
> new file mode 100644
> index 0000000000..128b348b3d
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/PeiDxeS
> mmSataLibCnl.inf
> @@ -0,0 +1,32 @@
> +## @file
> +# PEI/DXE/SMM PCH SATA library for Cannon Lake PCH.
> +#
> +# All function in this library is available for PEI, DXE, and SMM,
> +# But do not support UEFI RUNTIME environment call.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiDxeSmmPchSataLibCnl
> +FILE_GUID = 5163ECE3-5372-47E1-B057-2282E753DD55
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = SataLib
> +
> +[LibraryClasses]
> +BaseLib
> +PciSegmentLib
> +PchInfoLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +[Sources]
> +SataLib.c
> +SataLibCnl.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.i
> nf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.i
> nf
> new file mode 100644
> index 0000000000..37d0c80ea4
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.i
> nf
> @@ -0,0 +1,39 @@
> +## @file
> +# Component Description File for OcWdt Support.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiOcWdtLib
> +FILE_GUID = D5207C23-3632-4078-A671-3B5C364B2BDB
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +LIBRARY_CLASS = OcWdtLib
> +
> +
> +[LibraryClasses]
> +IoLib
> +DebugLib
> +PeiServicesLib
> +PchWdtCommonLib
> +PmcLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PeiOcWdtLib.c
> +
> +
> +[Ppis]
> +gWdtPpiGuid ## PRODUCES
> +
> +[Pcd]
> +gSiPkgTokenSpaceGuid.PcdOcEnableWdtforDebug ## CONSUMES
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.inf
> new file mode 100644
> index 0000000000..68ff41ef7f
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.inf
> @@ -0,0 +1,24 @@
> +## @file
> +# Component Description File for OcWdt Support.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiOcWdtLib
> +FILE_GUID = DB65B36B-E276-4A2b-AB20-61764889E483
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +LIBRARY_CLASS = OcWdtLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +
> +
> +[Sources]
> +PeiOcWdtLibNull.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.inf
> new file mode 100644
> index 0000000000..49e63cfc51
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.inf
> @@ -0,0 +1,86 @@
> +## @file
> +# Component description file for the PeiPchPolicy libbrary.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiPchPolicyLibCnl
> +FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +LIBRARY_CLASS = PchPolicyLib
> +
> +
> +[LibraryClasses]
> +DebugLib
> +IoLib
> +PcdLib
> +PeiServicesLib
> +BaseMemoryLib
> +MemoryAllocationLib
> +PchInfoLib
> +ConfigBlockLib
> +SiConfigBlockLib
> +SataLib
> +PchPcieRpLib
> +CpuPlatformLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Pcd]
> +gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress
> +gSiPkgTokenSpaceGuid.PcdSerialIoUartDebugEnable
> +gSiPkgTokenSpaceGuid.PcdSerialIoUartNumber
> +
> +
> +[Sources]
> +PeiPchPolicyLib.c
> +PeiPchPolicyLibCnl.c
> +PeiPchPolicyLibrary.h
> +PeiPchPreMemPolicyLib.c
> +PchPrintPolicy.c
> +PchPreMemPrintPolicy.c
> +
> +[Guids]
> +gPchGeneralConfigGuid ## CONSUMES
> +gPcieRpConfigGuid ## CONSUMES
> +gSataConfigGuid ## CONSUMES
> +gIoApicConfigGuid ## CONSUMES
> +gDmiConfigGuid ## CONSUMES
> +gFlashProtectionConfigGuid ## CONSUMES
> +gHdAudioConfigGuid ## CONSUMES
> +gInterruptConfigGuid ## CONSUMES
> +gIshConfigGuid ## CONSUMES
> +gLanConfigGuid ## CONSUMES
> +gLockDownConfigGuid ## CONSUMES
> +gP2sbConfigGuid ## CONSUMES
> +gPmConfigGuid ## CONSUMES
> +gScsConfigGuid ## CONSUMES
> +gSerialIoConfigGuid ## CONSUMES
> +gSerialIrqConfigGuid ## CONSUMES
> +gThermalConfigGuid ## CONSUMES
> +gUsbConfigGuid ## CONSUMES
> +gEspiConfigGuid ## CONSUMES
> +gCnviConfigGuid ## CONSUMES
> +gHsioConfigGuid ## CONSUMES
> +gPchGeneralPreMemConfigGuid ## COMSUMES
> +gDciPreMemConfigGuid ## CONSUMES
> +gWatchDogPreMemConfigGuid ## CONSUMES
> +gPchTraceHubPreMemConfigGuid ## CONSUMES
> +gSmbusPreMemConfigGuid ## CONSUMES
> +gLpcPreMemConfigGuid ## CONSUMES
> +gHsioPciePreMemConfigGuid ## CONSUMES
> +gHsioSataPreMemConfigGuid ## CONSUMES
> +gPcieRpPreMemConfigGuid ## CONSUMES
> +gHdAudioPreMemConfigGuid ## CONSUMES
> +gIshPreMemConfigGuid ## CONSUMES
> +
> +[Ppis]
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchReset
> Lib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchReset
> Lib.inf
> new file mode 100644
> index 0000000000..41e339a2e8
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchReset
> Lib.inf
> @@ -0,0 +1,41 @@
> +## @file
> +# Component description file for PCH Reset Lib Pei Phase
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiPchResetLib
> +FILE_GUID = DB91FFF0-5B99-4A88-9EC8-183A2106DCA2
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +LIBRARY_CLASS = PchResetLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF
> +#
> +
> +[LibraryClasses]
> +DebugLib
> +PeiServicesLib
> +PeiServicesTablePointerLib
> +MemoryAllocationLib
> +ResetSystemLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchReset.c
> +
> +[Ppis]
> +gEfiPeiReset2PpiGuid ## PRODUCES
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.inf
> new file mode 100644
> index 0000000000..f8f8bf1b66
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.inf
> @@ -0,0 +1,49 @@
> +## @file
> +# Component description file for Intel Ich7 Reset System Library.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiResetSystemLib
> +FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +UEFI_SPECIFICATION_VERSION = 2.00
> +LIBRARY_CLASS = ResetSystemLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF
> +#
> +
> +[LibraryClasses]
> +IoLib
> +DebugLib
> +BaseMemoryLib
> +PeiServicesLib
> +PmcLib
> +PmcPrivateLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PeiResetSystemLib.c
> +
> +
> +[Ppis]
> +gMeDidSentPpiGuid ## CONSUMES
> +gPchResetCallbackPpiGuid ## CONSUMES
> +
> +
> +[Guids]
> +gPchGlobalResetGuid
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf
> new file mode 100644
> index 0000000000..fb2fad78d3
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PeiSpiLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +# Component description file for PCH Reset Lib Pei Phase
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PeiSpiLib
> +FILE_GUID = 4998447D-7948-448F-AB75-96E24E18FF23
> +VERSION_STRING = 1.0
> +MODULE_TYPE = PEIM
> +LIBRARY_CLASS = SpiLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF
> +#
> +
> +[LibraryClasses]
> +DebugLib
> +PeiServicesLib
> +PeiServicesTablePointerLib
> +MemoryAllocationLib
> +PciSegmentLib
> +PchSpiCommonLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchSpi.c
> +
> +
> +[Ppis]
> +gPchSpiPpiGuid ## PRODUCES
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> rary.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> rary.h
> new file mode 100644
> index 0000000000..7a480b6cad
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> rary.h
> @@ -0,0 +1,117 @@
> +/** @file
> + Header file for GPIO Lib implementation.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _GPIO_LIBRARY_H_
> +#define _GPIO_LIBRARY_H_
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/GpioLib.h>
> +#include <Library/GpioNativeLib.h>
> +#include <Private/Library/GpioPrivateLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/SataLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/PchSbiAccessLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Private/Library/GpioHelpersLib.h>
> +#include <Register/PchRegsGpio.h>
> +
> +// BIT15-0 - pad number
> +// BIT31-16 - group info
> +// BIT23- 16 - group index
> +// BIT31- 24 - chipset ID
> +#define PAD_INFO_MASK 0x0000FFFF
> +#define GROUP_INFO_POSITION 16
> +#define GROUP_INFO_MASK 0xFFFF0000
> +#define GROUP_INDEX_MASK 0x00FF0000
> +#define UNIQUE_ID_MASK 0xFF000000
> +#define UNIQUE_ID_POSITION 24
> +
> +#define GPIO_PAD_DEF(Group,Pad) (UINT32)(((Group) << 16) +
> (Pad))
> +#define GPIO_GROUP_DEF(Index,ChipsetId) ((Index) | ((ChipsetId) << 8))
> +#define GPIO_GET_GROUP_INDEX(Group) ((Group) & 0xFF)
> +#define GPIO_GET_GROUP_FROM_PAD(Pad) ((Pad) >> 16)
> +#define GPIO_GET_GROUP_INDEX_FROM_PAD(Pad)
> GPIO_GET_GROUP_INDEX (((Pad) >> 16))
> +#define GPIO_GET_PAD_NUMBER(Pad) ((Pad) & 0xFFFF)
> +#define GPIO_GET_CHIPSET_ID(Pad) ((Pad) >> 24)
> +
> +#define GPIO_GET_PAD_POSITION(PadNumber) ((PadNumber) % 32)
> +#define GPIO_GET_DW_NUM(PadNumber) ((PadNumber) / 32u)
> +
> +//
> +// Number of PADCFG_DW registers
> +//
> +#define GPIO_PADCFG_DW_REG_NUMBER 4
> +
> +/**
> + This internal procedure will calculate GPIO_RESET_CONFIG value (new
> type)
> + based on provided PadRstCfg for a specific GPIO Pad.
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] PadRstCfg GPIO PadRstCfg value
> +
> + @retval GpioResetConfig GPIO Reset configuration (new type)
> +**/
> +GPIO_RESET_CONFIG
> +GpioResetConfigFromPadRstCfg (
> + IN GPIO_PAD GpioPad,
> + IN UINT32 PadRstCfg
> + );
> +
> +/**
> + This internal procedure will calculate PadRstCfg register value based
> + on provided GPIO Reset configuration for a certain pad.
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] GpioResetConfig GPIO Reset configuration
> + @param[out] PadRstCfg GPIO PadRstCfg value
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid configuration
> +**/
> +EFI_STATUS
> +GpioPadRstCfgFromResetConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_RESET_CONFIG GpioResetConfig,
> + OUT UINT32 *PadRstCfg
> + );
> +
> +/**
> + This procedure will calculate PADCFG register value based on GpioConfig
> data
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] GpioConfig GPIO Configuration data
> + @param[out] PadCfgDwReg PADCFG DWx register value
> + @param[out] PadCfgDwRegMask Mask with PADCFG DWx register
> bits to be modified
> +**/
> +VOID
> +GpioPadCfgRegValueFromGpioConfig (
> + IN GPIO_PAD GpioPad,
> + IN CONST GPIO_CONFIG *GpioConfig,
> + OUT UINT32 *PadCfgDwReg,
> + OUT UINT32 *PadCfgDwRegMask
> + );
> +
> +/**
> + Generates GPIO group name from GroupIndex
> +
> + @param[in] GroupIndex Gpio GroupIndex
> +
> + @retval CHAR8* Pointer to the GPIO group name
> +**/
> +CONST
> +CHAR8*
> +GpioGetGroupName (
> + IN UINT32 GroupIndex
> + );
> +
> +#endif // _GPIO_LIBRARY_H_
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchIn
> foLibPrivate.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibPrivate.h
> new file mode 100644
> index 0000000000..79e03fef44
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibPrivate.h
> @@ -0,0 +1,45 @@
> +/** @file
> + Private header for PCH Info Lib.
> +
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +/**
> + Structure for PCH SKU string mapping
> +**/
> +struct PCH_SKU_STRING {
> + UINT16 Id;
> + CHAR8 *String;
> +};
> +
> +extern struct PCH_SKU_STRING mSkuStrs[];
> +
> +/**
> + Determine Pch Series based on Device Id
> +
> + @param[in] LpcDeviceId Lpc Device Id
> +
> + @retval PCH_SERIES Pch Series
> +**/
> +PCH_SERIES
> +PchSeriesFromLpcDid (
> + IN UINT16 LpcDeviceId
> + );
> +
> +/**
> +Determine Pch Generation based on Device Id
> +
> +@param[in] LpcDeviceId Lpc Device Id
> +
> +@retval PCH_GENERATION Pch Generation
> +**/
> +PCH_GENERATION
> +PchGenerationFromDid (
> + IN UINT16 LpcDeviceId
> + );
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibInternal.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibInternal.h
> new file mode 100644
> index 0000000000..17e4bb863a
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibInternal.h
> @@ -0,0 +1,16 @@
> +/** @file
> + Header file for PchSerialIoLibInternal.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PCH_SERIAL_IO_LIB_INTERNAL_H_
> +#define _PCH_SERIAL_IO_LIB_INTERNAL_H_
> +
> +typedef struct {
> + UINT8 DevNum;
> + UINT8 FuncNum;
> +} SERIAL_IO_BDF_NUMBERS;
> +#endif
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibrary.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibrary.h
> new file mode 100644
> index 0000000000..abd7e63365
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibrary.h
> @@ -0,0 +1,35 @@
> +/** @file
> + Header file for the PeiPchPolicy library.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PEI_PCH_POLICY_LIBRARY_H_
> +#define _PEI_PCH_POLICY_LIBRARY_H_
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/ConfigBlockLib.h>
> +#include <Library/SiConfigBlockLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/SataLib.h>
> +#include <Ppi/SiPolicy.h>
> +#include <Library/PchSerialIoLib.h>
> +#include <Library/PchPolicyLib.h>
> +
> +/**
> + Adds interrupt configuration for device
> +
> + @param[in/out] InterruptConfig Pointer to interrupt config
> +**/
> +VOID
> +LoadDeviceInterruptConfig (
> + IN OUT PCH_INTERRUPT_CONFIG *InterruptConfig
> + );
> +
> +#endif // _PEI_PCH_POLICY_LIBRARY_H_
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Bios
> LockLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Bios
> LockLib.c
> new file mode 100644
> index 0000000000..20c024e893
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmBiosLockLib/Bios
> LockLib.c
> @@ -0,0 +1,98 @@
> +/** @file
> + Bios Lock library.
> +
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +
> +/**
> + Enable BIOS lock. This will set the LE (Lock Enable) and EISS (Enable In
> SMM.STS).
> + When this is set, attempts to write the WPD (Write Protect Disable) bit in
> PCH
> + will cause a SMI which will allow the BIOS to verify that the write is from a
> valid source.
> +
> + Bios should always enable LockDownConfig.BiosLock policy to set Bios Lock
> bit in FRC.
> + If capsule udpate is enabled, it's expected to not do BiosLock by setting
> BiosLock policy disable
> + so it can udpate BIOS region.
> + After flash update, it should utilize this lib to do BiosLock for security.
> +**/
> +VOID
> +BiosLockEnable (
> + VOID
> + )
> +{
> + UINT64 LpcBaseAddress;
> + UINT64 SpiBaseAddress;
> +
> + LpcBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_LPC,
> + PCI_FUNCTION_NUMBER_PCH_LPC,
> + 0
> + );
> + SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + 0
> + );
> +
> + ///
> + /// PCH BIOS Spec Flash Security Recommendation
> + ///
> + /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by
> setting
> + /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
> + /// When this bit is set, attempts to write the Write Protect Disable (WPD)
> bit
> + /// in PCH will cause a SMI which will allow the BIOS to verify that the write
> is
> + /// from a valid source.
> + /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to
> enable
> + /// BIOS region protection before exiting the SMI handler.
> + /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b)
> to keep
> + /// BLE feature enabled after booting to the OS.
> + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH
> to
> + /// ensure SMM protection of flash.
> + /// RC installs a default SMI handler that clears WPD.
> + /// There could be additional SMI handler to log such attempt if desired.
> + ///
> + /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the PCH
> by setting
> + /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 1b for
> eSPI.
> + /// When this bit is set, the BIOS region is not writable until SMM sets the
> InSMM.STS bit,
> + /// to ensure BIOS can only be modified from SMM. Please refer to CPU BWG
> for more details
> + /// on InSMM.STS bit.
> + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH
> to ensure
> + /// SMM protection of flash.
> + /// SPI PCI offset DCh[1] = 1b for SPI or setting eSPI PCI offset DCh[1] = 1b for
> eSPI.
> + /// When this bit is set, EISS is locked down.
> + ///
> + PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, B_SPI_CFG_BC_EISS |
> B_SPI_CFG_BC_LE);
> + S3BootScriptSaveMemWrite (
> + S3BootScriptWidthUint8,
> + PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
> + 1,
> + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress
> + R_SPI_CFG_BC)
> + );
> + PciSegmentOr8 (LpcBaseAddress + R_LPC_CFG_BC, B_LPC_CFG_BC_EISS |
> B_LPC_CFG_BC_LE);
> + S3BootScriptSaveMemWrite (
> + S3BootScriptWidthUint8,
> + PcdGet64 (PcdPciExpressBaseAddress) + LpcBaseAddress +
> R_LPC_CFG_BC,
> + 1,
> + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) +
> LpcBaseAddress + R_LPC_CFG_BC)
> + );
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioIni
> t.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioIni
> t.c
> new file mode 100644
> index 0000000000..76eb3a9b81
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioIni
> t.c
> @@ -0,0 +1,553 @@
> +/** @file
> + This file contains routines for GPIO initialization
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GpioLibrary.h"
> +#include <Register/PchRegsPcr.h>
> +
> +//
> +// GPIO_GROUP_DW_DATA structure is used by GpioConfigurePch function
> +// to cache values which will be programmed into respective GPIO registers
> +// after all GpioPads are processed. This way MMIO accesses are decreased
> +// and instead of doing one programming for one GpioPad there is only
> +// one access for whole register.
> +//
> +typedef struct {
> + UINT32 HostSoftOwnReg;
> + UINT32 HostSoftOwnRegMask;
> + UINT32 GpiGpeEnReg;
> + UINT32 GpiGpeEnRegMask;
> + UINT32 GpiNmiEnReg;
> + UINT32 GpiNmiEnRegMask;
> + UINT32 GpiSmiEnReg;
> + UINT32 GpiSmiEnRegMask;
> + UINT32 ConfigUnlockMask;
> + UINT32 OutputUnlockMask;
> +} GPIO_GROUP_DW_DATA;
> +
> +//
> +// GPIO_GROUP_DW_NUMBER contains number of DWords required to
> +// store Pad data for all groups. Each pad uses one bit.
> +//
> +// For Cannonlake only vGPIO group has >32 pads but those pads
> +// will not be accessed by this function so GPIO_GROUP_DW_NUMBER can be
> 1
> +//
> +#define GPIO_GROUP_DW_NUMBER 1
> +
> +/**
> + Get GPIO DW Register values (HOSTSW_OWN, GPE_EN, NMI_EN, Lock).
> +
> + @param[in] PadNumber GPIO pad number
> + @param[in] GpioConfig GPIO Config data
> + @param[in out] DwRegsValues Values for GPIO DW Registers
> +
> + @retval None
> +**/
> +STATIC
> +VOID
> +GpioDwRegValueFromGpioConfig (
> + IN UINT32 PadNumber,
> + IN CONST GPIO_CONFIG *GpioConfig,
> + IN OUT GPIO_GROUP_DW_DATA *GroupDwData
> + )
> +{
> + UINT32 PadBitPosition;
> + UINT32 DwNum;
> +
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> +
> + if (DwNum >= GPIO_GROUP_DW_NUMBER) {
> + ASSERT (FALSE);
> + return;
> + }
> + //
> + // Update value to be programmed in HOSTSW_OWN register
> + //
> + GroupDwData[DwNum].HostSoftOwnRegMask |=
> (GpioConfig->HostSoftPadOwn & 0x1) << PadBitPosition;
> + GroupDwData[DwNum].HostSoftOwnReg |=
> (GpioConfig->HostSoftPadOwn >> 0x1) << PadBitPosition;
> +
> + //
> + // Update value to be programmed in GPI_GPE_EN register
> + //
> + GroupDwData[DwNum].GpiGpeEnRegMask |=
> (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
> + GroupDwData[DwNum].GpiGpeEnReg |= ((GpioConfig->InterruptConfig &
> GpioIntSci) >> 3) << PadBitPosition;
> +
> + //
> + // Update value to be programmed in GPI_NMI_EN register
> + //
> + GroupDwData[DwNum].GpiNmiEnRegMask |=
> (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
> + GroupDwData[DwNum].GpiNmiEnReg |= ((GpioConfig->InterruptConfig &
> GpioIntNmi) >> 1) << PadBitPosition;
> +
> + //
> + // Update value to be programmed in GPI_SMI_EN register
> + GroupDwData[DwNum].GpiSmiEnRegMask |=
> (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
> + GroupDwData[DwNum].GpiSmiEnReg |= ((GpioConfig->InterruptConfig &
> GpioIntSmi) >> 2) << PadBitPosition;
> + if ((GpioConfig->InterruptConfig & GpioIntSmi) == GpioIntSmi) {
> + GroupDwData[DwNum].HostSoftOwnRegMask |= 1 << PadBitPosition;
> + GroupDwData[DwNum].HostSoftOwnReg |= 1 << PadBitPosition;
> + }
> +
> + //
> + // Update information on Pad Configuration Lock
> + //
> + GroupDwData[DwNum].ConfigUnlockMask |= ((GpioConfig->LockConfig >>
> 1) & 0x1) << PadBitPosition;
> +
> + //
> + // Update information on Pad Configuration Lock Tx
> + //
> + GroupDwData[DwNum].OutputUnlockMask |= ((GpioConfig->LockConfig
> >> 3) & 0x1) << PadBitPosition;
> +
> + //
> + // if pad in GpioMode is an output default action should be to leave output
> unlocked
> + //
> + if ((GpioConfig->PadMode == GpioPadModeGpio) &&
> + (GpioConfig->Direction == GpioDirOut) &&
> + ((GpioConfig->LockConfig &
> B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioLockDefault)) {
> + GroupDwData[DwNum].OutputUnlockMask |= 0x1 << PadBitPosition;
> + }
> +}
> +
> +/**
> + This internal procedure will scan GPIO initialization table and unlock
> + all pads present in it
> +
> + @param[in] NumberOfItem Number of GPIO pad records in table
> + @param[in] GpioInitTableAddress GPIO initialization table
> + @param[in] Index Index of GPIO Initialization table record
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +STATIC
> +EFI_STATUS
> +GpioUnlockPadsForAGroup (
> + IN UINT32 NumberOfItems,
> + IN GPIO_INIT_CONFIG *GpioInitTableAddress,
> + IN UINT32 Index
> + )
> +{
> + UINT32 PadsToUnlock[GPIO_GROUP_DW_NUMBER];
> + UINT32 DwNum;
> + UINT32 PadBitPosition;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + CONST GPIO_INIT_CONFIG *GpioData;
> + GPIO_GROUP Group;
> + UINT32 GroupIndex;
> + UINT32 PadNumber;
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + GpioData = &GpioInitTableAddress[Index];
> + Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
> +
> + ZeroMem (PadsToUnlock, sizeof (PadsToUnlock));
> + //
> + // Loop through pads for one group. If pad belongs to a different group then
> + // break and move to register programming.
> + //
> + while (Index < NumberOfItems) {
> +
> + GpioData = &GpioInitTableAddress[Index];
> + if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad))
> {
> + //if next pad is from different group then break loop
> + break;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
> + //
> + // Check if legal pin number
> + //
> + if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds
> possible range for group %d\n", PadNumber, GroupIndex));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> +
> + if (DwNum >= GPIO_GROUP_DW_NUMBER) {
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> + //
> + // Update pads which need to be unlocked
> + //
> + PadsToUnlock[DwNum] |= 0x1 << PadBitPosition;
> +
> + //Move to next item
> + Index++;
> + }
> +
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + //
> + // Unlock pads
> + //
> + if (PadsToUnlock[DwNum] != 0) {
> + GpioUnlockPadCfgForGroupDw (Group, DwNum,
> PadsToUnlock[DwNum]);
> + GpioUnlockPadCfgTxForGroupDw (Group, DwNum,
> PadsToUnlock[DwNum]);
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will initialize multiple PCH GPIO pins
> +
> + @param[in] NumberofItem Number of GPIO pads to be updated
> + @param[in] GpioInitTableAddress GPIO initialization table
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +STATIC
> +EFI_STATUS
> +GpioConfigurePch (
> + IN UINT32 NumberOfItems,
> + IN GPIO_INIT_CONFIG *GpioInitTableAddress
> + )
> +{
> + UINT32 Index;
> + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
> + UINT32
> PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER];
> + UINT32 PadCfgReg;
> + GPIO_GROUP_DW_DATA GroupDwData[GPIO_GROUP_DW_NUMBER];
> + UINT32 DwNum;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + GPIO_PAD_OWN PadOwnVal;
> + CONST GPIO_INIT_CONFIG *GpioData;
> + UINT32 GroupIndex;
> + UINT32 PadNumber;
> + PCH_SBI_PID GpioCom;
> +
> + PadOwnVal = GpioPadOwnHost;
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + Index = 0;
> + while (Index < NumberOfItems) {
> +
> + GpioData = &GpioInitTableAddress[Index];
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
> + GpioCom = GpioGroupInfo[GroupIndex].Community;
> +
> + DEBUG_CODE_BEGIN();
> + if (!GpioIsCorrectPadForThisChipset (GpioData->GpioPad)) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad (0x%08x) used
> on this chipset!\n", GpioData->GpioPad));
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> + DEBUG_CODE_END ();
> +
> + //
> + // Unlock pads for a given group which are going to be reconfigured
> + //
> + //
> + // Because PADCFGLOCK/LOCKTX register reset domain is Powergood, lock
> settings
> + // will get back to default only after G3 or DeepSx transition. On the other
> hand GpioPads
> + // configuration is controlled by a configurable type of reset - PadRstCfg.
> This means that if
> + // PadRstCfg != Powergood GpioPad will have its configuration locked
> despite it being not the
> + // one desired by BIOS. Before reconfiguring all pads they will get unlocked.
> + //
> + GpioUnlockPadsForAGroup (NumberOfItems, GpioInitTableAddress,
> Index);
> +
> + ZeroMem (GroupDwData, sizeof (GroupDwData));
> + //
> + // Loop through pads for one group. If pad belongs to a different group
> then
> + // break and move to register programming.
> + //
> + while (Index < NumberOfItems) {
> +
> + GpioData = &GpioInitTableAddress[Index];
> + if (GroupIndex != GpioGetGroupIndexFromGpioPad
> (GpioData->GpioPad)) {
> + //if next pad is from different group then break loop
> + break;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
> +
> + DEBUG_CODE_BEGIN ();
> + //
> + // Check if legal pin number
> + //
> + if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds
> possible range for group %d\n", PadNumber, GroupIndex));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Check if selected GPIO Pad is not owned by CSME/ISH
> + //
> + GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
> +
> + if (PadOwnVal != GpioPadOwnHost) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by
> host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
> + DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync
> between CSME and BIOS configuration. \n"));
> + DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not
> do any configuration by BIOS.\n"));
> + //Move to next item
> + Index++;
> + continue;
> + }
> +
> + //
> + // Check if Pad enabled for SCI is to be in unlocked state
> + //
> + if (((GpioData->GpioConfig.InterruptConfig & GpioIntSci) == GpioIntSci)
> &&
> + ((GpioData->GpioConfig.LockConfig &
> B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != GpioPadConfigUnlock)){
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a used for SCI is not
> unlocked!\n", GpioName (GpioData->GpioPad)));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> + DEBUG_CODE_END ();
> +
> + ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
> + ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
> + //
> + // Get GPIO PADCFG register value from GPIO config data
> + //
> + GpioPadCfgRegValueFromGpioConfig (
> + GpioData->GpioPad,
> + &GpioData->GpioConfig,
> + PadCfgDwReg,
> + PadCfgDwRegMask
> + );
> +
> + //
> + // Create PADCFG register offset using group and pad number
> + //
> + PadCfgReg = S_GPIO_PCR_PADCFG * PadNumber +
> GpioGroupInfo[GroupIndex].PadCfgOffset;
> +
> + //
> + // Write PADCFG DW0 register
> + //
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom, PadCfgReg),
> + ~PadCfgDwRegMask[0],
> + PadCfgDwReg[0]
> + );
> +
> + //
> + // Write PADCFG DW1 register
> + //
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x4),
> + ~PadCfgDwRegMask[1],
> + PadCfgDwReg[1]
> + );
> +
> + //
> + // Write PADCFG DW2 register
> + //
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x8),
> + ~PadCfgDwRegMask[2],
> + PadCfgDwReg[2]
> + );
> +
> + //
> + // Get GPIO DW register values from GPIO config data
> + //
> + GpioDwRegValueFromGpioConfig (
> + PadNumber,
> + &GpioData->GpioConfig,
> + GroupDwData
> + );
> +
> + //Move to next item
> + Index++;
> + }
> +
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + //
> + // Write HOSTSW_OWN registers
> + //
> + if (GpioGroupInfo[GroupIndex].HostOwnOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom,
> GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4),
> + ~GroupDwData[DwNum].HostSoftOwnRegMask,
> + GroupDwData[DwNum].HostSoftOwnReg
> + );
> + }
> +
> + //
> + // Write GPI_GPE_EN registers
> + //
> + if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom,
> GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4),
> + ~GroupDwData[DwNum].GpiGpeEnRegMask,
> + GroupDwData[DwNum].GpiGpeEnReg
> + );
> + }
> +
> + //
> + // Write GPI_NMI_EN registers
> + //
> + if (GpioGroupInfo[GroupIndex].NmiEnOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom,
> GpioGroupInfo[GroupIndex].NmiEnOffset + DwNum * 0x4),
> + ~GroupDwData[DwNum].GpiNmiEnRegMask,
> + GroupDwData[DwNum].GpiNmiEnReg
> + );
> + } else if (GroupDwData[DwNum].GpiNmiEnReg != 0x0) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads
> supporting NMI\n", GroupIndex));
> + ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
> + }
> +
> + //
> + // Write GPI_SMI_EN registers
> + //
> + if (GpioGroupInfo[GroupIndex].SmiEnOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioCom,
> GpioGroupInfo[GroupIndex].SmiEnOffset + DwNum * 0x4),
> + ~GroupDwData[DwNum].GpiSmiEnRegMask,
> + GroupDwData[DwNum].GpiSmiEnReg
> + );
> + } else if (GroupDwData[DwNum].GpiSmiEnReg != 0x0) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads
> supporting SMI\n", GroupIndex));
> + ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
> + }
> +
> + //
> + // Update Pad Configuration unlock data
> + //
> + if (GroupDwData[DwNum].ConfigUnlockMask) {
> + GpioStoreGroupDwUnlockPadConfigData (GroupIndex, DwNum,
> GroupDwData[DwNum].ConfigUnlockMask);
> + }
> +
> + //
> + // Update Pad Output unlock data
> + //
> + if (GroupDwData[DwNum].OutputUnlockMask) {
> + GpioStoreGroupDwUnlockOutputData (GroupIndex, DwNum,
> GroupDwData[DwNum].OutputUnlockMask);
> + }
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will clear all status bits of any GPIO interrupts.
> +**/
> +STATIC
> +VOID
> +GpioClearAllGpioInterrupts (
> + VOID
> + )
> +{
> + GPIO_GROUP Group;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + GPIO_GROUP GpioGroupLowest;
> + GPIO_GROUP GpioGroupHighest;
> + UINT32 GroupIndex;
> + UINT32 GpioGroupInfoLength;
> + UINT32 DwNum;
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + GpioGroupLowest = GpioGetLowestGroup ();
> + GpioGroupHighest = GpioGetHighestGroup ();
> +
> + for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) {
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> + //
> + // Check if group has GPI IS register
> + //
> + if (GpioGroupInfo[GroupIndex].GpiIsOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + //
> + // Clear all GPI_IS Status bits by writing '1'
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + MmioWrite32 (
> + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community,
> GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4),
> + 0xFFFFFFFF
> + );
> + }
> + }
> +
> + //
> + // Check if group has GPI_GPE_STS register
> + //
> + if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + //
> + // Clear all GPI_GPE_STS Status bits by writing '1'
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + MmioWrite32 (
> + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community,
> GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4),
> + 0xFFFFFFFF
> + );
> + }
> + }
> +
> + //
> + // Check if group has SMI_STS register
> + //
> + if (GpioGroupInfo[GroupIndex].SmiStsOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + //
> + // Clear all SMI_STS Status bits by writing '1'
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + MmioWrite32 (
> + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community,
> GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4),
> + 0xFFFFFFFF
> + );
> + }
> + }
> +
> + //
> + // Check if group has NMI_STS register
> + //
> + if (GpioGroupInfo[GroupIndex].NmiStsOffset !=
> NO_REGISTER_FOR_PROPERTY) {
> + //
> + // Clear all NMI_STS Status bits by writing '1'
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
> + MmioWrite32 (
> + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community,
> GpioGroupInfo[GroupIndex].NmiStsOffset + DwNum * 4),
> + 0xFFFFFFFF
> + );
> + }
> + }
> +
> + }
> +}
> +
> +/**
> + This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG
> structure.
> + Structure contains fields that can be used to configure each pad.
> + Pad not configured using GPIO_INIT_CONFIG will be left with hardware
> default values.
> + Separate fields could be set to hardware default if it does not matter, except
> + GpioPad and PadMode.
> + Function will work in most efficient way if pads which belong to the same
> group are
> + placed in adjacent records of the table.
> + Although function can enable pads for Native mode, such programming is
> done
> + by reference code when enabling related silicon feature.
> +
> + @param[in] NumberofItem Number of GPIO pads to be updated
> + @param[in] GpioInitTableAddress GPIO initialization table
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioConfigurePads (
> + IN UINT32 NumberOfItems,
> + IN GPIO_INIT_CONFIG *GpioInitTableAddress
> + )
> +{
> + EFI_STATUS Status;
> + Status = GpioConfigurePch (NumberOfItems, GpioInitTableAddress);
> + GpioClearAllGpioInterrupts ();
> + return Status;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> .c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> .c
> new file mode 100644
> index 0000000000..0be50f75df
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib
> .c
> @@ -0,0 +1,2710 @@
> +/** @file
> + This file contains routines for GPIO
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GpioLibrary.h"
> +#include <Register/PchRegsPcr.h>
> +
> +/**
> + This procedure will check if GpioGroup argument is correct and
> + supplied DW reg number can be used for this group to access DW registers.
> + Function will check below conditions:
> + - Valid GpioGroup
> + - DwNum is has valid value for this group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum Register number for current group (parameter
> applicable in accessing whole register).
> + For group which has less then 32 pads per group DwNum
> must be 0.
> +
> + @retval TRUE DW Reg number and GpioGroup is valid
> + @retval FALSE DW Reg number and GpioGroup is invalid
> +**/
> +STATIC
> +BOOLEAN
> +GpioIsGroupAndDwNumValid (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum
> + )
> +{
> + UINT32 GroupIndex;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ())
> || (GroupIndex >= GpioGroupInfoLength)) {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within
> range of possible groups for this PCH\n", GroupIndex));
> + goto Error;
> + }
> +
> + //
> + // Check if DwNum argument does not exceed number of DWord registers
> + // resulting from available pads for certain group
> + //
> + if (DwNum > GPIO_GET_DW_NUM
> (GpioGroupInfo[GroupIndex].PadPerGroup - 1)){
> + goto Error;
> + }
> +
> + return TRUE;
> +Error:
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +//
> +// Possible registers to be accessed using GpioReadReg()/GpioWriteReg()
> functions
> +//
> +typedef enum {
> + GpioHostOwnershipRegister = 0,
> + GpioGpeEnableRegister,
> + GpioGpeStatusRegister,
> + GpioSmiEnableRegister,
> + GpioSmiStatusRegister,
> + GpioNmiEnableRegister,
> + GpioPadConfigLockRegister,
> + GpioPadLockOutputRegister
> +} GPIO_REG;
> +
> +/**
> + This procedure will read GPIO register
> +
> + @param[in] RegType GPIO register type
> + @param[in] Group GPIO group
> + @param[in] DwNum Register number for current group
> (parameter applicable in accessing whole register).
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[out] ReadVal Read data
> +**/
> +STATIC
> +VOID
> +GpioReadReg (
> + IN GPIO_REG RegType,
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + OUT UINT32 *ReadVal
> + )
> +{
> + UINT32 RegOffset;
> + UINT32 GroupIndex;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> +
> + RegOffset = NO_REGISTER_FOR_PROPERTY;
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + switch (RegType) {
> + case GpioHostOwnershipRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
> + break;
> + case GpioGpeEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
> + break;
> + case GpioGpeStatusRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
> + break;
> + case GpioSmiEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
> + break;
> + case GpioSmiStatusRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
> + break;
> + case GpioNmiEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
> + break;
> + case GpioPadConfigLockRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
> + break;
> + case GpioPadLockOutputRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
> + break;
> + default:
> + break;
> + }
> +
> + //
> + // Check if selected register exists
> + //
> + if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
> + *ReadVal = 0;
> + ASSERT (FALSE);
> + return;
> + }
> +
> + //
> + // If there are more then 32 pads per group then certain
> + // group information would be split into more then one DWord register.
> + //
> + if ((RegType == GpioPadConfigLockRegister) || (RegType ==
> GpioPadLockOutputRegister)) {
> + //
> + // PadConfigLock and OutputLock registers when used for group
> containing more than 32 pads
> + // are not placed in a continuous way, e.g:
> + // 0x0 - PadConfigLock_DW0
> + // 0x4 - OutputLock_DW0
> + // 0x8 - PadConfigLock_DW1
> + // 0xC - OutputLock_DW1
> + //
> + RegOffset += DwNum * 0x8;
> + } else {
> + RegOffset += DwNum * 0x4;
> + }
> +
> + *ReadVal = MmioRead32 (PCH_PCR_ADDRESS
> (GpioGroupInfo[GroupIndex].Community, RegOffset));
> +}
> +
> +/**
> + This function determines if the group is SMI capable.
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum Register number for current group
> (parameter applicable in accessing whole register).
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @retval TRUE The function completed successfully
> + @retval FALSE Setting SMI for a group is not supported
> +**/
> +STATIC
> +BOOLEAN
> +GpioIsSmiSupportedByGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 Dw
> + )
> +{
> + UINT32 RegOffset;
> + UINT32 GroupIndex;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> +
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
> +
> + //
> + // Check if selected register exists
> + //
> + if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
> +
> +/**
> + This function determines if the group is NMI capable.
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum Register number for current group
> (parameter applicable in accessing whole register).
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @retval TRUE The function completed successfully
> + @retval FALSE Setting NMI for a group is not supported
> +**/
> +STATIC
> +BOOLEAN
> +GpioIsNmiSupportedByGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 Dw
> + )
> +{
> + UINT32 RegOffset;
> + UINT32 GroupIndex;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> +
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
> +
> + //
> + // Check if selected register exists
> + //
> + if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
> +
> +/**
> + This procedure will write GPIO register
> +
> + @param[in] RegType GPIO register type
> + @param[in] Group GPIO group
> + @param[in] DwNum Register number for current group
> (parameter applicable in accessing whole register).
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] RegAndMask Mask which will be AND'ed with register
> value
> + @param[in] RegOrMask Mask which will be OR'ed with register
> value
> +**/
> +STATIC
> +VOID
> +GpioWriteReg (
> + IN GPIO_REG RegType,
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 RegAndMask,
> + IN UINT32 RegOrMask
> + )
> +{
> + UINT32 RegOffset;
> + UINT32 GroupIndex;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + UINT32 PadCfgLock;
> + BOOLEAN Lockable;
> + EFI_STATUS Status;
> +
> + Lockable = FALSE;
> + PadCfgLock = 0;
> + RegOffset = NO_REGISTER_FOR_PROPERTY;
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + switch (RegType) {
> + case GpioHostOwnershipRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
> + break;
> + case GpioGpeEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
> + Lockable = TRUE;
> + break;
> + case GpioGpeStatusRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
> + break;
> + case GpioSmiEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
> + Lockable = TRUE;
> + break;
> + case GpioSmiStatusRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
> + break;
> + case GpioNmiEnableRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
> + Lockable = TRUE;
> + break;
> + case GpioPadConfigLockRegister:
> + case GpioPadLockOutputRegister:
> + default:
> + break;
> + }
> +
> + //
> + // Check if selected register exists
> + //
> + if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
> + return;
> + }
> +
> + if (Lockable) {
> + GpioGetPadCfgLockForGroupDw (Group, DwNum, &PadCfgLock);
> + if (PadCfgLock) {
> + //
> + // Check if for pads which are going to be reconfigured lock is set.
> + //
> + if ((~RegAndMask | RegOrMask) & PadCfgLock) {
> + //
> + // Unlock all pads for this Group DW reg for simplicity
> + // even if not all of those pads will have their settings reprogrammed
> + //
> + Status = GpioUnlockPadCfgForGroupDw (Group, DwNum, PadCfgLock);
> + if (EFI_ERROR (Status)) {
> + ASSERT (FALSE);
> + return;
> + }
> + } else {
> + //
> + // No need to perform an unlock as pads which are going to be
> reconfigured
> + // are not in locked state
> + //
> + PadCfgLock = 0;
> + }
> + }
> + }
> +
> + //
> + // If there are more then 32 pads per group then certain
> + // group information would be split into more then one DWord register.
> + //
> + RegOffset += DwNum * 0x4;
> +
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
> + RegAndMask,
> + RegOrMask
> + );
> +
> + if (Lockable && PadCfgLock) {
> + //
> + // Lock previously unlocked pads
> + //
> + Status = GpioLockPadCfgForGroupDw (Group, DwNum, PadCfgLock);
> + if (EFI_ERROR (Status)) {
> + ASSERT (FALSE);
> + return;
> + }
> + }
> +}
> +
> +/**
> + This procedure will write GPIO Lock/LockTx register using SBI.
> +
> + @param[in] RegType GPIO register (Lock or LockTx)
> + @param[in] Group GPIO group number
> + @param[in] DwNum Register number for current group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] LockRegAndMask Mask which will be AND'ed with Lock
> register value
> + @param[in] LockRegOrMask Mask which will be Or'ed with Lock
> register value
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_UNSUPPORTED Feature is not supported for this group or
> pad
> +**/
> +STATIC
> +EFI_STATUS
> +GpioWriteLockReg (
> + IN GPIO_REG RegType,
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 LockRegAndMask,
> + IN UINT32 LockRegOrMask
> + )
> +{
> + UINT8 Response;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + UINT32 RegOffset;
> + UINT32 OldLockVal;
> + UINT32 NewLockVal;
> + UINT32 GroupIndex;
> + EFI_STATUS Status;
> +
> + OldLockVal = 0;
> + NewLockVal = 0;
> +
> + RegOffset = NO_REGISTER_FOR_PROPERTY;
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + switch (RegType) {
> + case GpioPadConfigLockRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
> + GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldLockVal);
> + break;
> + case GpioPadLockOutputRegister:
> + RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
> + GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldLockVal);
> + break;
> + default:
> + break;
> + }
> +
> + //
> + // Check if selected register exists
> + //
> + if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // If there are more then 32 pads per group then certain
> + // group information would be split into more then one DWord register.
> + // PadConfigLock and OutputLock registers when used for group containing
> more than 32 pads
> + // are not placed in a continuous way, e.g:
> + // 0x0 - PadConfigLock_DW0
> + // 0x4 - OutputLock_DW0
> + // 0x8 - PadConfigLock_DW1
> + // 0xC - OutputLock_DW1
> + //
> + RegOffset += DwNum *0x8;
> +
> + NewLockVal = (OldLockVal & LockRegAndMask) | LockRegOrMask;
> +
> + Status = PchSbiExecutionEx (
> + GpioGroupInfo[GroupIndex].Community,
> + RegOffset,
> + GpioLockUnlock,
> + FALSE,
> + 0x000F,
> + 0x0000,
> + 0x0000,
> + &NewLockVal,
> + &Response
> + );
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/**
> + This internal procedure will calculate GPIO_RESET_CONFIG value (new
> type)
> + based on provided PadRstCfg for a specific GPIO Pad.
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] PadRstCfg GPIO PadRstCfg value
> +
> + @retval GpioResetConfig GPIO Reset configuration (new type)
> +**/
> +GPIO_RESET_CONFIG
> +GpioResetConfigFromPadRstCfg (
> + IN GPIO_PAD GpioPad,
> + IN UINT32 PadRstCfg
> + )
> +{
> + GPIO_GROUP Group;
> +
> + static GPIO_RESET_CONFIG GppPadRstCfgToGpioResetConfigMap[] = {
> + GpioResumeReset,
> + GpioHostDeepReset,
> + GpioPlatformReset};
> + static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] = {
> + GpioDswReset,
> + GpioHostDeepReset,
> + GpioPlatformReset,
> + GpioResumeReset};
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> +
> + if (GpioIsDswGroup (Group) && PadRstCfg < 4) {
> + return GpdPadRstCfgToGpioResetConfigMap[PadRstCfg];
> + } else if (PadRstCfg < 3) {
> + return GppPadRstCfgToGpioResetConfigMap[PadRstCfg];
> + } else {
> + ASSERT (FALSE);
> + return GpioResetDefault;
> + }
> +}
> +
> +/**
> + This internal procedure will calculate PadRstCfg register value based
> + on provided GPIO Reset configuration for a certain pad.
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] GpioResetConfig GPIO Reset configuration
> + @param[out] PadRstCfg GPIO PadRstCfg value
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid configuration
> +**/
> +EFI_STATUS
> +GpioPadRstCfgFromResetConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_RESET_CONFIG GpioResetConfig,
> + OUT UINT32 *PadRstCfg
> + )
> +{
> + GPIO_GROUP Group;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> +
> + switch (GpioResetConfig) {
> + case GpioResetDefault:
> + *PadRstCfg = 0x0;
> + break;
> + case GpioHostDeepReset:
> + *PadRstCfg = V_GPIO_PCR_RST_CONF_DEEP_RST;
> + break;
> + case GpioPlatformReset:
> + *PadRstCfg = V_GPIO_PCR_RST_CONF_GPIO_RST;
> + break;
> + case GpioResumeReset:
> + if (GpioIsDswGroup (Group)) {
> + *PadRstCfg = V_GPIO_PCR_RST_CONF_RESUME_RST;
> + } else {
> + *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD;
> + }
> + break;
> + case GpioDswReset:
> + if (GpioIsDswGroup (Group)) {
> + *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD;
> + } else {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use
> GpioDswReset: %a\n", GpioName (GpioPad)));
> + goto Error;
> + }
> + break;
> + default:
> + goto Error;
> + }
> +
> + return EFI_SUCCESS;
> +Error:
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> +}
> +
> +/**
> + This internal procedure will get GPIO_CONFIG data from PADCFG registers
> value
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] PadCfgDwReg PADCFG DWx register values
> + @param[out] GpioData GPIO Configuration data
> +
> + @retval Status
> +**/
> +STATIC
> +VOID
> +GpioConfigFromPadCfgRegValue (
> + IN GPIO_PAD GpioPad,
> + IN CONST UINT32 *PadCfgDwReg,
> + OUT GPIO_CONFIG *GpioConfig
> + )
> +{
> + UINT32 PadRstCfg;
> +
> + //
> + // Get Reset Type (PadRstCfg)
> + //
> + PadRstCfg = (PadCfgDwReg[0] & B_GPIO_PCR_RST_CONF) >>
> N_GPIO_PCR_RST_CONF;
> +
> + GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg (
> + GpioPad,
> + PadRstCfg
> + );
> +
> + //
> + // Get how interrupt is triggered (RxEvCfg)
> + //
> + GpioConfig->InterruptConfig = ((PadCfgDwReg[0] &
> B_GPIO_PCR_RX_LVL_EDG) >> (N_GPIO_PCR_RX_LVL_EDG -
> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | (0x1 <<
> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS);
> +
> + //
> + // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
> + //
> + GpioConfig->InterruptConfig |= ((PadCfgDwReg[0] &
> (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE |
> B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE)) >>
> (N_GPIO_PCR_RX_NMI_ROUTE -
> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1))) | (0x1 <<
> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS);
> +
> + //
> + // Get GPIO direction (GPIORxDis and GPIOTxDis)
> + //
> + GpioConfig->Direction = ((PadCfgDwReg[0] & (B_GPIO_PCR_RXDIS |
> B_GPIO_PCR_TXDIS)) >> (N_GPIO_PCR_TXDIS -
> (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (0x1 <<
> N_GPIO_DIRECTION_DIR_BIT_POS);
> +
> + //
> + // Get GPIO input inversion (RXINV)
> + // (Only meaningful if input enabled)
> + //
> + if((PadCfgDwReg[0] & B_GPIO_PCR_RXDIS) == 0) {
> + GpioConfig->Direction |= ((PadCfgDwReg[0] & B_GPIO_PCR_RXINV) >>
> (N_GPIO_PCR_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 <<
> N_GPIO_DIRECTION_INV_BIT_POS);
> + }
> +
> + //
> + // Get GPIO output state (GPIOTxState)
> + //
> + GpioConfig->OutputState = ((PadCfgDwReg[0] & B_GPIO_PCR_TX_STATE) <<
> (N_GPIO_PCR_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 <<
> N_GPIO_OUTPUT_BIT_POS);
> +
> + //
> + // Configure GPIO RX raw override to '1' (RXRAW1)
> + //
> + GpioConfig->OtherSettings = ((PadCfgDwReg[0] & B_GPIO_PCR_RX_RAW1)
> >> (N_GPIO_PCR_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)))
> | (0x1 << N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS);
> +
> + //
> + // Get GPIO Pad Mode (PMode)
> + //
> + GpioConfig->PadMode = ((PadCfgDwReg[0] & B_GPIO_PCR_PAD_MODE) >>
> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 <<
> N_GPIO_PAD_MODE_BIT_POS);
> +
> + //
> + // Get GPIO termination (Term)
> + //
> + GpioConfig->ElectricalConfig = ((PadCfgDwReg[1] & B_GPIO_PCR_TERM) >>
> (N_GPIO_PCR_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS
> + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS);
> +}
> +
> +/**
> + This procedure will read multiple GPIO settings
> +
> + @param[in] GpioPad GPIO Pad
> + @param[out] GpioData GPIO data structure
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioGetPadConfig (
> + IN GPIO_PAD GpioPad,
> + OUT GPIO_CONFIG *GpioData
> + )
> +{
> + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
> + UINT32 RegVal;
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> + UINT32 PadBitPosition;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Read PADCFG DW0 register
> + //
> + PadCfgDwReg[0] = GpioReadPadCfgReg (GpioPad, 0);
> +
> + //
> + // Read PADCFG DW1 register
> + //
> + PadCfgDwReg[1] = GpioReadPadCfgReg (GpioPad, 1);
> +
> + //
> + // Read PADCFG DW2 register
> + //
> + PadCfgDwReg[2] = GpioReadPadCfgReg (GpioPad, 2);
> +
> + GpioConfigFromPadCfgRegValue (
> + GpioPad,
> + PadCfgDwReg,
> + GpioData
> + );
> +
> + //
> + // Read HOSTSW_OWN registers
> + //
> + GpioReadReg (
> + GpioHostOwnershipRegister,
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + &RegVal
> + );
> +
> + //
> + // Get Host Software Ownership
> + //
> + GpioData->HostSoftPadOwn = (((RegVal >> PadBitPosition) & 0x1) <<
> (N_GPIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 <<
> N_GPIO_HOSTSW_OWN_BIT_POS);
> +
> + //
> + // Read PADCFGLOCK register
> + //
> + GpioReadReg (
> + GpioPadConfigLockRegister,
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + &RegVal
> + );
> +
> + //
> + // Get Pad Configuration Lock state
> + //
> + GpioData->LockConfig = ((!((RegVal >> PadBitPosition) & 0x1)) << 1) | 0x1;
> +
> + //
> + // Read PADCFGLOCKTX register
> + //
> + GpioReadReg (
> + GpioPadLockOutputRegister,
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + &RegVal
> + );
> +
> + //
> + // Get Pad Configuration Lock Tx state
> + //
> + GpioData->LockConfig |= ((!((RegVal >> PadBitPosition) & 0x1)) << 2) | 0x1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will calculate PADCFG register value based on GpioConfig
> data
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] GpioConfig GPIO Configuration data
> + @param[out] PadCfgDwReg PADCFG DWx register value
> + @param[out] PadCfgDwRegMask Mask with PADCFG DWx register
> bits to be modified
> +**/
> +VOID
> +GpioPadCfgRegValueFromGpioConfig (
> + IN GPIO_PAD GpioPad,
> + IN CONST GPIO_CONFIG *GpioConfig,
> + OUT UINT32 *PadCfgDwReg,
> + OUT UINT32 *PadCfgDwRegMask
> + )
> +{
> + UINT32 PadRstCfg;
> + EFI_STATUS Status;
> +
> + //
> + // Configure Reset Type (PadRstCfg)
> + // Reset configuration depends on group type.
> + // This field requires support for new and deprecated settings.
> + //
> + Status = GpioPadRstCfgFromResetConfig (
> + GpioPad,
> + GpioConfig->PowerConfig,
> + &PadRstCfg
> + );
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig &
> B_GPIO_RESET_CONFIG_RESET_MASK) >>
> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 :
> B_GPIO_PCR_RST_CONF);
> + PadCfgDwReg[0] |= PadRstCfg << N_GPIO_PCR_RST_CONF;
> +
> + //
> + // Configure how interrupt is triggered (RxEvCfg)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig &
> B_GPIO_INT_CONFIG_INT_TYPE_MASK) >>
> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 :
> B_GPIO_PCR_RX_LVL_EDG);
> + PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig &
> B_GPIO_INT_CONFIG_INT_TYPE_MASK) >>
> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX_LVL_EDG);
> +
> + //
> + // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig &
> B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >>
> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) == GpioHardwareDefault) ?
> 0x0 : (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE |
> B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE));
> + PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig &
> B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >>
> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) <<
> N_GPIO_PCR_RX_NMI_ROUTE);
> +
> + //
> + // Configure GPIO direction (GPIORxDis and GPIOTxDis)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->Direction &
> B_GPIO_DIRECTION_DIR_MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) ==
> GpioHardwareDefault) ? 0x0 : (B_GPIO_PCR_RXDIS | B_GPIO_PCR_TXDIS));
> + PadCfgDwReg[0] |= (((GpioConfig->Direction &
> B_GPIO_DIRECTION_DIR_MASK) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) <<
> N_GPIO_PCR_TXDIS);
> +
> + //
> + // Configure GPIO input inversion (RXINV)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->Direction &
> B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) ==
> GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RXINV);
> + PadCfgDwReg[0] |= (((GpioConfig->Direction &
> B_GPIO_DIRECTION_INV_MASK) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) <<
> N_GPIO_PCR_RXINV);
> +
> + //
> + // Configure GPIO output state (GPIOTxState)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->OutputState &
> B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) ==
> GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TX_STATE);
> + PadCfgDwReg[0] |= (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK)
> >> (N_GPIO_OUTPUT_BIT_POS + 1)) << N_GPIO_PCR_TX_STATE);
> +
> + //
> + // Configure GPIO RX raw override to '1' (RXRAW1)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->OtherSettings &
> B_GPIO_OTHER_CONFIG_RXRAW_MASK) >>
> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 :
> B_GPIO_PCR_RX_RAW1);
> + PadCfgDwReg[0] |= (((GpioConfig->OtherSettings &
> B_GPIO_OTHER_CONFIG_RXRAW_MASK) >>
> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_GPIO_PCR_RX_RAW1);
> +
> + //
> + // Configure GPIO Pad Mode (PMode)
> + //
> + PadCfgDwRegMask[0] |= ((((GpioConfig->PadMode &
> B_GPIO_PAD_MODE_MASK) >> N_GPIO_PAD_MODE_BIT_POS) ==
> GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_PAD_MODE);
> + PadCfgDwReg[0] |= (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK)
> >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_GPIO_PCR_PAD_MODE);
> +
> + //
> + // Configure GPIO termination (Term)
> + //
> + PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig &
> B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >>
> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) ==
> GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TERM);
> + PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig &
> B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >>
> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) <<
> N_GPIO_PCR_TERM);
> +}
> +
> +/**
> + This procedure will configure multiple GPIO settings
> +
> + @param[in] GpioPad GPIO Pad
> + @param[in] GpioData GPIO data structure
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioSetPadConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_CONFIG *GpioData
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
> + UINT32 PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER];
> + UINT32 HostSoftOwnReg;
> + UINT32 HostSoftOwnRegMask;
> + UINT32 GpiGpeEnReg;
> + UINT32 GpiGpeEnRegMask;
> + UINT32 GpiNmiEnReg;
> + UINT32 GpiNmiEnRegMask;
> + UINT32 GpiSmiEnReg;
> + UINT32 GpiSmiEnRegMask;
> + GPIO_GROUP Group;
> + UINT32 GroupIndex;
> + UINT32 PadNumber;
> + UINT32 PadBitPosition;
> + UINT32 DwNum;
> + GPIO_LOCK_CONFIG LockConfig;
> +
> + Status = EFI_SUCCESS;
> + ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
> + ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Check if Pad enabled for SCI is to be in unlocked state
> + //
> + if (((GpioData->InterruptConfig & GpioIntSci) == GpioIntSci) &&
> + ((GpioData->LockConfig &
> B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != GpioPadConfigUnlock)){
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a for SCI is not unlocked!\n",
> GpioName (GpioPad)));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Get GPIO PADCFG register value from GPIO config data
> + //
> + GpioPadCfgRegValueFromGpioConfig (
> + GpioPad,
> + GpioData,
> + PadCfgDwReg,
> + PadCfgDwRegMask
> + );
> +
> + //
> + // Write PADCFG DW0 register
> + //
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + ~PadCfgDwRegMask[0],
> + PadCfgDwReg[0]
> + );
> +
> + //
> + // Write PADCFG DW1 register
> + //
> + GpioWritePadCfgReg (
> + GpioPad,
> + 1,
> + ~PadCfgDwRegMask[1],
> + PadCfgDwReg[1]
> + );
> +
> + //
> + // Write PADCFG DW2 register
> + //
> + GpioWritePadCfgReg (
> + GpioPad,
> + 2,
> + ~PadCfgDwRegMask[2],
> + PadCfgDwReg[2]
> + );
> +
> + //
> + // Update value to be programmed in HOSTSW_OWN register
> + //
> + if ((GpioData->InterruptConfig & GpioIntSmi) == GpioIntSmi) {
> + HostSoftOwnRegMask = 1 << PadBitPosition;
> + HostSoftOwnReg = 1 << PadBitPosition;
> + } else {
> + HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) <<
> PadBitPosition;
> + HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) <<
> PadBitPosition;
> + }
> +
> + //
> + // Write HOSTSW_OWN registers
> + //
> + GpioWriteReg (
> + GpioHostOwnershipRegister,
> + Group,
> + DwNum,
> + ~HostSoftOwnRegMask,
> + HostSoftOwnReg
> + );
> +
> + //
> + // Update value to be programmed in GPI_GPE_EN register
> + //
> + GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
> + GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) <<
> PadBitPosition;
> +
> + //
> + // Write GPI_GPE_EN registers
> + //
> + GpioWriteReg (
> + GpioGpeEnableRegister,
> + Group,
> + DwNum,
> + ~GpiGpeEnRegMask,
> + GpiGpeEnReg
> + );
> +
> + //
> + // Update value to be programmed in GPI_NMI_EN register
> + //
> + GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
> + GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) <<
> PadBitPosition;
> +
> + if (GpioIsNmiSupportedByGroupDw (Group, DwNum)) {
> + GpioWriteReg (
> + GpioNmiEnableRegister,
> + Group,
> + DwNum,
> + ~GpiNmiEnRegMask,
> + GpiNmiEnReg
> + );
> + } else {
> + if (GpiNmiEnReg == 0) {
> + //
> + // Not all GPIO have NMI capabilities. Since we always try to program this
> register,
> + // even when not enabling NMI for a pad so do not report such access as
> an error
> + //
> + Status = EFI_SUCCESS;
> + } else {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads
> supporting NMI\n", GpioGetGroupName (GroupIndex)));
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> + }
> +
> + //
> + // Update value to be programmed in GPI_SMI_EN register
> + //
> + GpiSmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
> + GpiSmiEnReg = ((GpioData->InterruptConfig & GpioIntSmi) >> 2) <<
> PadBitPosition;
> +
> + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) {
> + GpioWriteReg (
> + GpioSmiEnableRegister,
> + Group,
> + DwNum,
> + ~GpiSmiEnRegMask,
> + GpiSmiEnReg
> + );
> + } else {
> + if (GpiSmiEnReg == 0) {
> + //
> + // Not all GPIO have SMI capabilities. Since we always try to program this
> register,
> + // even when not enabling SMI for a pad so do not report such access as
> an error
> + //
> + Status = EFI_SUCCESS;
> + } else {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads
> supporting SMI\n", GpioGetGroupName (GroupIndex)));
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> + }
> +
> + //
> + // Store unlock data
> + //
> + if (GpioData->LockConfig != GpioLockDefault) {
> + LockConfig = GpioData->LockConfig &
> B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK;
> + //
> + // If pad in GpioMode is an output default action should be to leave
> output unlocked
> + //
> + if ((GpioData->PadMode == GpioPadModeGpio) &&
> + (GpioData->Direction == GpioDirOut) &&
> + ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK)
> == GpioLockDefault)) {
> + LockConfig |= GpioOutputStateUnlock;
> + } else {
> + LockConfig |= GpioData->LockConfig &
> B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK;
> + }
> + Status = GpioStoreUnlockData (GpioPad, LockConfig);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + This procedure will set GPIO output level
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Output value
> + 0: OutputLow, 1: OutputHigh
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetOutputValue (
> + IN GPIO_PAD GpioPad,
> + IN UINT32 Value
> + )
> +{
> + if (Value > 1) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + (UINT32)~B_GPIO_PCR_TX_STATE,
> + Value << N_GPIO_PCR_TX_STATE
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO output level
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] OutputVal GPIO Output value
> + 0: OutputLow, 1: OutputHigh
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetOutputValue (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *OutputVal
> + )
> +{
> + UINT32 PadCfgReg;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
> +
> + *OutputVal = (PadCfgReg & B_GPIO_PCR_TX_STATE) >>
> N_GPIO_PCR_TX_STATE;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO input level
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] InputVal GPIO Input value
> + 0: InputLow, 1: InpuHigh
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetInputValue (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *InputVal
> + )
> +{
> + UINT32 PadCfgReg;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
> +
> + *InputVal = (PadCfgReg & B_GPIO_PCR_RX_STATE) >>
> N_GPIO_PCR_RX_STATE;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO IOxAPIC interrupt number
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] IrqNum IRQ number
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetPadIoApicIrqNumber (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *IrqNum
> + )
> +{
> + UINT32 PadCfgReg;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + PadCfgReg = GpioReadPadCfgReg (GpioPad, 1);
> +
> + *IrqNum = (PadCfgReg & B_GPIO_PCR_INTSEL) >> N_GPIO_PCR_INTSEL;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will configure GPIO input inversion
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Value for GPIO input inversion
> + 0: No input inversion, 1: Invert input
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetInputInversion (
> + IN GPIO_PAD GpioPad,
> + IN UINT32 Value
> + )
> +{
> + if (Value > 1) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + (UINT32)~B_GPIO_PCR_RXINV,
> + Value << N_GPIO_PCR_RXINV
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO pad input inversion value
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] InvertState GPIO inversion state
> + 0: No input inversion, 1: Inverted input
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetInputInversion (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *InvertState
> + )
> +{
> + UINT32 PadCfgReg;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
> +
> + *InvertState = (PadCfgReg & B_GPIO_PCR_RXINV) >> N_GPIO_PCR_RXINV;
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will set GPIO interrupt settings
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Value of Level/Edge
> + use GPIO_INT_CONFIG as argument
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetPadInterruptConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_INT_CONFIG Value
> + )
> +{
> + EFI_STATUS Status;
> + BOOLEAN IsNmiSupported;
> + UINT32 RxLvlEdgeValue;
> + UINT32 IntRouteValue;
> + UINT32 PadNumber;
> + UINT32 GpeEnable;
> + UINT32 NmiEnable;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + Status = EFI_SUCCESS;
> +
> + if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >>
> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) {
> + RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >>
> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX_LVL_EDG;
> +
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + (UINT32)~B_GPIO_PCR_RX_LVL_EDG,
> + RxLvlEdgeValue
> + );
> + }
> +
> + if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >>
> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) != GpioHardwareDefault) {
> +
> + IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >>
> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) <<
> N_GPIO_PCR_RX_NMI_ROUTE;
> +
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + (UINT32)~(B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE
> | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE),
> + IntRouteValue
> + );
> +
> + if ((Value & GpioIntSci) == GpioIntSci) {
> + GpeEnable = 0x1;
> + } else {
> + GpeEnable = 0x0;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioWriteReg (
> + GpioGpeEnableRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
> + GpeEnable << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +
> + if ((Value & GpioIntNmi) == GpioIntNmi) {
> + NmiEnable = 0x1;
> + } else {
> + NmiEnable = 0x0;
> + }
> +
> + IsNmiSupported = GpioIsNmiSupportedByGroupDw (
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber)
> + );
> + if (IsNmiSupported) {
> + GpioWriteReg (
> + GpioNmiEnableRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
> + NmiEnable << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> + } else {
> + if (NmiEnable == 0) {
> + //
> + // Not all GPIO have NMI capabilities. Since we always try to program
> this register,
> + // even when not enabling NMI for a pad so do not report such access
> as an error
> + //
> + return EFI_SUCCESS;
> + } else {
> + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads
> supporting NMI\n", GpioGetGroupName (GpioGetGroupIndexFromGpioPad
> (GpioPad))));
> + ASSERT (FALSE);
> + }
> + }
> + }
> +
> + return Status;
> +}
> +
> +/**
> + This procedure will set GPIO electrical settings
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Value of termination
> + use GPIO_ELECTRICAL_CONFIG as argument
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetPadElectricalConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_ELECTRICAL_CONFIG Value
> + )
> +{
> + UINT32 TermValue;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >>
> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) !=
> GpioHardwareDefault) {
> + TermValue = ((Value &
> B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >>
> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) <<
> N_GPIO_PCR_TERM;
> +
> + GpioWritePadCfgReg (
> + GpioPad,
> + 1,
> + (UINT32)~B_GPIO_PCR_TERM,
> + TermValue
> + );
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will set GPIO Reset settings
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Value for Pad Reset Configuration
> + use GPIO_RESET_CONFIG as argument
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetPadResetConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_RESET_CONFIG Value
> + )
> +{
> + UINT32 PadRstCfg;
> + EFI_STATUS Status;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >>
> N_GPIO_RESET_CONFIG_RESET_BIT_POS) != GpioHardwareDefault) {
> +
> + //
> + // Reset configuration depends on group type.
> + // This field requires support for new and deprecated settings.
> + //
> + Status = GpioPadRstCfgFromResetConfig (
> + GpioPad,
> + Value,
> + &PadRstCfg
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + GpioWritePadCfgReg (
> + GpioPad,
> + 0,
> + (UINT32)~B_GPIO_PCR_RST_CONF,
> + PadRstCfg << N_GPIO_PCR_RST_CONF
> + );
> + }
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO Reset settings
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] Value Value of Pad Reset Configuration
> + based on GPIO_RESET_CONFIG
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetPadResetConfig (
> + IN GPIO_PAD GpioPad,
> + IN GPIO_RESET_CONFIG *Value
> + )
> +{
> + UINT32 PadRstCfg;
> + UINT32 PadCfgDw0Reg;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!GpioIsPadHostOwned (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + PadCfgDw0Reg = GpioReadPadCfgReg (GpioPad, 0);
> +
> + //
> + // Get Reset Type (PadRstCfg)
> + //
> + PadRstCfg = (PadCfgDw0Reg & B_GPIO_PCR_RST_CONF) >>
> N_GPIO_PCR_RST_CONF;
> +
> + *Value = GpioResetConfigFromPadRstCfg (
> + GpioPad,
> + PadRstCfg
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO Host Software Pad Ownership for certain group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum Host Ownership register number for
> current group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[out] HostSwRegVal Value of Host Software Pad Ownership
> register
> + Bit position - PadNumber
> + Bit value - 0: ACPI Mode, 1: GPIO Driver mode
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioGetHostSwOwnershipForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + OUT UINT32 *HostSwRegVal
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GpioReadReg (
> + GpioHostOwnershipRegister,
> + Group,
> + DwNum,
> + HostSwRegVal
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPIO Host Software Pad Ownership for certain group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum Host Ownership register number for
> current group
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] HostSwRegVal Value of Host Software Pad Ownership
> register
> + Bit position - PadNumber
> + Bit value - 0: ACPI Mode, 1: GPIO Driver mode
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioSetHostSwOwnershipForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 HostSwRegVal
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GpioWriteReg (
> + GpioHostOwnershipRegister,
> + Group,
> + DwNum,
> + 0,
> + HostSwRegVal
> + );
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get Gpio Pad Host Software Ownership
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] PadHostSwOwn Value of Host Software Pad Owner
> + 0: ACPI Mode, 1: GPIO Driver mode
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetHostSwOwnershipForPad (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *PadHostSwOwn
> + )
> +{
> + UINT32 PadNumber;
> + UINT32 HostSwRegVal;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioReadReg (
> + GpioHostOwnershipRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + &HostSwRegVal
> + );
> +
> + *PadHostSwOwn = (HostSwRegVal >> GPIO_GET_PAD_POSITION
> (PadNumber)) & 0x1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will set Gpio Pad Host Software Ownership
> +
> + @param[in] GpioPad GPIO pad
> + @param[in] PadHostSwOwn Pad Host Software Owner
> + 0: ACPI Mode, 1: GPIO Driver mode
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioSetHostSwOwnershipForPad (
> + IN GPIO_PAD GpioPad,
> + IN UINT32 PadHostSwOwn
> + )
> +{
> + UINT32 PadNumber;
> +
> + if (!GpioIsPadValid (GpioPad) || (PadHostSwOwn > 1)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioWriteReg (
> + GpioHostOwnershipRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + (UINT32)~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
> + PadHostSwOwn << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get Gpio Pad Ownership
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] PadOwnVal Value of Pad Ownership
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioGetPadOwnership (
> + IN GPIO_PAD GpioPad,
> + OUT GPIO_PAD_OWN *PadOwnVal
> + )
> +{
> + UINT32 Mask;
> + UINT32 RegOffset;
> + UINT32 GroupIndex;
> + UINT32 PadNumber;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + UINT32 PadOwnRegValue;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + //
> + // Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
> + // One DWord register contains information for 8 pads.
> + //
> + RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3)
> * 0x4;
> +
> + //
> + // Calculate pad bit position within DWord register
> + //
> + PadNumber %= 8;
> + Mask = (BIT1 | BIT0) << (PadNumber * 4);
> +
> + PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS
> (GpioGroupInfo[GroupIndex].Community, RegOffset));
> +
> + *PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >>
> (PadNumber * 4));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will check state of Pad Config Lock for pads within one group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLock register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[out] PadCfgLockRegVal Value of PadCfgLock register
> + Bit position - PadNumber
> + Bit value - 0: NotLocked, 1: Locked
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioGetPadCfgLockForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + OUT UINT32 *PadCfgLockRegVal
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GpioReadReg (
> + GpioPadConfigLockRegister,
> + Group,
> + DwNum,
> + PadCfgLockRegVal
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will check state of Pad Config Lock for selected pad
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] PadCfgLock PadCfgLock for selected pad
> + 0: NotLocked, 1: Locked
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetPadCfgLock (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *PadCfgLock
> + )
> +{
> + UINT32 PadNumber;
> + UINT32 PadCfgLockRegVal;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioReadReg (
> + GpioPadConfigLockRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + &PadCfgLockRegVal
> + );
> +
> + *PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION
> (PadNumber)) & 0x1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will check state of Pad Config Tx Lock for pads within one
> group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLockTx register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
> + Bit position - PadNumber
> + Bit value - 0: NotLockedTx, 1: LockedTx
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioGetPadCfgLockTxForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + OUT UINT32 *PadCfgLockTxRegVal
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GpioReadReg (
> + GpioPadLockOutputRegister,
> + Group,
> + DwNum,
> + PadCfgLockTxRegVal
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will check state of Pad Config Tx Lock for selected pad
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] PadCfgLock PadCfgLockTx for selected pad
> + 0: NotLockedTx, 1: LockedTx
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetPadCfgLockTx (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *PadCfgLockTx
> + )
> +{
> + UINT32 PadNumber;
> + UINT32 PadCfgLockTxRegVal;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + GpioReadReg (
> + GpioPadLockOutputRegister,
> + GpioGetGroupFromGpioPad (GpioPad),
> + GPIO_GET_DW_NUM (PadNumber),
> + &PadCfgLockTxRegVal
> + );
> +
> + *PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION
> (PadNumber)) & 0x1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will clear PadCfgLock for selected pads within one group.
> + This function should be used only inside SMI.
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLock register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] PadsToUnlock Bitmask for pads which are going to be
> unlocked,
> + Bit position - PadNumber
> + Bit value - 0: DoNotUnlock, 1: Unlock
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioUnlockPadCfgForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 PadsToUnlock
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return GpioWriteLockReg (
> + GpioPadConfigLockRegister,
> + Group,
> + DwNum,
> + ~PadsToUnlock,
> + 0
> + );
> +}
> +
> +/**
> + This procedure will clear PadCfgLock for selected pad.
> + This function should be used only inside SMI.
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioUnlockPadCfg (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + return GpioUnlockPadCfgForGroupDw (
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + 1 << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +}
> +
> +/**
> + This procedure will set PadCfgLock for selected pads within one group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLock register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] PadsToLock Bitmask for pads which are going to be
> locked
> + Bit position - PadNumber
> + Bit value - 0: DoNotLock, 1: Lock
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioLockPadCfgForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 PadsToLock
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return GpioWriteLockReg (
> + GpioPadConfigLockRegister,
> + Group,
> + DwNum,
> + ~0u,
> + PadsToLock
> + );
> +}
> +
> +/**
> + This procedure will set PadCfgLock for selected pad
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioLockPadCfg (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + return GpioLockPadCfgForGroupDw (
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + 1 << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +}
> +
> +/**
> + This procedure will clear PadCfgLockTx for selected pads within one group.
> + This function should be used only inside SMI.
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLockTx register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] PadsToUnlockTx Bitmask for pads which are going to be
> unlocked,
> + Bit position - PadNumber
> + Bit value - 0: DoNotUnLockTx, 1: LockTx
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioUnlockPadCfgTxForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 PadsToUnlockTx
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return GpioWriteLockReg (
> + GpioPadLockOutputRegister,
> + Group,
> + DwNum,
> + ~PadsToUnlockTx,
> + 0
> + );
> +}
> +
> +/**
> + This procedure will clear PadCfgLockTx for selected pad.
> + This function should be used only inside SMI.
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioUnlockPadCfgTx (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + return GpioUnlockPadCfgTxForGroupDw (
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + 1 << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +}
> +
> +/**
> + This procedure will set PadCfgLockTx for selected pads within one group
> +
> + @param[in] Group GPIO group
> + @param[in] DwNum PadCfgLock register number for current
> group.
> + For group which has less then 32 pads per group
> DwNum must be 0.
> + @param[in] PadsToLockTx Bitmask for pads which are going to be
> locked,
> + Bit position - PadNumber
> + Bit value - 0: DoNotLockTx, 1: LockTx
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter
> number
> +**/
> +EFI_STATUS
> +GpioLockPadCfgTxForGroupDw (
> + IN GPIO_GROUP Group,
> + IN UINT32 DwNum,
> + IN UINT32 PadsToLockTx
> + )
> +{
> + if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return GpioWriteLockReg (
> + GpioPadLockOutputRegister,
> + Group,
> + DwNum,
> + ~0u,
> + PadsToLockTx
> + );
> +}
> +
> +/**
> + This procedure will set PadCfgLockTx for selected pad
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioLockPadCfgTx (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + return GpioLockPadCfgTxForGroupDw (
> + Group,
> + GPIO_GET_DW_NUM (PadNumber),
> + 1 << GPIO_GET_PAD_POSITION (PadNumber)
> + );
> +}
> +
> +/**
> + This procedure will get Group to GPE mapping.
> + It will assume that only first 32 pads can be mapped to GPE.
> + To handle cases where groups have more than 32 pads and higher part of
> group
> + can be mapped please refer to GpioGetGroupDwToGpeDwX()
> +
> + @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
> + @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
> + @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioGetGroupToGpeDwX (
> + IN GPIO_GROUP *GroupToGpeDw0,
> + IN GPIO_GROUP *GroupToGpeDw1,
> + IN GPIO_GROUP *GroupToGpeDw2
> + )
> +{
> + UINT32 GroupDw[3];
> + UINT32 Index;
> + EFI_STATUS Status;
> +
> + Status = GpioGetGroupDwToGpeDwX (
> + GroupToGpeDw0,
> + &GroupDw[0],
> + GroupToGpeDw1,
> + &GroupDw[1],
> + GroupToGpeDw2,
> + &GroupDw[2]
> + );
> +
> + for (Index = 0; Index < ARRAY_SIZE (GroupDw); Index++) {
> + if (GroupDw[Index] != 0) {
> + Status = EFI_UNSUPPORTED;
> + ASSERT (FALSE);
> + }
> + }
> + return Status;
> +}
> +
> +
> +/**
> + This procedure will get Group to GPE mapping. If group has more than 32
> bits
> + it is possible to map only single DW of pins (e.g. 0-31, 32-63) because
> + ACPI GPE_DWx register is 32 bits large.
> +
> + @param[out] GroupToGpeDw0 GPIO group mapped to GPE_DW0
> + @param[out] GroupDwForGpeDw0 DW of pins mapped to GPE_DW0
> + @param[out] GroupToGpeDw1 GPIO group mapped to GPE_DW1
> + @param[out] GroupDwForGpeDw1 DW of pins mapped to GPE_DW1
> + @param[out] GroupToGpeDw2 GPIO group mapped to GPE_DW2
> + @param[out] GroupDwForGpeDw2 DW of pins mapped to GPE_DW2
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioGetGroupDwToGpeDwX (
> + OUT GPIO_GROUP *GroupToGpeDw0,
> + OUT UINT32 *GroupDwForGpeDw0,
> + OUT GPIO_GROUP *GroupToGpeDw1,
> + OUT UINT32 *GroupDwForGpeDw1,
> + OUT GPIO_GROUP *GroupToGpeDw2,
> + OUT UINT32 *GroupDwForGpeDw2
> + )
> +{
> + UINT32 PmcGpeDwXValue[3];
> + GPIO_GROUP GroupToGpeDwX[3];
> + UINT32 GroupDwForGpeDwX[3];
> + UINT8 GpeDwXIndex;
> + UINT32 Index;
> + GPIO_GROUP_TO_GPE_MAPPING *GpioGpeMap;
> + UINT32 GpioGpeMapLength;
> +
> + ZeroMem (GroupToGpeDwX, sizeof (GroupToGpeDwX));
> + ZeroMem (GroupDwForGpeDwX, sizeof (GroupDwForGpeDwX));
> +
> + PmcGetGpioGpe (&PmcGpeDwXValue[0], &PmcGpeDwXValue[1],
> &PmcGpeDwXValue[2]);
> +
> + GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength);
> +
> + for (GpeDwXIndex = 0; GpeDwXIndex < 3; GpeDwXIndex++) {
> + for (Index = 0; Index < GpioGpeMapLength; Index++) {
> +
> + if (GpioGpeMap[Index].PmcGpeDwxVal ==
> PmcGpeDwXValue[GpeDwXIndex]) {
> + GroupToGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].Group;
> + GroupDwForGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].GroupDw;
> + break;
> + }
> + }
> + }
> +
> + if ((GroupToGpeDwX[0] == 0) ||
> + (GroupToGpeDwX[1] == 0) ||
> + (GroupToGpeDwX[2] == 0)) {
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> +
> + *GroupToGpeDw0 = GroupToGpeDwX[0];
> + *GroupDwForGpeDw0 = GroupDwForGpeDwX[0];
> + *GroupToGpeDw1 = GroupToGpeDwX[1];
> + *GroupDwForGpeDw1 = GroupDwForGpeDwX[1];
> + *GroupToGpeDw2 = GroupToGpeDwX[2];
> + *GroupDwForGpeDw2 = GroupDwForGpeDwX[2];
> +
> + return EFI_SUCCESS;
> +}
> +
> +
> +/**
> + This procedure will set Group to GPE mapping.
> + It will assume that only first 32 pads can be mapped to GPE.
> + To handle cases where groups have more than 32 pads and higher part of
> group
> + can be mapped please refer to GpioSetGroupDwToGpeDwX()
> +
> + @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
> + @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
> + @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioSetGroupToGpeDwX (
> + IN GPIO_GROUP GroupToGpeDw0,
> + IN GPIO_GROUP GroupToGpeDw1,
> + IN GPIO_GROUP GroupToGpeDw2
> + )
> +{
> + return GpioSetGroupDwToGpeDwX (
> + GroupToGpeDw0,
> + 0,
> + GroupToGpeDw1,
> + 0,
> + GroupToGpeDw2,
> + 0
> + );
> +}
> +
> +/**
> + This procedure will set Group to GPE mapping. If group has more than 32
> bits
> + it is possible to map only single DW of pins (e.g. 0-31, 32-63) because
> + ACPI GPE_DWx register is 32 bits large.
> +
> + @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
> + @param[in] GroupDwForGpeDw0 DW of pins to be mapped to
> GPE_DW0
> + @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
> + @param[in] GroupDwForGpeDw1 DW of pins to be mapped to
> GPE_DW1
> + @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
> + @param[in] GroupDwForGpeDw2 DW of pins to be mapped to
> GPE_DW2
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioSetGroupDwToGpeDwX (
> + IN GPIO_GROUP GroupToGpeDw0,
> + IN UINT32 GroupDwForGpeDw0,
> + IN GPIO_GROUP GroupToGpeDw1,
> + IN UINT32 GroupDwForGpeDw1,
> + IN GPIO_GROUP GroupToGpeDw2,
> + IN UINT32 GroupDwForGpeDw2
> + )
> +{
> + UINT32 Data32Or;
> + UINT32 Data32And;
> + PCH_SBI_PID *GpioComSbiIds;
> + UINT32 NoOfGpioComs;
> + UINT32 GpioComIndex;
> + UINT32 GpioGpeDwx[3];
> + UINT32 PmcGpeDwx[3];
> + GPIO_GROUP GroupToGpeDwX[3];
> + UINT32 GroupDwForGpeDwX[3];
> + UINT8 GpeDwXIndex;
> + UINT32 Index;
> + GPIO_GROUP_TO_GPE_MAPPING *GpioGpeMap;
> + UINT32 GpioGpeMapLength;
> +
> + ZeroMem (GpioGpeDwx, sizeof (GpioGpeDwx));
> + ZeroMem (PmcGpeDwx, sizeof (PmcGpeDwx));
> + //
> + // Check if each group number is unique
> + //
> + if ((GroupToGpeDw0 == GroupToGpeDw1) ||
> + (GroupToGpeDw0 == GroupToGpeDw2) ||
> + (GroupToGpeDw1 == GroupToGpeDw2)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + GroupToGpeDwX[0] = GroupToGpeDw0;
> + GroupDwForGpeDwX[0] = GroupDwForGpeDw0;
> + GroupToGpeDwX[1] = GroupToGpeDw1;
> + GroupDwForGpeDwX[1] = GroupDwForGpeDw1;
> + GroupToGpeDwX[2] = GroupToGpeDw2;
> + GroupDwForGpeDwX[2] = GroupDwForGpeDw2;
> +
> + GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength);
> +
> + for (GpeDwXIndex = 0; GpeDwXIndex < 3; GpeDwXIndex++) {
> + for (Index = 0; Index < GpioGpeMapLength; Index++) {
> +
> + if ((GpioGpeMap[Index].Group == GroupToGpeDwX[GpeDwXIndex]) &&
> + (GpioGpeMap[Index].GroupDw ==
> GroupDwForGpeDwX[GpeDwXIndex])) {
> + PmcGpeDwx[GpeDwXIndex] = GpioGpeMap[Index].PmcGpeDwxVal;
> + GpioGpeDwx[GpeDwXIndex] = GpioGpeMap[Index].GpioGpeDwxVal;
> + break;
> + }
> + }
> +
> + if (Index == GpioGpeMapLength) {
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> + }
> +
> + //
> + // Program GPE configuration in PMC register
> + //
> + PmcSetGpioGpe (
> + PmcGpeDwx[0],
> + PmcGpeDwx[1],
> + PmcGpeDwx[2]
> + );
> +
> + //
> + // Program GPE configuration in GPIO registers
> + //
> + Data32And = (UINT32) ~(B_GPIO_PCR_MISCCFG_GPE0_DW2 |
> B_GPIO_PCR_MISCCFG_GPE0_DW1 | B_GPIO_PCR_MISCCFG_GPE0_DW0);
> + Data32Or = (UINT32) ((GpioGpeDwx[2] <<
> N_GPIO_PCR_MISCCFG_GPE0_DW2) |
> + (GpioGpeDwx[1] << N_GPIO_PCR_MISCCFG_GPE0_DW1) |
> + (GpioGpeDwx[0] << N_GPIO_PCR_MISCCFG_GPE0_DW0));
> +
> + NoOfGpioComs = GpioGetComSbiPortIds (&GpioComSbiIds);
> +
> + //
> + // Program MISCCFG register for each community
> + //
> + for (GpioComIndex = 0; GpioComIndex < NoOfGpioComs; GpioComIndex++)
> {
> + MmioAndThenOr32 (
> + PCH_PCR_ADDRESS (GpioComSbiIds[GpioComIndex],
> R_GPIO_PCR_MISCCFG),
> + Data32And,
> + Data32Or
> + );
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure will get GPE number for provided GpioPad.
> + PCH allows to configure mapping between GPIO groups and related GPE
> (GpioSetGroupToGpeDwX())
> + what results in the fact that certain Pad can cause different General Purpose
> Event. Only three
> + GPIO groups can be mapped to cause unique GPE (1-tier), all others groups
> will be under one common
> + event (GPE_111 for 2-tier).
> +
> + 1-tier:
> + Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
> + to determine what _LXX ACPI method would be called on event on selected
> GPIO pad
> +
> + 2-tier:
> + Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to
> 1-tier GPE
> + will be under one master GPE_111 which is linked to _L6F ACPI method. If it
> is needed to determine
> + what Pad from 2-tier has caused the event, _L6F method should check
> GPI_GPE_STS and GPI_GPE_EN
> + registers for all GPIO groups not mapped to 1-tier GPE.
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] GpeNumber GPE number
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetGpeNumber (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *GpeNumber
> + )
> +{
> + GPIO_GROUP GroupToGpeDwX[3];
> + UINT32 GroupDw[3];
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> + UINT32 Index;
> + EFI_STATUS Status;
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Get GPIO groups mapping to 1-tier GPE
> + // This mapping is dependent on GPIO IP implementation
> + // and may change between chipset generations
> + //
> + Status = GpioGetGroupDwToGpeDwX (
> + &GroupToGpeDwX[0], &GroupDw[0],
> + &GroupToGpeDwX[1], &GroupDw[1],
> + &GroupToGpeDwX[2], &GroupDw[2]
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Check if pad is routed to 1-Tier GPE
> + //
> + for (Index = 0; Index < 3; Index++) {
> + if ((Group == GroupToGpeDwX[Index]) && (PadNumber >= (32 *
> GroupDw[Index])) && (PadNumber < (32 * (GroupDw[Index] + 1)))) {
> + *GpeNumber = PadNumber + (32 * Index) - (32 * GroupDw[Index]);
> + return EFI_SUCCESS;
> + }
> + }
> +
> + //
> + // If Group number doesn't match any of above then
> + // it means that the pad is routed to 2-tier GPE
> + // which corresponds to GPE_111 (0x6F)
> + //
> + *GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used to clear SMI STS for a specified Pad
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioClearGpiSmiSts (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> + UINT32 DwNum;
> + UINT32 PadBitPosition;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> +
> + //
> + // Clear GPI SMI Status bit by writing '1'
> + //
> + GpioWriteReg (
> + GpioSmiStatusRegister,
> + Group,
> + DwNum,
> + 0u,
> + (UINT32) (BIT0 << PadBitPosition)
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used by PchSmiDispatcher and will clear
> + all GPI SMI Status bits
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioClearAllGpiSmiSts (
> + VOID
> + )
> +{
> + UINT32 DwNum;
> + GPIO_GROUP Group;
> + GPIO_GROUP GroupMin;
> + GPIO_GROUP GroupMax;
> +
> + GroupMin = GpioGetLowestGroup ();
> + GroupMax = GpioGetHighestGroup ();
> +
> + for (Group = GroupMin; Group <= GroupMax; Group++) {
> + //
> + // Clear all GPI SMI STS
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup
> (Group)); DwNum++) {
> + if (GpioIsSmiSupportedByGroupDw(Group, DwNum)) {
> + GpioWriteReg (
> + GpioSmiStatusRegister,
> + Group,
> + DwNum,
> + 0u,
> + 0xFFFFFFFF
> + );
> + }
> + }
> + }
> + return EFI_SUCCESS;
> +
> +}
> +
> +/**
> + This procedure is used to disable all GPI SMI
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioDisableAllGpiSmi (
> + VOID
> + )
> +{
> + UINT32 DwNum;
> + GPIO_GROUP Group;
> + GPIO_GROUP GroupMin;
> + GPIO_GROUP GroupMax;
> + UINT32 SmiEnRegVal;
> +
> + GroupMin = GpioGetLowestGroup ();
> + GroupMax = GpioGetHighestGroup ();
> +
> + for (Group = GroupMin; Group <= GroupMax; Group++) {
> + //
> + // Disable all GPI SMI
> + //
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup
> (Group)); DwNum++) {
> + if (GpioIsSmiSupportedByGroupDw (Group, DwNum)) {
> + SmiEnRegVal = 0;
> + //
> + // Check which pins have SMI_EN set
> + //
> + GpioReadReg (
> + GpioSmiEnableRegister,
> + Group,
> + DwNum,
> + &SmiEnRegVal
> + );
> + //
> + // Set HOSTSW_OWN to GPIO mode (1) for those pins to disable SMI
> capability
> + //
> + GpioWriteReg (
> + GpioHostOwnershipRegister,
> + Group,
> + DwNum,
> + ~0u,
> + SmiEnRegVal
> + );
> + }
> + }
> + }
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used to register GPI SMI dispatch function.
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] GpiNum GPI number
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetGpiSmiNum (
> + IN GPIO_PAD GpioPad,
> + OUT UINTN *GpiNum
> + )
> +{
> + UINT32 GroupIndex;
> + UINT32 Index;
> + UINT32 PadNumber;
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> +
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> +
> + *GpiNum = 0;
> +
> + for (Index = 0; Index < GroupIndex; Index++) {
> + *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
> + }
> + *GpiNum += (UINTN) PadNumber;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier
> architecture
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval Data 0 means 1-tier, 1 means 2-tier
> +**/
> +BOOLEAN
> +GpioCheckFor2Tier (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + UINT32 Data32;
> + EFI_STATUS Status;
> +
> + Status = GpioGetGpeNumber (GpioPad, &Data32);
> + if (EFI_ERROR (Status)) {
> + DEBUG (( DEBUG_ERROR, "GpioCheckFor2Tier: Failed to get GPE number.
> Status: %r\n", Status ));
> + return FALSE;
> + }
> +
> + if (Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + This procedure is used to clear GPE STS for a specified GpioPad
> +
> + @param[in] GpioPad GPIO pad
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioClearGpiGpeSts (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> + UINT32 DwNum;
> + UINT32 PadBitPosition;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Check for 2-tier
> + //
> + if (!(GpioCheckFor2Tier (GpioPad))) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> +
> + //
> + // Clear GPI GPE Status bit by writing '1'
> + //
> + GpioWriteReg (
> + GpioGpeStatusRegister,
> + Group,
> + DwNum,
> + 0u,
> + (UINT32) (BIT0 << PadBitPosition)
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used to read GPE STS for a specified Pad
> +
> + @param[in] GpioPad GPIO pad
> + @param[out] Data GPE STS data
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid GpioPad
> +**/
> +EFI_STATUS
> +GpioGetGpiGpeSts (
> + IN GPIO_PAD GpioPad,
> + OUT UINT32 *Data
> + )
> +{
> + UINT32 GpeStsRegVal;
> + GPIO_GROUP Group;
> + UINT32 PadNumber;
> + UINT32 DwNum;
> + UINT32 PadBitPosition;
> +
> + if (!GpioIsPadValid (GpioPad)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Check for 2-tier
> + //
> + if (!(GpioCheckFor2Tier (GpioPad))) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Group = GpioGetGroupFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + DwNum = GPIO_GET_DW_NUM (PadNumber);
> + PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
> +
> + //
> + // Read GPI GPE Status bits
> + //
> + GpioReadReg (
> + GpioGpeStatusRegister,
> + Group,
> + DwNum,
> + &GpeStsRegVal
> + );
> +
> + *Data = (GpeStsRegVal >> PadBitPosition) & 0x1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This procedure is used to lock all GPIO pads except the ones
> + which were requested during their configuration to be left unlocked.
> + This function must be called before BIOS_DONE - before POSTBOOT_SAI is
> enabled.
> + FSP - call this function from wrapper before transition to FSP-S
> + UEFI/EDK - call this function before EndOfPei event
> +
> + @retval EFI_SUCCESS The function completed successfully
> + @retval EFI_INVALID_PARAMETER Invalid group or pad number
> +**/
> +EFI_STATUS
> +GpioLockPads (
> + VOID
> + )
> +{
> + UINT32 DwNum;
> + GPIO_GROUP Group;
> + GPIO_GROUP GroupMin;
> + GPIO_GROUP GroupMax;
> + UINT32 UnlockedPads;
> + EFI_STATUS Status;
> +
> + GroupMin = GpioGetLowestGroup ();
> + GroupMax = GpioGetHighestGroup ();
> +
> + for (Group = GroupMin; Group <= GroupMax; Group++) {
> + for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup
> (Group)); DwNum++) {
> +
> + UnlockedPads = GpioGetGroupDwUnlockPadConfigMask
> (GpioGetGroupIndexFromGroup (Group), DwNum);
> +
> + Status = GpioLockPadCfgForGroupDw (Group, DwNum,
> (UINT32)~UnlockedPads);
> + if (EFI_ERROR (Status)) {
> + ASSERT (FALSE);
> + return Status;
> + }
> +
> + UnlockedPads = GpioGetGroupDwUnlockOutputMask
> (GpioGetGroupIndexFromGroup (Group), DwNum);
> +
> + Status = GpioLockPadCfgTxForGroupDw (Group, DwNum,
> (UINT32)~UnlockedPads);
> + if (EFI_ERROR (Status)) {
> + ASSERT (FALSE);
> + return Status;
> + }
> + }
> + }
> + return EFI_SUCCESS;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> mes.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> mes.c
> new file mode 100644
> index 0000000000..ec33d06156
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> mes.c
> @@ -0,0 +1,87 @@
> +/** @file
> + This file contains GPIO name library implementation
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GpioLibrary.h"
> +#include <Library/PrintLib.h>
> +
> +/**
> + Generates GPIO group name from GpioPad
> +
> + @param[in] GpioPad GpioPad
> +
> + @retval CHAR8* Pointer to the GPIO group name
> +**/
> +CONST
> +CHAR8*
> +GpioGetGroupName (
> + IN UINT32 GroupIndex
> + )
> +{
> + CONST GPIO_GROUP_NAME_INFO* GroupNameInfo;
> +
> + GroupNameInfo = GpioGetGroupNameInfo (GroupIndex);
> + if (GroupNameInfo == NULL) {
> + return NULL;
> + } else {
> + return GroupNameInfo->GpioGroupPrefix;
> + }
> +}
> +
> +/**
> + Generates GPIO name from GpioPad
> +
> + @param[in] GpioPad GpioPad
> + @param[out] GpioNameBuffer Caller allocated buffer of
> GPIO_NAME_LENGTH_MAX size
> + @param[in] GpioNameBufferSize Size of the buffer
> +
> + @retval CHAR8* Pointer to the GPIO name
> +**/
> +CHAR8*
> +GpioGetPadName (
> + IN GPIO_PAD GpioPad,
> + OUT CHAR8* GpioNameBuffer,
> + IN UINT32 GpioNameBufferSize
> + )
> +{
> + UINT32 GroupIndex;
> + UINT32 PadNumber;
> + UINT32 FirstUniquePadNumber;
> + CONST GPIO_GROUP_NAME_INFO* GroupNameInfo;
> +
> + if (GpioNameBuffer == NULL) {
> + ASSERT (FALSE);
> + return NULL;
> + }
> + if ((GpioNameBufferSize < GPIO_NAME_LENGTH_MAX) || !GpioIsPadValid
> (GpioPad)) {
> + ASSERT (FALSE);
> + *GpioNameBuffer = 0;
> + return NULL;
> + }
> +
> + GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
> + PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
> + GroupNameInfo = GpioGetGroupNameInfo (GroupIndex);
> + if (GroupNameInfo == NULL) {
> + return NULL;
> + }
> +
> + FirstUniquePadNumber = GpioGetPadNumberFromGpioPad
> (GroupNameInfo->FirstUniqueGpio);
> + if ((PadNumber < FirstUniquePadNumber) ||
> (GroupNameInfo->GroupUniqueNames == NULL)) {
> + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a%d",
> GpioGetGroupName (GroupIndex), PadNumber);
> + } else {
> + if (PadNumber - FirstUniquePadNumber <
> GroupNameInfo->UniqueNamesTableSize) {
> + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a",
> GroupNameInfo->GroupUniqueNames[PadNumber -
> FirstUniquePadNumber]);
> + } else {
> + AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%08X",
> GpioPad);
> + ASSERT (FALSE);
> + }
> + }
> +
> + return GpioNameBuffer;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> tiveLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> tiveLib.c
> new file mode 100644
> index 0000000000..9b71cb1d95
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNa
> tiveLib.c
> @@ -0,0 +1,234 @@
> +/** @file
> + This file contains routines for GPIO native and chipset specific usage
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GpioLibrary.h"
> +
> +/**
> + This procedure will get number of pads for certain GPIO group
> +
> + @param[in] Group GPIO group number
> +
> + @retval Value Pad number for group
> + If illegal group number then return 0
> +**/
> +UINT32
> +GpioGetPadPerGroup (
> + IN GPIO_GROUP Group
> + )
> +{
> + CONST GPIO_GROUP_INFO *GpioGroupInfo;
> + UINT32 GpioGroupInfoLength;
> + UINT32 GroupIndex;
> + //
> + // Check if group argument exceeds GPIO GROUP INFO array
> + //
> + GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
> + GroupIndex = GpioGetGroupIndexFromGroup (Group);
> +
> + if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
> + return 0;
> + } else {
> + return GpioGroupInfo[GroupIndex].PadPerGroup;
> + }
> +}
> +
> +/**
> + This procedure will get number of groups
> +
> + @param[in] none
> +
> + @retval Value Group number
> +**/
> +UINT32
> +GpioGetNumberOfGroups (
> + VOID
> + )
> +{
> + UINT32 GpioGroupInfoLength;
> +
> + GpioGetGroupInfoTable (&GpioGroupInfoLength);
> + return GpioGroupInfoLength;
> +}
> +/**
> + This procedure will get lowest group
> +
> + @param[in] none
> +
> + @retval Value Lowest Group
> +**/
> +GPIO_GROUP
> +GpioGetLowestGroup (
> + VOID
> + )
> +{
> + return GpioGetGroupFromGroupIndex (0);
> +}
> +/**
> + This procedure will get highest group
> +
> + @param[in] none
> +
> + @retval Value Highest Group
> +**/
> +GPIO_GROUP
> +GpioGetHighestGroup (
> + VOID
> + )
> +{
> + return GpioGetGroupFromGroupIndex (GpioGetNumberOfGroups () - 1);
> +}
> +
> +/**
> + This procedure will get group number
> +
> + @param[in] GpioPad Gpio Pad
> +
> + @retval Value Group number
> +**/
> +GPIO_GROUP
> +GpioGetGroupFromGpioPad (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + return GPIO_GET_GROUP_FROM_PAD (GpioPad);
> +}
> +
> +/**
> + This procedure will get group index (0 based)
> +
> + @param[in] GpioPad Gpio Pad
> +
> + @retval Value Group Index
> +**/
> +UINT32
> +GpioGetGroupIndexFromGpioPad (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
> +}
> +
> +/**
> + This procedure will get group index (0 based) from group
> +
> + @param[in] GpioGroup Gpio Group
> +
> + @retval Value Group Index
> +**/
> +UINT32
> +GpioGetGroupIndexFromGroup (
> + IN GPIO_GROUP GpioGroup
> + )
> +{
> + return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
> +}
> +
> +/**
> + This procedure will get group from group index (0 based)
> +
> + @param[in] GroupIndex Group Index
> +
> + @retval GpioGroup Gpio Group
> +**/
> +GPIO_GROUP
> +GpioGetGroupFromGroupIndex (
> + IN UINT32 GroupIndex
> + )
> +{
> + return GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ());
> +}
> +
> +/**
> + This procedure will get pad number (0 based) from Gpio Pad
> +
> + @param[in] GpioPad Gpio Pad
> +
> + @retval Value Pad Number
> +**/
> +UINT32
> +GpioGetPadNumberFromGpioPad (
> + IN GPIO_PAD GpioPad
> + )
> +{
> + return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad);
> +}
> +/**
> + This procedure will return GpioPad from Group and PadNumber
> +
> + @param[in] Group GPIO group
> + @param[in] PadNumber GPIO PadNumber
> +
> + @retval GpioPad GpioPad
> +**/
> +GPIO_PAD
> +GpioGetGpioPadFromGroupAndPadNumber (
> + IN GPIO_GROUP Group,
> + IN UINT32 PadNumber
> + )
> +{
> + if (IsPchLp ()) {
> + return GPIO_PAD_DEF (Group,PadNumber);
> + } else {
> + return GPIO_PAD_DEF (Group,PadNumber);
> + }
> +}
> +
> +/**
> + This procedure will return GpioPad from GroupIndex and PadNumber
> +
> + @param[in] GroupIndex GPIO GroupIndex
> + @param[in] PadNumber GPIO PadNumber
> +
> + @retval GpioPad GpioPad
> +**/
> +GPIO_PAD
> +GpioGetGpioPadFromGroupIndexAndPadNumber (
> + IN UINT32 GroupIndex,
> + IN UINT32 PadNumber
> + )
> +{
> + GPIO_GROUP Group;
> +
> + Group = GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ());
> + return GPIO_PAD_DEF (Group, PadNumber);
> +}
> +
> +/**
> + This function checks if SATA GP pin is enabled
> +
> + @param[in] SataCtrlIndex SATA controller index
> + @param[in] SataPort SATA port number
> +
> + @retval TRUE SATA GPx is enabled (pad is in required native
> mode)
> + FALSE SATA GPx is not enabled
> +**/
> +BOOLEAN
> +GpioIsSataGpEnabled (
> + IN UINT32 SataCtrlIndex,
> + IN UINTN SataPort
> + )
> +{
> + EFI_STATUS Status;
> + GPIO_PAD_NATIVE_FUNCTION SataGpGpio;
> + GPIO_PAD_MODE GpioMode;
> +
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + GpioGetSataGpPin (
> + SataCtrlIndex,
> + SataPort,
> + &SataGpGpio
> + );
> +
> + Status = GpioGetPadMode (SataGpGpio.Pad, &GpioMode);
> + if ((EFI_ERROR (Status)) || (GpioMode != SataGpGpio.Mode)) {
> + return FALSE;
> + } else {
> + return TRUE;
> + }
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PchCycleDecodingLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PchCycleDecodingLib.c
> new file mode 100644
> index 0000000000..24afbbf712
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodi
> ngLib/PchCycleDecodingLib.c
> @@ -0,0 +1,1136 @@
> +/** @file
> + PCH cycle deocding configuration and query library.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Private/Library/PchDmiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PchEspiLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +#include <Register/PchRegsSmbus.h>
> +
> +typedef enum {
> + SlaveLpcEspiCS0,
> + SlaveEspiCS1,
> + SlaveId_Max
> +} SLAVE_ID_INDEX;
> +
> +/**
> + Set PCH TCO base address.
> + This cycle decoding is required also on DMI side
> + Programming steps:
> + 1. set Smbus PCI offset 54h [8] to enable TCO base address.
> + 2. program Smbus PCI offset 50h [15:5] to TCO base address.
> + 3. set Smbus PCI offset 54h [8] to enable TCO base address.
> + 4. program "TCO Base Address" in DMI
> +
> + @param[in] Address Address for TCO base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchTcoBaseSet (
> + IN UINT16 Address
> + )
> +{
> + UINT64 SmbusBase;
> + EFI_STATUS Status;
> +
> + if ((Address & ~B_SMBUS_CFG_TCOBASE_BAR) != 0) {
> + DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n",
> Address));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = PchDmiSetTcoBase (Address);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> +
> + SmbusBase = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SMBUS,
> + PCI_FUNCTION_NUMBER_PCH_SMBUS,
> + 0
> + );
> + if (PciSegmentRead16 (SmbusBase) == 0xFFFF) {
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> + }
> + //
> + // Verify TCO base is not locked.
> + //
> + if ((PciSegmentRead8 (SmbusBase + R_SMBUS_CFG_TCOCTL) &
> B_SMBUS_CFG_TCOCTL_TCO_BASE_LOCK) != 0) {
> + ASSERT (FALSE);
> + return EFI_DEVICE_ERROR;
> + }
> + //
> + // Disable TCO in SMBUS Device first before changing base address.
> + // Byte access to not touch the TCO_BASE_LOCK bit
> + //
> + PciSegmentAnd8 (
> + SmbusBase + R_SMBUS_CFG_TCOCTL + 1,
> + (UINT8) ~(B_SMBUS_CFG_TCOCTL_TCO_BASE_EN >> 8)
> + );
> + //
> + // Program TCO in SMBUS Device
> + //
> + PciSegmentAndThenOr16 (
> + SmbusBase + R_SMBUS_CFG_TCOBASE,
> + (UINT16) (~B_SMBUS_CFG_TCOBASE_BAR),
> + Address
> + );
> + //
> + // Enable TCO in SMBUS Device and lock TCO BASE
> + //
> + PciSegmentOr16 (
> + SmbusBase + R_SMBUS_CFG_TCOCTL,
> + B_SMBUS_CFG_TCOCTL_TCO_BASE_EN |
> B_SMBUS_CFG_TCOCTL_TCO_BASE_LOCK
> + );
> +
> + return Status;
> +}
> +
> +/**
> + Get PCH TCO base address.
> +
> + @param[out] Address Address of TCO base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid pointer passed.
> +**/
> +EFI_STATUS
> +PchTcoBaseGet (
> + OUT UINT16 *Address
> + )
> +{
> + if (Address == NULL) {
> + DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> + //
> + // Read "TCO Base Address" from DMI
> + // Don't read TCO base address from SMBUS PCI register since SMBUS might
> be disabled.
> + //
> + *Address = PchDmiGetTcoBase ();
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Returns PCH LPC device PCI base address.
> +
> + @retval PCH LPC PCI base address.
> +**/
> +STATIC
> +UINT64
> +LpcPciBase (
> + VOID
> + )
> +{
> + return PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_LPC,
> + PCI_FUNCTION_NUMBER_PCH_LPC,
> + 0
> + );
> +}
> +
> +/**
> + Function checks if passed Generic LPC IO Address and Length meets
> requirements.
> +
> + @param[in] Address Address for generic IO range decoding.
> + @param[in] Length Length of generic IO range.
> +
> + @retval TRUE Passed IO range meets requirements
> + @retval FALSE Passed IO range does not meets
> requirements.
> +**/
> +STATIC
> +BOOLEAN
> +IsLpcIoRangeValid (
> + IN UINT32 Address,
> + IN UINT32 Length
> + )
> +{
> + UINT32 Index;
> + UINT32 NumRanges;
> +
> + STATIC struct EXCEPT_RANGE {
> + UINT8 Start;
> + UINT8 Length;
> + } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08},
> {0x80, 0x10}, {0xC0, 0x40} };
> +
> + NumRanges = ARRAY_SIZE (ExceptRanges);
> + //
> + // For generic IO range, the base address must align to 4 and less than
> 0xFFFF,
> + // the length must be power of 2 and less than or equal to 256, and the
> address must be length aligned.
> + // IO range below 0x100 will be rejected in this function except below
> ranges:
> + // 0x00-0x1F,
> + // 0x44-0x4B,
> + // 0x54-0x5F,
> + // 0x68-0x6F,
> + // 0x80-0x8F,
> + // 0xC0-0xFF
> + //
> + if (((Length & (Length - 1)) != 0) ||
> + ((Address & (UINT16) ~B_LPC_CFG_GENX_DEC_IOBAR) != 0) ||
> + (Length > 256)) {
> + return FALSE;
> + }
> + if (Address < 0x100) {
> + for (Index = 0; Index < NumRanges; Index++) {
> + if ((Address >= ExceptRanges[Index].Start) &&
> + ((Address + Length) <= ((UINTN) ExceptRanges[Index].Start + (UINTN)
> ExceptRanges[Index].Length))) {
> + break;
> + }
> + }
> + if (Index >= NumRanges) {
> + return FALSE;
> + }
> + }
> +
> + return TRUE;
> +}
> +
> +/**
> + Function checks if passed Generic LPC IO Range is already in Gen IO Range list
> +
> + @param[in] Address Address for generic IO range decoding.
> + @param[in] Length Length of generic IO range.
> + @param[in] GenIoRangeList Pointer to Generic IO Ranges List
> +
> + @retval TRUE Passed IO range alredy covered
> + @retval FALSE Passed IO range NOT covered
> +**/
> +STATIC
> +BOOLEAN
> +IsRangeInList (
> + IN UINT32 Address,
> + IN UINT32 Length,
> + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList
> + )
> +{
> + UINT32 CurrentBaseAddr;
> + UINT32 CurrentLength;
> + UINT32 Index;
> +
> + for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
> + CurrentBaseAddr = GenIoRangeList->Range[Index].BaseAddr;
> + CurrentLength = GenIoRangeList->Range[Index].Length;
> + if (GenIoRangeList->Range[Index].Enable == 0) {
> + continue;
> + }
> + if ((Address >= CurrentBaseAddr) && ((Address + Length) <=
> (CurrentBaseAddr + CurrentLength))) {
> + return TRUE;
> + }
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Function checks if passed Generic LPC IO Range overlaps with existing range
> +
> + @param[in] Address Address for generic IO range base
> address.
> + @param[in] Length Length of generic IO range.
> + @param[in] GenIoRangeList Pointer to Generic IO Ranges List
> +
> + @retval TRUE Passed LPC IO range overlaps with existing
> range
> + @retval FALSE Passed LPC IO range NOT overlaps
> +**/
> +STATIC
> +BOOLEAN
> +FindOverlappingGenIoRange (
> + IN UINT32 Address,
> + IN UINT32 Length,
> + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList
> + )
> +{
> + UINT32 Index;
> + UINT32 CurrentBaseAddr;
> + UINT32 CurrentLength;
> +
> + for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
> + CurrentBaseAddr = GenIoRangeList->Range[Index].BaseAddr;
> + CurrentLength = GenIoRangeList->Range[Index].Length;
> + if (GenIoRangeList->Range[Index].Enable == 0) {
> + continue;
> + }
> +
> + if ((Address >= CurrentBaseAddr) &&
> + (Address <= (CurrentBaseAddr + CurrentLength))) {
> + return TRUE;
> + } else if (((Address + Length) >= CurrentBaseAddr) &&
> + ((Address + Length) <= (CurrentBaseAddr + CurrentLength))) {
> + return TRUE;
> + }
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Function look for empty Generic IO range register.
> + If found return range index.
> +
> + @param[in] GenIoRangeList Pointer to Generic IO Ranges List
> + @param[in] ListLength Length of passed list
> + @param[out] RangeIndex Generic IO Range Index
> +
> + @retval TRUE Empty range found
> + @retval FALSE NOT found empty range
> +**/
> +STATIC
> +BOOLEAN
> +FindEmptyGenIoRange (
> + IN PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList,
> + IN UINT32 ListLength,
> + OUT UINT32 *RangeIndex
> + )
> +{
> + UINT32 Index;
> +
> + for (Index = 0; Index < ListLength; Index++) {
> + if (GenIoRangeList->Range[Index].Enable == 0) {
> + *RangeIndex = Index;
> + return TRUE;
> + }
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Get PCH LPC/eSPI and eSPI CS1# generic IO range list.
> + This function returns a list of base address, length, and enable for all
> LPC/eSPI or eSPI CS1# generic IO range registers.
> +
> + @param[in] RangeIndex Slave ID (refer to SLAVE_ID_INDEX)
> + @param[out] GenIoRangeList LPC/eSPI or eSPI CS1# generic IO
> range registers.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> +**/
> +EFI_STATUS
> +LpcEspiGenIoRangeGetHelper (
> + IN SLAVE_ID_INDEX SlaveId,
> + OUT PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList
> + )
> +{
> + UINT32 Index;
> + UINT64 LpcBase;
> + UINT32 Data32;
> + UINT32 GenIoReg;
> +
> + if ((GenIoRangeList == NULL) || (SlaveId >= SlaveId_Max)) {
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + LpcBase = LpcPciBase ();
> +
> + if (SlaveId == SlaveEspiCS1) {
> + GenIoReg = R_ESPI_CFG_CS1GIR1;
> + } else {
> + GenIoReg = R_LPC_CFG_GEN1_DEC;
> + }
> +
> + for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
> + if ((SlaveId == SlaveEspiCS1) &&
> + (Index > 0)) {
> + // For eSPI CS1# we have only one range. Reset remaining entries to zero.
> + GenIoRangeList->Range[Index].BaseAddr = 0;
> + GenIoRangeList->Range[Index].Enable = 0;
> + GenIoRangeList->Range[Index].Length = 0;
> + continue;
> + }
> + Data32 = PciSegmentRead32 (LpcBase + GenIoReg + Index * 4);
> + GenIoRangeList->Range[Index].BaseAddr = Data32 &
> B_LPC_CFG_GENX_DEC_IOBAR;
> + GenIoRangeList->Range[Index].Length = ((Data32 &
> B_LPC_CFG_GENX_DEC_IODRA) >> 16) + 4;
> + GenIoRangeList->Range[Index].Enable = Data32 &
> B_LPC_CFG_GENX_DEC_EN;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +
> +/**
> + Function checks if passed Generic LPC IO Range colliding
> + with range alredy defined for other eSPI chiselect (CS)
> +
> + @param[in] Address Address for generic IO range base
> address.
> + @param[in] Length Length of generic IO range.
> + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
> +
> + @retval TRUE Passed IO range conflicting
> + @retval FALSE There is no conflict
> +**/
> +STATIC
> +BOOLEAN
> +IsRangeColliding (
> + IN UINT32 Address,
> + IN UINT32 Length,
> + IN SLAVE_ID_INDEX SlaveId
> + )
> +{
> + EFI_STATUS Status;
> + PCH_LPC_GEN_IO_RANGE_LIST GenIoRangeList;
> +
> + if (SlaveId == SlaveEspiCS1) {
> + Status = LpcEspiGenIoRangeGetHelper (SlaveLpcEspiCS0,
> &GenIoRangeList);
> + if (!EFI_ERROR (Status)) {
> + if (FindOverlappingGenIoRange (Address, Length, &GenIoRangeList) ||
> + IsRangeInList (Address, Length, &GenIoRangeList)) {
> + return TRUE;
> + }
> + }
> + } else {
> + Status = LpcEspiGenIoRangeGetHelper (SlaveEspiCS1, &GenIoRangeList);
> + if (!EFI_ERROR (Status)) {
> + if (FindOverlappingGenIoRange (Address, Length, &GenIoRangeList) ||
> + IsRangeInList (Address, Length, &GenIoRangeList)) {
> + return TRUE;
> + }
> + }
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Set PCH LPC/eSPI and eSPI CS1# generic IO range decoding.
> +
> + Steps of programming generic IO range:
> + 1. Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI CS1#)
> of Mask, Address, and Enable.
> + 2. Program LPC/eSPI Generic IO Range in DMI
> +
> + @param[in] Address Address for generic IO range decoding.
> + @param[in] Length Length of generic IO range.
> + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> + @retval EFI_OUT_OF_RESOURCES No more generic range available.
> + @retval EFI_UNSUPPORTED DMI configuration is locked,
> + GenIO range conflicting with other eSPI CS
> +**/
> +STATIC
> +EFI_STATUS
> +LpcEspiGenIoRangeSetHelper (
> + IN UINT32 Address,
> + IN UINT32 Length,
> + IN SLAVE_ID_INDEX SlaveId
> + )
> +{
> + EFI_STATUS Status;
> + PCH_LPC_GEN_IO_RANGE_LIST GenIoRangeList;
> + UINT32 RangeIndex;
> + UINT32 Data32;
> + UINT32 GenIoReg;
> + UINT32 ListLength;
> +
> + //
> + // Check if pasesed Address and Length meets all requirements
> + //
> + if(!IsLpcIoRangeValid (Address, Length) || (SlaveId >= SlaveId_Max)) {
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Read current Generic IO configuration
> + //
> + Status = LpcEspiGenIoRangeGetHelper (SlaveId, &GenIoRangeList);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Check if passed Generic IO range is already covered in current
> configuration
> + //
> + if (IsRangeInList (Address, Length, &GenIoRangeList)) {
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Check if passed Generic IO range conflicting with other eSPI CS decoding
> + //
> + if (IsRangeColliding (Address, Length, SlaveId)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (SlaveId == SlaveEspiCS1) {
> + GenIoReg = R_ESPI_CFG_CS1GIR1;
> + ListLength = ESPI_CS1_GEN_IO_RANGE_MAX;
> + } else {
> + GenIoReg = R_LPC_CFG_GEN1_DEC;
> + ListLength = PCH_LPC_GEN_IO_RANGE_MAX;
> + }
> +
> + RangeIndex = ListLength;
> + //
> + // Check if there is an empty Generic IO range register
> + //
> + if (FindEmptyGenIoRange (&GenIoRangeList, ListLength, &RangeIndex) ==
> FALSE) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + //
> + // Program decoding in DMI and LPC/eSPI registers
> + //
> + if (SlaveId == SlaveEspiCS1) {
> + ASSERT (RangeIndex == 0);
> + Status = PchDmiSetEspiCs1GenIoRange (Address, Length);
> + } else {
> + Status = PchDmiSetLpcGenIoRange (Address, Length, RangeIndex);
> + }
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Program LPC/eSPI generic IO range register accordingly.
> + //
> + Data32 = (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA);
> + Data32 |= (UINT32) Address;
> + Data32 |= B_LPC_CFG_GENX_DEC_EN;
> +
> + //
> + // Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI CS1#)
> of Mask, Address, and Enable.
> + //
> + PciSegmentWrite32 (
> + LpcPciBase () + GenIoReg + RangeIndex * 4,
> + Data32
> + );
> +
> + return Status;
> +}
> +
> +/**
> + Set PCH LPC/eSPI generic IO range.
> + For generic IO range, the base address must align to 4 and less than 0xFFFF,
> and the length must be power of 2
> + and less than or equal to 256. Moreover, the address must be length aligned.
> + This function basically checks the address and length, which should not
> overlap with all other generic ranges.
> + If no more generic range register available, it returns out of resource error.
> + This cycle decoding is also required on DMI side
> + Some IO ranges below 0x100 have fixed target. The target might be
> ITSS,RTC,LPC,PMC or terminated inside P2SB
> + but all predefined and can't be changed. IO range below 0x100 will be
> rejected in this function except below ranges:
> + 0x00-0x1F,
> + 0x44-0x4B,
> + 0x54-0x5F,
> + 0x68-0x6F,
> + 0x80-0x8F,
> + 0xC0-0xFF
> + Steps of programming generic IO range:
> + 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
> + 2. Program LPC/eSPI Generic IO Range in DMI
> +
> + @param[in] Address Address for generic IO range base
> address.
> + @param[in] Length Length of generic IO range.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> + @retval EFI_OUT_OF_RESOURCES No more generic range available.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchLpcGenIoRangeSet (
> + IN UINT16 Address,
> + IN UINTN Length
> + )
> +{
> + return LpcEspiGenIoRangeSetHelper ((UINT32)Address, (UINT32)Length,
> SlaveLpcEspiCS0);
> +}
> +
> +/**
> + Set PCH eSPI CS1# generic IO range decoding.
> +
> + Steps of programming generic IO range:
> + 1. Program eSPI PCI Offset A4h (eSPI CS1#) of Mask, Address, and Enable.
> + 2. Program eSPI Generic IO Range in DMI
> +
> + @param[in] Address Address for generic IO range decoding.
> + @param[in] Length Length of generic IO range.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> + @retval EFI_OUT_OF_RESOURCES No more generic range available.
> + @retval EFI_UNSUPPORTED eSPI secondary slave not supported
> +**/
> +EFI_STATUS
> +PchEspiCs1GenIoRangeSet (
> + IN UINT16 Address,
> + IN UINTN Length
> + )
> +{
> + if (!IsEspiSecondSlaveSupported ()) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LpcEspiGenIoRangeSetHelper ((UINT32)Address, (UINT32)Length,
> SlaveEspiCS1);
> +}
> +
> +/**
> + Get PCH LPC/eSPI generic IO range list.
> + This function returns a list of base address, length, and enable for all
> LPC/eSPI generic IO range registers.
> +
> + @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO range
> register status.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> +**/
> +EFI_STATUS
> +PchLpcGenIoRangeGet (
> + OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
> + )
> +{
> + return LpcEspiGenIoRangeGetHelper (SlaveLpcEspiCS0,
> LpcGenIoRangeList);
> +}
> +
> +/**
> + Get PCH eSPI CS1# generic IO range list.
> + This function returns a list of base address, length, and enable for all eSPI
> CS1# generic IO range registers.
> +
> + @param[out] GenIoRangeList eSPI generic IO range registers.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> + @retval EFI_UNSUPPORTED eSPI secondary slave not supported
> +**/
> +EFI_STATUS
> +PchEspiCs1GenIoRangeGet (
> + OUT PCH_LPC_GEN_IO_RANGE_LIST *GenIoRangeList
> + )
> +{
> + if (!IsEspiSecondSlaveSupported ()) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LpcEspiGenIoRangeGetHelper (SlaveEspiCS1, GenIoRangeList);
> +}
> +
> +/**
> + Set PCH LPC/eSPI and eSPI CS1# memory range decoding.
> + This cycle decoding is required to be set on DMI side
> + Programming steps:
> + 1. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [0] to
> [0] to disable memory decoding first before changing base address.
> + 2. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [31:16,
> 0] to [Address, 1].
> + 3. Program LPC/eSPI Memory Range in DMI
> +
> + @param[in] Address Address for memory for decoding.
> + @param[in] RangeIndex Slave ID (refer to SLAVE_ID_INDEX)
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> +**/
> +EFI_STATUS
> +LpcEspiMemRangeSetHelper (
> + IN UINT32 Address,
> + IN SLAVE_ID_INDEX SlaveId
> + )
> +{
> + UINT64 LpcBase;
> + EFI_STATUS Status;
> + UINT32 GenMemReg;
> + UINT32 MemRangeAddr;
> +
> + if (((Address & (~B_LPC_CFG_LGMR_MA)) != 0) || (SlaveId >= SlaveId_Max))
> {
> + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeSet Error. Invalid Address:
> %x or invalid SlaveId\n", Address));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + LpcBase = LpcPciBase ();
> +
> + MemRangeAddr = ~Address;
> + if (SlaveId == SlaveEspiCS1) {
> + GenMemReg = R_ESPI_CFG_CS1GMR1;
> + // Memory Range already decoded for LPC/eSPI?
> + Status = PchLpcMemRangeGet (&MemRangeAddr);
> + if (MemRangeAddr != Address) {
> + Status = PchDmiSetEspiCs1MemRange (Address);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> + }
> + } else {
> + GenMemReg = R_LPC_CFG_LGMR;
> + // Memory Range already decoded for eSPI CS1?
> + Status = PchEspiCs1MemRangeGet (&MemRangeAddr);
> + if (MemRangeAddr != Address) {
> + Status = PchDmiSetLpcMemRange (Address);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> + }
> + }
> +
> + //
> + // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [0] to
> [0] to disable memory decoding first before changing base address.
> + //
> + PciSegmentAnd32 (
> + LpcBase + GenMemReg,
> + (UINT32) ~B_LPC_CFG_LGMR_LMRD_EN
> + );
> + //
> + // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [31:16,
> 0] to [Address, 1].
> + //
> + PciSegmentWrite32 (
> + LpcBase + GenMemReg,
> + (Address | B_LPC_CFG_LGMR_LMRD_EN)
> + );
> +
> + return Status;
> +}
> +
> +/**
> + Set PCH LPC/eSPI memory range decoding.
> + This cycle decoding is required to be set on DMI side
> + Programming steps:
> + 1. Program LPC PCI Offset 98h [0] to [0] to disable memory decoding first
> before changing base address.
> + 2. Program LPC PCI Offset 98h [31:16, 0] to [Address, 1].
> + 3. Program LPC Memory Range in DMI
> +
> + @param[in] Address Address for memory base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> + @retval EFI_OUT_OF_RESOURCES No more generic range available.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchLpcMemRangeSet (
> + IN UINT32 Address
> + )
> +{
> + return LpcEspiMemRangeSetHelper (Address, SlaveLpcEspiCS0);
> +}
> +
> +/**
> + Set PCH eSPI CS1# memory range decoding.
> + This cycle decoding is required to be set on DMI side
> + Programming steps:
> + 1. Program eSPI PCI Offset A8h (eSPI CS1#) [0] to [0] to disable memory
> decoding first before changing base address.
> + 2. Program eSPI PCI Offset A8h (eSPI CS1#) [31:16, 0] to [Address, 1].
> + 3. Program eSPI Memory Range in DMI
> +
> + @param[in] Address Address for memory for decoding.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address or length
> passed.
> + @retval EFI_UNSUPPORTED eSPI secondary slave not supported
> +**/
> +EFI_STATUS
> +PchEspiCs1MemRangeSet (
> + IN UINT32 Address
> + )
> +{
> + if (!IsEspiSecondSlaveSupported ()) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LpcEspiMemRangeSetHelper (Address, SlaveEspiCS1);
> +}
> +
> +/**
> + @deprecated. Keep this for backward compatibility.
> + It's replaced by PchEspiCs1MemRangeSet.
> +**/
> +EFI_STATUS
> +PchEspiMemRange2Set (
> + IN UINT32 Address
> + )
> +{
> + return PchEspiCs1MemRangeSet (Address);
> +}
> +
> +/**
> + Get PCH LPC/eSPI and eSPI CS1# memory range decoding address.
> +
> + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
> + @param[out] Address Address of LPC/eSPI or eSPI CS1#
> memory decoding base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> + @retval EFI_UNSUPPORTED eSPI secondary slave not supported
> +**/
> +EFI_STATUS
> +LpcEspiMemRangeGetHelper (
> + IN SLAVE_ID_INDEX SlaveId,
> + OUT UINT32 *Address
> + )
> +{
> + UINT32 GenMemReg;
> +
> + if ((Address == NULL) || (SlaveId >= SlaveId_Max)) {
> + DEBUG ((DEBUG_ERROR, "PchLpcEspiMemRangeGet Error. Invalid pointer
> or SlaveId.\n"));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (SlaveId == SlaveEspiCS1) {
> + GenMemReg = R_ESPI_CFG_CS1GMR1;
> + } else {
> + GenMemReg = R_LPC_CFG_LGMR;
> + }
> + *Address = PciSegmentRead32 (LpcPciBase () + GenMemReg) &
> B_LPC_CFG_LGMR_MA;
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get PCH LPC/eSPI memory range decoding address.
> +
> + @param[out] Address Address of LPC/eSPI memory decoding
> base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> +**/
> +EFI_STATUS
> +PchLpcMemRangeGet (
> + OUT UINT32 *Address
> + )
> +{
> + return LpcEspiMemRangeGetHelper (SlaveLpcEspiCS0, Address);
> +}
> +
> +/**
> + Get PCH eSPI CS1# memory range decoding address.
> +
> + @param[out] Address Address of eSPI CS1# memory decoding
> base address.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid base address passed.
> + @retval EFI_UNSUPPORTED eSPI secondary slave not supported
> +**/
> +EFI_STATUS
> +PchEspiCs1MemRangeGet (
> + OUT UINT32 *Address
> + )
> +{
> + if (!IsEspiSecondSlaveSupported ()) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LpcEspiMemRangeGetHelper (SlaveEspiCS1, Address);
> +}
> +
> +/**
> + Set PCH BIOS range deocding.
> + This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or
> LPC/eSPI and program BDE register accordingly.
> + Please check EDS for detail of BiosDecodeEnable bit definition.
> + bit 15: F8-FF Enable
> + bit 14: F0-F8 Enable
> + bit 13: E8-EF Enable
> + bit 12: E0-E8 Enable
> + bit 11: D8-DF Enable
> + bit 10: D0-D7 Enable
> + bit 9: C8-CF Enable
> + bit 8: C0-C7 Enable
> + bit 7: Legacy F Segment Enable
> + bit 6: Legacy E Segment Enable
> + bit 5: Reserved
> + bit 4: Reserved
> + bit 3: 70-7F Enable
> + bit 2: 60-6F Enable
> + bit 1: 50-5F Enable
> + bit 0: 40-4F Enable
> + This cycle decoding is also required in DMI
> + Programming steps:
> + 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
> + if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
> + 2. program LPC BIOS Decode Enable in DMI
> +
> + @param[in] BiosDecodeEnable Bios decode enable setting.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchBiosDecodeEnableSet (
> + IN UINT16 BiosDecodeEnable
> + )
> +{
> + UINT64 BaseAddr;
> + EFI_STATUS Status;
> +
> + Status = PchDmiSetBiosDecodeEnable (BiosDecodeEnable);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> +
> + //
> + // Check Boot BIOS Strap in DMI
> + //
> + if (PchDmiIsBootBiosStrapSetForSpi ()) {
> + BaseAddr = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + 0
> + );
> + //
> + // Read SPI CFG cycle before write SPI CFG cycle
> + PciSegmentRead16 (BaseAddr + R_SPI_CFG_BDE);
> + //
> + // If SPI, Program SPI offset D8h to BiosDecodeEnable.
> + //
> + PciSegmentWrite16 (BaseAddr + R_SPI_CFG_BDE, BiosDecodeEnable);
> + } else {
> + BaseAddr = LpcPciBase ();
> + //
> + // If LPC/eSPi, program LPC offset D8h to BiosDecodeEnable.
> + //
> + PciSegmentWrite16 (BaseAddr + R_LPC_CFG_BDE, BiosDecodeEnable);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Set PCH LPC/eSPI IO decode ranges.
> + Program LPC/eSPI I/O Decode Ranges in DMI to the same value programmed
> in LPC/eSPI PCI offset 80h.
> + Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
> + Bit 12: FDD range
> + Bit 9:8: LPT range
> + Bit 6:4: ComB range
> + Bit 2:0: ComA range
> +
> + @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit
> settings.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchLpcIoDecodeRangesSet (
> + IN UINT16 LpcIoDecodeRanges
> + )
> +{
> + UINT64 LpcBaseAddr;
> + EFI_STATUS Status;
> +
> + //
> + // Note: Inside this function, don't use debug print since it's could used
> before debug print ready.
> + //
> +
> + LpcBaseAddr = LpcPciBase ();
> +
> + //
> + // check if setting is identical
> + //
> + if (LpcIoDecodeRanges == PciSegmentRead16 (LpcBaseAddr +
> R_LPC_CFG_IOD)) {
> + return EFI_SUCCESS;
> + }
> +
> + Status = PchDmiSetLpcIoDecodeRanges (LpcIoDecodeRanges);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> +
> + //
> + // program LPC/eSPI PCI offset 80h.
> + //
> + PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOD, LpcIoDecodeRanges);
> +
> + return Status;
> +}
> +
> +/**
> + Set PCH LPC/eSPI and eSPI CS1# IO enable decoding.
> + Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset
> 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#).
> + Note: Bit[15:10] of the source decode register is Read-Only. The IO range
> indicated by the Enables field
> + in LPC/eSPI PCI offset 82h[13:10] or A0h[13:10] is always forwarded by DMI
> to subtractive agent for handling.
> + Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
> +
> + @param[in] IoEnableDecoding LPC/eSPI IO enable decoding bit
> settings.
> + @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_UNSUPPORTED DMI configuration is locked
> +**/
> +EFI_STATUS
> +LpcEspiIoEnableDecodingSetHelper (
> + IN UINT16 IoEnableDecoding,
> + IN SLAVE_ID_INDEX SlaveId
> + )
> +{
> + UINT64 LpcBaseAddr;
> + EFI_STATUS Status;
> + UINT16 Cs1IoEnableDecodingOrg;
> + UINT16 Cs0IoEnableDecodingOrg;
> + UINT16 IoEnableDecodingMerged;
> +
> + LpcBaseAddr = LpcPciBase ();
> +
> + Cs0IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr +
> R_LPC_CFG_IOE);
> +
> + if (IsEspiSecondSlaveSupported ()) {
> + Cs1IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr +
> R_ESPI_CFG_CS1IORE);
> + } else {
> + Cs1IoEnableDecodingOrg = 0;
> + }
> +
> + if (SlaveId == SlaveEspiCS1) {
> + if (IoEnableDecoding == Cs1IoEnableDecodingOrg) {
> + return EFI_SUCCESS;
> + } else {
> + IoEnableDecodingMerged = (Cs0IoEnableDecodingOrg |
> IoEnableDecoding);
> + }
> + } else {
> + if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) ==
> Cs0IoEnableDecodingOrg) {
> + return EFI_SUCCESS;
> + } else {
> + IoEnableDecodingMerged = (Cs1IoEnableDecodingOrg |
> IoEnableDecoding);
> + }
> + }
> +
> + Status = PchDmiSetLpcIoEnable (IoEnableDecodingMerged);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> + }
> +
> + //
> + // program PCI offset 82h for LPC/eSPI.
> + //
> + PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOE,
> IoEnableDecodingMerged);
> +
> + if (SlaveId == SlaveEspiCS1) {
> + //
> + // For eSPI CS1# device program eSPI PCI offset A0h.
> + //
> + PciSegmentWrite16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE,
> IoEnableDecoding);
> + }
> +
> + return Status;
> +}
> +
> +
> +/**
> + Set PCH LPC and eSPI CS0# IO enable decoding.
> + Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset
> 82h.
> + Note: Bit[15:10] of the source decode register is Read-Only. The IO range
> indicated by the Enables field
> + in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive
> agent for handling.
> + Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
> +
> + @param[in] LpcIoEnableDecoding LPC IO enable decoding bit settings.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_UNSUPPORTED DMIC.SRL is set.
> +**/
> +EFI_STATUS
> +PchLpcIoEnableDecodingSet (
> + IN UINT16 LpcIoEnableDecoding
> + )
> +{
> + return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding,
> SlaveLpcEspiCS0);
> +}
> +
> +/**
> + Set PCH eSPI CS1# IO enable decoding.
> + Setup I/O Enables in DMI to the same value program in eSPI PCI offset A0h
> (eSPI CS1#).
> + Note: Bit[15:10] of the source decode register is Read-Only. The IO range
> indicated by the Enables field
> + in eSPI PCI offset A0h[13:10] is always forwarded by DMI to subtractive agent
> for handling.
> + Please check EDS for detail of eSPI IO decode ranges bit definition.
> +
> + @param[in] IoEnableDecoding eSPI IO enable decoding bit settings.
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_UNSUPPORTED DMI configuration is locked
> +**/
> +EFI_STATUS
> +PchEspiCs1IoEnableDecodingSet (
> + IN UINT16 IoEnableDecoding
> + )
> +{
> + if (!IsEspiSecondSlaveSupported ()) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LpcEspiIoEnableDecodingSetHelper (IoEnableDecoding,
> SlaveEspiCS1);
> +}
> +
> +/**
> + Set PCH IO port 80h cycle decoding to PCIE root port.
> + System BIOS is likely to do this very soon after reset before PCI bus
> enumeration.
> + This cycle decoding is allowed to set when DMI is unlocked
> +
> + @param[in] RpNumber PCIE root port physical number.
> +
> + @retval EFI_SUCCESS Successfully completed.
> +**/
> +EFI_STATUS
> +PchIoPort80DecodeSet (
> + IN UINTN RpNumber
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = PchDmiSetIoPort80Decode (RpNumber);
> + ASSERT_EFI_ERROR (Status);
> +
> + return Status;
> +}
> +
> +/**
> + Get IO APIC registers base address.
> +
> + @param[out] IoApicBase Buffer of IO APIC register address
> +
> + @retval EFI_SUCCESS Successfully completed.
> +**/
> +EFI_STATUS
> +PchIoApicBaseGet (
> + OUT UINT32 *IoApicBase
> + )
> +{
> + *IoApicBase = PcdGet32 (PcdIoApicBaseAddress);
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get HPET base address.
> +
> + @param[out] HpetBase Buffer of HPET base address
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_INVALID_PARAMETER Invalid offset passed.
> +**/
> +EFI_STATUS
> +PchHpetBaseGet (
> + OUT UINT32 *HpetBase
> + )
> +{
> + if (HpetBase == NULL) {
> + DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n"));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *HpetBase = PcdGet32 (PcdSiHpetBaseAddress);
> + return EFI_SUCCESS;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchE
> spiLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchE
> spiLib.c
> new file mode 100644
> index 0000000000..1bbecc71ed
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchEspiLib/PchE
> spiLib.c
> @@ -0,0 +1,505 @@
> +/** @file
> + This file contains routines for eSPI
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PchEspiLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/TimerLib.h>
> +#include <PchLimits.h>
> +#include <Register/PchRegsPcr.h>
> +#include <Register/PchRegsLpc.h>
> +
> +#define CHANNEL_RESET_TIMEOUT 100 ///< Channel reset timeout in
> us after which to report error
> +#define SLAVE_CHANNELS_MAX 7 ///< Max number of channels
> +
> +//
> +// eSPI Slave registers
> +//
> +#define R_ESPI_SLAVE_GENCAP 0x08 ///< General Capabilities
> and Configurations
> +#define B_ESPI_SLAVE_GENCAP_SUPPCHAN 0xFF ///< Channels
> supported bit mask
> +#define R_ESPI_SLAVE_CHACAP_BASE 0x10 ///< Base address
> from which channel Cap and Conf registers start on slave
> +#define S_ESPI_SLAVE_CHACAP_OFFSET 0x10 ///< Offset for each
> channel from base
> +#define B_ESPI_SLAVE_CHACAP_CHEN BIT0 ///< Slave Channel
> enable bit
> +#define B_ESPI_SLAVE_CHACAP_CHRDY BIT1 ///< Slave Channel
> ready bit
> +
> +/**
> + Checks if second slave capability is enabled
> +
> + @retval TRUE There's second slave
> + @retval FALSE There's no second slave
> +**/
> +BOOLEAN
> +IsEspiSecondSlaveSupported (
> + VOID
> + )
> +{
> + return (IsPchH () && ((PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SOFTSTRAPS)
> & R_ESPI_PCR_SOFTSTRAPS_CS1_EN) != 0));
> +}
> +
> +/**
> + Checks in slave General Capabilities register if it supports channel with
> requested number
> +
> + @param[in] SlaveId Id of slave to check
> + @param[in] ChannelNumber Number of channel of which to check
> +
> + @retval TRUE Channel with requested number is supported by slave
> device
> + @retval FALSE Channel with requested number is not supported by slave
> device
> +**/
> +BOOLEAN
> +IsEspiSlaveChannelSupported (
> + UINT8 SlaveId,
> + UINT8 ChannelNumber
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 Data32;
> + UINT8 SupportedChannels;
> +
> + Status = PchEspiSlaveGetConfig (SlaveId, R_ESPI_SLAVE_GENCAP, &Data32);
> + if (EFI_ERROR (Status)) {
> + return FALSE;
> + }
> + SupportedChannels = (UINT8) (Data32 &
> B_ESPI_SLAVE_GENCAP_SUPPCHAN);
> +
> + DEBUG ((DEBUG_INFO, "Slave %d supported channels 0x%4X\n", SlaveId,
> SupportedChannels));
> +
> + if (ChannelNumber > SLAVE_CHANNELS_MAX || !(SupportedChannels &
> (BIT0 << ChannelNumber))) {
> + // Incorrect channel number was specified. Either exceeded max or Slave
> doesn't support that channel.
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
> +
> +/**
> + Is eSPI enabled in strap.
> +
> + @retval TRUE Espi is enabled in strap
> + @retval FALSE Espi is disabled in strap
> +**/
> +BOOLEAN
> +IsEspiEnabled (
> + VOID
> + )
> +{
> + return (PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_CFG_VAL) &
> B_ESPI_PCR_CFG_VAL_ESPI_EN) != 0;
> +}
> +
> +/**
> + eSPI helper function to clear slave configuration register status
> +
> + @retval EFI_SUCCESS Write to private config space succeed
> + @retval others Read / Write failed
> +**/
> +STATIC
> +VOID
> +EspiClearScrs (
> + VOID
> + )
> +{
> + PchPcrAndThenOr32 (
> + PID_ESPISPI,
> + R_ESPI_PCR_SLV_CFG_REG_CTL,
> + (UINT32) ~0,
> + B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS
> + );
> +}
> +
> +/**
> + eSPI helper function to poll slave configuration register enable for 0
> + and to check for slave configuration register status
> +
> + @retval EFI_SUCCESS Enable bit is zero and no error in status bits
> + @retval EFI_DEVICE_ERROR Error in SCRS
> + @retval others Read / Write to private config space failed
> +**/
> +STATIC
> +EFI_STATUS
> +EspiPollScreAndCheckScrs (
> + VOID
> + )
> +{
> + UINT32 ScrStat;
> +
> + do {
> + ScrStat = PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SLV_CFG_REG_CTL);
> + } while ((ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE) != 0);
> +
> + ScrStat = (ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS) >>
> N_ESPI_PCR_SLV_CFG_REG_CTL_SCRS;
> + if (ScrStat != V_ESPI_PCR_SLV_CFG_REG_CTL_SCRS_NOERR) {
> + DEBUG ((DEBUG_ERROR, "eSPI slave config register status (error) is %x \n",
> ScrStat));
> + return EFI_DEVICE_ERROR;
> + }
> + return EFI_SUCCESS;
> +}
> +
> +typedef enum {
> + EspiSlaveOperationConfigRead,
> + EspiSlaveOperationConfigWrite,
> + EspiSlaveOperationStatusRead,
> + EspiSlaveOperationInBandReset
> +} ESPI_SLAVE_OPERATION;
> +
> +/**
> + Helper library to do all the operations regards to eSPI slave
> +
> + @param[in] SlaveId eSPI Slave ID
> + @param[in] SlaveAddress Slave address to be put in
> R_ESPI_PCR_SLV_CFG_REG_CTL[11:0]
> + @param[in] SlaveOperation Based on ESPI_SLAVE_OPERATION
> + @param[in,out] Data
> +
> + @retval EFI_SUCCESS Operation succeed
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is
> used in PCH_LP
> + @retval EFI_INVALID_PARAMETER Slave configuration register address
> exceed maximum allowed
> + @retval EFI_INVALID_PARAMETER Slave configuration register address is
> not DWord aligned
> + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF
> has been locked
> + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of
> operation
> +**/
> +STATIC
> +EFI_STATUS
> +EspiSlaveOperationHelper (
> + IN UINT32 SlaveId,
> + IN UINT32 SlaveAddress,
> + IN ESPI_SLAVE_OPERATION SlaveOperation,
> + IN OUT UINT32 *Data
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 Data32;
> +
> + //
> + // Check the SlaveId is 0 or 1
> + //
> + if (SlaveId >= PCH_MAX_ESPI_SLAVES) {
> + DEBUG ((DEBUG_ERROR, "eSPI Slave ID of %d or more is not accepted \n",
> PCH_MAX_ESPI_SLAVES));
> + return EFI_INVALID_PARAMETER;
> + }
> + //
> + // Check if SlaveId 1 is used, it is a PCH_H
> + //
> + if ((SlaveId == 1) && (IsPchLp ())) {
> + DEBUG ((DEBUG_ERROR, "eSPI Slave ID of 1 is only available on PCH_H
> \n"));
> + return EFI_INVALID_PARAMETER;
> + }
> + //
> + // Check the address is not more then 0xFFF
> + //
> + if (SlaveAddress > B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA) {
> + DEBUG ((DEBUG_ERROR, "eSPI Slave address must be less than 0x%x \n",
> (B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA + 1)));
> + return EFI_INVALID_PARAMETER;
> + }
> + //
> + // Check the address is DWord aligned
> + //
> + if ((SlaveAddress & 0x3) != 0) {
> + DEBUG ((DEBUG_ERROR, "eSPI Slave address must be DWord aligned \n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Check if write is allowed
> + //
> + if ((SlaveOperation == EspiSlaveOperationConfigWrite) &&
> + (SlaveAddress <= 0x7FF)) {
> +
> + //
> + // If the SLCRR is not set in corresponding slave, we will check the lock bit
> + //
> + Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) (R_ESPI_PCR_LNKERR_SLV0
> + (SlaveId * S_ESPI_PCR_LNKERR_SLV0)));
> + if ((Data32 & B_ESPI_PCR_LNKERR_SLV0_SLCRR) == 0) {
> +
> + Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16)
> R_ESPI_PCR_SLV_CFG_REG_CTL);
> + if ((Data32 & B_ESPI_PCR_SLV_CFG_REG_CTL_SBLCL) != 0) {
> + DEBUG ((DEBUG_ERROR, "eSPI Slave write to address range 0 to 0x7FF
> has been locked \n"));
> + return EFI_ACCESS_DENIED;
> + }
> + }
> + }
> +
> + //
> + // Input check done, now go through all the processes
> + //
> + EspiClearScrs ();
> +
> + if (SlaveOperation == EspiSlaveOperationConfigWrite) {
> + PchPcrWrite32 (
> + PID_ESPISPI,
> + (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA,
> + *Data
> + );
> + }
> +
> + PchPcrAndThenOr32 (
> + PID_ESPISPI,
> + (UINT16) R_ESPI_PCR_SLV_CFG_REG_CTL,
> + (UINT32) ~(B_ESPI_PCR_SLV_CFG_REG_CTL_SID |
> B_ESPI_PCR_SLV_CFG_REG_CTL_SCRT |
> B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA),
> + (B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE |
> + (SlaveId << N_ESPI_PCR_SLV_CFG_REG_CTL_SID) |
> + (((UINT32) SlaveOperation) << N_ESPI_PCR_SLV_CFG_REG_CTL_SCRT) |
> + SlaveAddress
> + )
> + );
> +
> + Status = EspiPollScreAndCheckScrs ();
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if ((SlaveOperation == EspiSlaveOperationConfigRead) || (SlaveOperation
> == EspiSlaveOperationStatusRead)) {
> + Data32 = PchPcrRead32 (
> + PID_ESPISPI,
> + (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA
> + );
> + if (SlaveOperation == EspiSlaveOperationStatusRead) {
> + *Data = Data32 & 0xFFFF;
> + } else {
> + *Data = Data32;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get configuration from eSPI slave
> +
> + @param[in] SlaveId eSPI slave ID
> + @param[in] SlaveAddress Slave Configuration Register Address
> + @param[out] OutData Configuration data read
> +
> + @retval EFI_SUCCESS Operation succeed
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is
> used in PCH_LP
> + @retval EFI_INVALID_PARAMETER Slave configuration register address
> exceed maximum allowed
> + @retval EFI_INVALID_PARAMETER Slave configuration register address is
> not DWord aligned
> + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of
> operation
> +**/
> +EFI_STATUS
> +PchEspiSlaveGetConfig (
> + IN UINT32 SlaveId,
> + IN UINT32 SlaveAddress,
> + OUT UINT32 *OutData
> + )
> +{
> + //
> + // 1. Clear status from previous transaction by writing 111b to status in SCRS,
> PCR[eSPI] + 4000h [30:28]
> + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit
> [20:19]=<SlvID>, Bit [17:16] = 00b, Bit[11:0] = <addr_xxx>.
> + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
> + // 4. Check the transaction status in SCRS (bits [30:28])
> + // 5. Read SLV_CFG_REG_DATA.
> + //
> + return EspiSlaveOperationHelper (SlaveId, SlaveAddress,
> EspiSlaveOperationConfigRead, OutData);
> +}
> +
> +/**
> + Set eSPI slave configuration
> +
> + Note: A Set_Configuration must always be followed by a Get_Configuration
> in order to ensure
> + that the internal state of the eSPI-MC is consistent with the Slave's register
> settings.
> +
> + @param[in] SlaveId eSPI slave ID
> + @param[in] SlaveAddress Slave Configuration Register Address
> + @param[in] InData Configuration data to write
> +
> + @retval EFI_SUCCESS Operation succeed
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is
> used in PCH_LP
> + @retval EFI_INVALID_PARAMETER Slave configuration register address
> exceed maximum allowed
> + @retval EFI_INVALID_PARAMETER Slave configuration register address is
> not DWord aligned
> + @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF
> has been locked
> + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of
> operation
> +**/
> +EFI_STATUS
> +PchEspiSlaveSetConfig (
> + IN UINT32 SlaveId,
> + IN UINT32 SlaveAddress,
> + IN UINT32 InData
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 Data32;
> +
> + //
> + // 1. Clear status from previous transaction by writing 111b to status in SCRS,
> PCR[eSPI] + 4000h [30:28]
> + // 2. Program SLV_CFG_REG_DATA with the write value.
> + // 3. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit
> [20:19]=<SlvID>, Bit [17:16] = 01b, Bit[11:0] = <addr_xxx>.
> + // 4. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
> + // 5. Check the transaction status in SCRS (bits [30:28])
> + //
> + Status = EspiSlaveOperationHelper (SlaveId, SlaveAddress,
> EspiSlaveOperationConfigWrite, &InData);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveAddress, &Data32);
> + return Status;
> +}
> +
> +/**
> + Get status from eSPI slave
> +
> + @param[in] SlaveId eSPI slave ID
> + @param[out] OutData Configuration data read
> +
> + @retval EFI_SUCCESS Operation succeed
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is
> used in PCH_LP
> + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of
> operation
> +**/
> +EFI_STATUS
> +PchEspiSlaveGetStatus (
> + IN UINT32 SlaveId,
> + OUT UINT16 *OutData
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 TempOutData;
> +
> + TempOutData = 0;
> +
> + //
> + // 1. Clear status from previous transaction by writing 111b to status in SCRS,
> PCR[eSPI] + 4000h [30:28]
> + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit
> [20:19]=<SlvID>, Bit [17:16] = 10b, Bit[11:0] = <addr_xxx>.
> + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
> + // 4. Check the transaction status in SCRS (bits [30:28])
> + // 5. Read SLV_CFG_REG_DATA [15:0].
> + //
> + Status = EspiSlaveOperationHelper (SlaveId, 0,
> EspiSlaveOperationStatusRead, &TempOutData);
> + *OutData = (UINT16) TempOutData;
> +
> + return Status;
> +}
> +
> +/**
> + eSPI slave in-band reset
> +
> + @param[in] SlaveId eSPI slave ID
> +
> + @retval EFI_SUCCESS Operation succeed
> + @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is
> used in PCH_LP
> + @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of
> operation
> +**/
> +EFI_STATUS
> +PchEspiSlaveInBandReset (
> + IN UINT32 SlaveId
> + )
> +{
> + //
> + // 1. Clear status from previous transaction by writing 111b to status in SCRS,
> PCR[eSPI] + 4000h [30:28]
> + // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit
> [20:19]=<SlvID>, Bit [17:16] = 11b).
> + // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
> + // 4. Check the transaction status in SCRS (bits [30:28])
> + //
> + return EspiSlaveOperationHelper (SlaveId, 0,
> EspiSlaveOperationInBandReset, NULL);
> +}
> +
> +/**
> + eSPI Slave channel reset helper function
> +
> + @param[in] SlaveId eSPI slave ID
> + @param[in] ChannelNumber Number of channel to reset
> +
> + @retval EFI_SUCCESS Operation succeeded
> + @retval EFI_UNSUPPORTED Slave doesn't support that channel or
> invalid number specified
> + @retval EFI_TIMEOUT Operation has timeouted
> +**/
> +EFI_STATUS
> +PchEspiSlaveChannelReset (
> + IN UINT8 SlaveId,
> + IN UINT8 ChannelNumber
> + )
> +{
> + UINT8 Timeout;
> + UINT32 Data32;
> + UINT32 SlaveChannelAddress;
> + BOOLEAN SlaveBmeSet;
> + EFI_STATUS Status;
> +
> + DEBUG ((DEBUG_INFO, "eSPI slave %d channel %d reset\n", SlaveId,
> ChannelNumber));
> +
> + Timeout = CHANNEL_RESET_TIMEOUT;
> + SlaveBmeSet = FALSE;
> +
> + if (!IsEspiSlaveChannelSupported (SlaveId, ChannelNumber)) {
> + // Incorrect channel number was specified. Either exceeded max or Slave
> doesn't support that channel.
> + DEBUG ((DEBUG_ERROR, "Channel %d is not valid channel number for
> slave %d!\n", ChannelNumber, SlaveId));
> + return EFI_UNSUPPORTED;
> + }
> +
> + // Calculating slave channel address
> + SlaveChannelAddress = R_ESPI_SLAVE_CHACAP_BASE +
> (S_ESPI_SLAVE_CHACAP_OFFSET * ChannelNumber);
> +
> + // If we're resetting Peripheral Channel then we need to disable Bus
> Mastering first and reenable after reset
> + if (ChannelNumber == 0) {
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + if ((Data32 & B_ESPI_SLAVE_BME) != 0) {
> + Data32 &= ~(B_ESPI_SLAVE_BME);
> + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + SlaveBmeSet = TRUE;
> + }
> + }
> +
> + // Disable channel
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Data32 &= ~(B_ESPI_SLAVE_CHACAP_CHEN);
> + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + // Enable channel
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Data32 |= B_ESPI_SLAVE_CHACAP_CHEN;
> + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + DEBUG ((DEBUG_INFO, "Waiting for Channel Ready bit\n"));
> + // Wait until channel is ready by polling Channel Ready bit
> + while (((Data32 & B_ESPI_SLAVE_CHACAP_CHRDY) == 0) && (Timeout > 0)) {
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + MicroSecondDelay (1);
> + --Timeout;
> + }
> +
> + if (Timeout == 0) {
> + // The waiting for channel to be ready has timed out
> + DEBUG ((DEBUG_ERROR, "The operation of channel %d reset for slave %d
> has timed out!\n", ChannelNumber, SlaveId));
> + return EFI_TIMEOUT;
> + }
> +
> + if (ChannelNumber == 0 && SlaveBmeSet) {
> + Status = PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Data32 |= B_ESPI_SLAVE_BME;
> + Status = PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchG
> beLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchG
> beLib.c
> new file mode 100644
> index 0000000000..652a47ebaf
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchG
> beLib.c
> @@ -0,0 +1,82 @@
> +/** @file
> + PCH Gbe Library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsSpi.h>
> +
> +/**
> + Check whether GbE region is valid
> + Check SPI region directly since GbE might be disabled in SW.
> +
> + @retval TRUE Gbe Region is valid
> + @retval FALSE Gbe Region is invalid
> +**/
> +BOOLEAN
> +PchIsGbeRegionValid (
> + VOID
> + )
> +{
> + UINT32 SpiBar;
> + SpiBar = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + R_SPI_CFG_BAR0)) & ~B_SPI_CFG_BAR0_MASK;
> + ASSERT (SpiBar != 0);
> + if (MmioRead32 (SpiBar + R_SPI_MEM_FREG3_GBE) !=
> B_SPI_MEM_FREGX_BASE_MASK) {
> + return TRUE;
> + }
> + return FALSE;
> +}
> +
> +
> +/**
> + Check whether LAN controller is enabled in the platform.
> +
> + @retval TRUE GbE is enabled
> + @retval FALSE GbE is disabled
> +**/
> +BOOLEAN
> +PchIsGbePresent (
> + VOID
> + )
> +{
> + //
> + // Check PCH Support
> + //
> + if (!PchIsGbeSupported ()) {
> + return FALSE;
> + }
> + //
> + // Check PMC strap/fuse
> + //
> + if (!PmcIsGbeSupported ()) {
> + return FALSE;
> + }
> + //
> + // Check GbE NVM
> + //
> + if (PchIsGbeRegionValid () == FALSE) {
> + return FALSE;
> + }
> + return TRUE;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/Pch
> HsioLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/Pch
> HsioLib.c
> new file mode 100644
> index 0000000000..2be8e8ed49
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/Pch
> HsioLib.c
> @@ -0,0 +1,127 @@
> +/** @file
> + PCH HSIO Library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <PchAccess.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchHsioLib.h>
> +
> +/**
> + The function returns the Port Id and lane owner for the specified lane
> +
> + @param[in] PhyMode Phymode that needs to be checked
> + @param[out] PortId Common Lane End Point ID
> + @param[out] LaneOwner Lane Owner
> +
> + @retval EFI_SUCCESS Read success
> + @retval EFI_INVALID_PARAMETER Invalid lane number
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchGetLaneInfo (
> + IN UINT32 LaneNum,
> + OUT UINT8 *PortId,
> + OUT UINT8 *LaneOwner
> + )
> +{
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Determine the lane number of a specified port
> +
> + @param[out] LaneNum GBE Lane Number
> +
> + @retval EFI_SUCCESS Lane number valid.
> + @retval EFI_UNSUPPORTED Incorrect input device port
> +**/
> +EFI_STATUS
> +PchGetGbeLaneNum (
> + UINT8 *LaneNum
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Determine the lane number of a specified port
> +
> + @param[in] Usb3LaneIndex USB3 Lane Index
> + @param[out] LaneNum Lane Number
> +
> + @retval EFI_SUCCESS Lane number valid.
> + @retval EFI_UNSUPPORTED Incorrect input device port
> +**/
> +EFI_STATUS
> +PchGetUsb3LaneNum (
> + UINT32 Usb3LaneIndex,
> + UINT8 *LaneNum
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Determine the lane number of a specified port
> +
> + @param[in] SataLaneIndex Sata Lane Index
> + @param[out] LaneNum Lane Number
> +
> + @retval EFI_SUCCESS Lane number valid.
> + @retval EFI_UNSUPPORTED Incorrect input device port
> +**/
> +EFI_STATUS
> +PchGetSataLaneNum (
> + UINT32 SataLaneIndex,
> + UINT8 *LaneNum
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Determine the lane number of a specified port
> +
> + @param[in] PcieLaneIndex PCIE Root Port Lane Index
> + @param[out] LaneNum Lane Number
> +
> + @retval EFI_SUCCESS Lane number valid.
> + @retval EFI_UNSUPPORTED Incorrect input device port
> +**/
> +EFI_STATUS
> +PchGetPcieLaneNum (
> + UINT32 PcieLaneIndex,
> + UINT8 *LaneNum
> + )
> +{
> +
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Get HSIO lane representation needed to perform any operation on the lane.
> +
> + @param[in] LaneIndex Number of the HSIO lane
> + @param[out] HsioLane HSIO lane representation
> +**/
> +VOID
> +HsioGetLane (
> + IN UINT8 LaneIndex,
> + OUT HSIO_LANE *HsioLane
> + )
> +{
> +
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchIn
> foLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLib.c
> new file mode 100644
> index 0000000000..7c3ade49b6
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLib.c
> @@ -0,0 +1,272 @@
> +/** @file
> + Pch information library.
> +
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/PcdLib.h>
> +#include "PchInfoLibPrivate.h"
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsPcie.h>
> +#include <IndustryStandard/Pci30.h>
> +
> +/**
> + Return LPC Device Id
> +
> + @retval PCH_LPC_DEVICE_ID PCH Lpc Device ID
> +**/
> +UINT16
> +PchGetLpcDid (
> + VOID
> + )
> +{
> + UINT64 LpcBaseAddress;
> +
> + LpcBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_LPC,
> + PCI_FUNCTION_NUMBER_PCH_LPC,
> + 0
> + );
> +
> + return PciSegmentRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
> +}
> +
> +/**
> + Return Pch Series
> +
> + @retval PCH_SERIES Pch Series
> +**/
> +PCH_SERIES
> +PchSeries (
> + VOID
> + )
> +{
> + PCH_SERIES PchSer;
> + static PCH_SERIES PchSeries = PCH_UNKNOWN_SERIES;
> +
> + if (PchSeries != PCH_UNKNOWN_SERIES) {
> + return PchSeries;
> + }
> +
> + PchSer = PchSeriesFromLpcDid (PchGetLpcDid ());
> +
> + PchSeries = PchSer;
> +
> + return PchSer;
> +}
> +
> +/**
> + Return Pch stepping type
> +
> + @retval PCH_STEPPING Pch stepping type
> +**/
> +PCH_STEPPING
> +PchStepping (
> + VOID
> + )
> +{
> + UINT8 RevId;
> + UINT64 LpcBaseAddress;
> + static PCH_STEPPING PchStepping = PCH_STEPPING_MAX;
> +
> + if (PchStepping != PCH_STEPPING_MAX) {
> + return PchStepping;
> + }
> +
> + LpcBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_LPC,
> + PCI_FUNCTION_NUMBER_PCH_LPC,
> + 0
> + );
> + RevId = PciSegmentRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
> +
> + PchStepping = RevId;
> +
> + return RevId;
> +}
> +
> +/**
> + Determine if PCH is supported
> +
> + @retval TRUE PCH is supported
> + @retval FALSE PCH is not supported
> +**/
> +BOOLEAN
> +IsPchSupported (
> + VOID
> + )
> +{
> + UINT16 LpcDeviceId;
> + UINT16 LpcVendorId;
> + UINT64 LpcBaseAddress;
> +
> + LpcBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_LPC,
> + PCI_FUNCTION_NUMBER_PCH_LPC,
> + 0
> + );
> +
> + LpcDeviceId = PciSegmentRead16 (LpcBaseAddress +
> PCI_DEVICE_ID_OFFSET);
> + LpcVendorId = PciSegmentRead16 (LpcBaseAddress +
> PCI_VENDOR_ID_OFFSET);
> +
> + ///
> + /// Verify that this is a supported chipset
> + ///
> + if ((LpcVendorId == V_LPC_CFG_VENDOR_ID) && (PchSeries () !=
> PCH_UNKNOWN_SERIES)) {
> + return TRUE;
> + } else {
> + DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId:
> 0x%04x!\n", LpcDeviceId));
> + return FALSE;
> + }
> +}
> +
> +/**
> + Check if this is PCH LP series
> +
> + @retval TRUE It's PCH LP series
> + @retval FALSE It's not PCH LP series
> +**/
> +BOOLEAN
> +IsPchLp (
> + VOID
> + )
> +{
> + return (PchSeries () == PCH_LP);
> +}
> +
> +/**
> + Check if this is PCH H series
> +
> + @retval TRUE It's PCH H series
> + @retval FALSE It's not PCH H series
> +**/
> +BOOLEAN
> +IsPchH (
> + VOID
> + )
> +{
> + return (PchSeries () == PCH_H);
> +}
> +
> +/**
> + Check if this is CDF PCH generation
> +
> + @retval TRUE It's CDF PCH
> + @retval FALSE It's not CDF PCH
> +**/
> +BOOLEAN
> +IsCdfPch (
> + VOID
> + )
> +{
> + return (PchGeneration () == CDF_PCH);
> +}
> +
> +/**
> + Check if this is PCH generation
> +
> + @retval TRUE It's CNL PCH
> + @retval FALSE It's not CNL PCH
> +**/
> +BOOLEAN
> +IsCnlPch (
> + VOID
> + )
> +{
> + return (PchGeneration () == CNL_PCH);
> +}
> +
> +/**
> + Get PCH stepping ASCII string.
> + Function determines major and minor stepping versions and writes them
> into a buffer.
> + The return string is zero terminated
> +
> + @param [out] Buffer Output buffer of string
> + @param [in] BufferSize Buffer size.
> + Must not be less then
> PCH_STEPPING_STR_LENGTH_MAX
> +
> + @retval EFI_SUCCESS String copied successfully
> + @retval EFI_INVALID_PARAMETER The stepping is not supported, or
> parameters are NULL
> + @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
> +**/
> +EFI_STATUS
> +PchGetSteppingStr (
> + OUT CHAR8 *Buffer,
> + IN UINT32 BufferSize
> + )
> +{
> + PCH_STEPPING PchStep;
> +
> + PchStep = PchStepping ();
> +
> + if ((Buffer == NULL) || (BufferSize == 0)) {
> + return EFI_INVALID_PARAMETER;
> + }
> + if (BufferSize < PCH_STEPPING_STR_LENGTH_MAX) {
> + return EFI_BUFFER_TOO_SMALL;
> + }
> +
> + AsciiSPrint (Buffer, BufferSize, "%c%c", 'A' + (PchStep >> 4), '0' + (PchStep &
> 0xF));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get PCH Sku ASCII string
> + The return string is zero terminated.
> +
> + @retval Static ASCII string of PCH Sku
> +**/
> +CHAR8*
> +PchGetSkuStr (
> + VOID
> + )
> +{
> + UINTN Index;
> + UINT16 LpcDid;
> +
> + LpcDid = PchGetLpcDid ();
> +
> + for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) {
> + if (LpcDid == mSkuStrs[Index].Id) {
> + return mSkuStrs[Index].String;
> + }
> + }
> +
> + return "Undefined SKU";
> +}
> +
> +/**
> + Get Pch Maximum Pcie Controller Number
> +
> + @retval Pch Maximum Pcie Root Port Number
> +**/
> +UINT8
> +GetPchMaxPcieControllerNum (
> + VOID
> + )
> +{
> + return GetPchMaxPciePortNum () / PCH_PCIE_CONTROLLER_PORTS;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchIn
> foLibClient.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibClient.c
> new file mode 100644
> index 0000000000..7b09a2dbb9
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibClient.c
> @@ -0,0 +1,87 @@
> +/** @file
> + Common Pch information library for Client PCH silicon.
> +
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PchInfoLib.h>
> +
> +/**
> + Get Pch Maximum Pcie Clock Number
> +
> + @retval Pch Maximum Pcie Clock Number
> +**/
> +UINT8
> +GetPchMaxPcieClockNum (
> + VOID
> + )
> +{
> + if (IsPchH ()) {
> + return 16;
> + } else {
> + return 6;
> + }
> +}
> +
> +/**
> + Get Pch Maximum Serial IO controllers number
> +
> + @retval Pch Maximum Serial IO controllers number
> +**/
> +UINT8
> +GetPchMaxSerialIoControllersNum (
> + VOID
> + )
> +{
> + return 12;
> +}
> +
> +/**
> + Get Pch Maximum Serial IO I2C controllers number
> +
> + @retval Pch Maximum Serial IO I2C controllers number
> +**/
> +UINT8
> +GetPchMaxSerialIoI2cControllersNum (
> + VOID
> + )
> +{
> + if (IsPchH ()) {
> + return 4;
> + } else {
> + return 6;
> + }
> +}
> +
> +/**
> + Get Pch Maximum Serial IO SPI controllers number
> +
> + @retval Pch Maximum Serial IO SPI controllers number
> +**/
> +UINT8
> +GetPchMaxSerialIoSpiControllersNum (
> + VOID
> + )
> +{
> + return 3;
> +}
> +
> +/**
> + Get Pch Maximum Serial IO UART controllers number
> +
> + @retval Pch Maximum Serial IO UART controllers number
> +**/
> +UINT8
> +GetPchMaxSerialIoUartControllersNum (
> + VOID
> + )
> +{
> + return 3;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchIn
> foLibCnl.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibCnl.c
> new file mode 100644
> index 0000000000..431b1470c2
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchI
> nfoLibCnl.c
> @@ -0,0 +1,386 @@
> +/** @file
> + Pch information library.
> +
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Register/PchRegsLpcCnl.h>
> +#include "PchInfoLibPrivate.h"
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Register/PchRegsLpc.h>
> +
> +/**
> + Determine Pch Series based on Device Id
> +
> + @param[in] LpcDeviceId Lpc Device Id
> +
> + @retval PCH_SERIES Pch Series
> +**/
> +PCH_SERIES
> +PchSeriesFromLpcDid (
> + IN UINT16 LpcDeviceId
> + )
> +{
> + switch (LpcDeviceId & B_LPC_CFG_DID) {
> +
> + case V_LPC_CFG_DID_CNL_H:
> + return PCH_H;
> +
> + case V_LPC_CFG_DID_CNL_LP:
> + return PCH_LP;
> +
> + default:
> + return PCH_UNKNOWN_SERIES;
> + }
> +}
> +
> +/**
> + Return Pch Generation
> +
> + @retval PCH_GENERATION Pch Generation
> +**/
> +PCH_GENERATION
> +PchGeneration (
> + VOID
> + )
> +{
> + return CNL_PCH;
> +}
> +
> +/**
> + Check if this is Server PCH
> +
> + @retval TRUE It's a Server PCH
> + @retval FALSE It's not a Server PCH
> +**/
> +BOOLEAN
> +IsPchServer (
> + VOID
> + )
> +{
> + return FALSE;
> +}
> +
> +/**
> + Get RST mode supported by the silicon
> +
> + @retval RST_MODE RST mode supported by silicon
> +**/
> +RST_MODE
> +PchGetSupportedRstMode (
> + VOID
> + )
> +{
> + switch (PchGetLpcDid ()) {
> +
> + case V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_4:
> + case V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A303_SKU:
> + return RstUnsupported;
> + break;
> +
> + default:
> + return RstPremium;
> + break;
> + }
> +}
> +
> +/**
> + Check if this is Server SKU
> +
> + @retval TRUE It's PCH Server SKU
> + @retval FALSE It's not PCH Server SKU
> +**/
> +BOOLEAN
> +IsPchServerSku (
> + VOID
> + )
> +{
> + UINT16 LpcDid;
> +
> + LpcDid = PchGetLpcDid ();
> +
> + if (LpcDid == V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A309_SKU) {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> +}
> +
> +/**
> + Get PCH series ASCII string.
> +
> + @retval PCH Series string
> +**/
> +CHAR8*
> +PchGetSeriesStr (
> + VOID
> + )
> +{
> + switch (PchSeries ()) {
> +
> + case PCH_LP:
> + return "CNL PCH-LP";
> +
> + case PCH_H:
> + return "CNL PCH-H";
> +
> + default:
> + return NULL;
> + }
> +}
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +struct PCH_SKU_STRING mSkuStrs[] = {
> + //
> + // PCH LP Mobile LPC Device IDs
> + //
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_0, "(U) Super SKU"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_1, "Super SKU (locked)"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_2, "(Y) Premium SKU"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_3, "(U) Premium SKU"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_4, "(U) Base/Mainstream SKU"},
> + {V_CNL_PCH_LP_LPC_CFG_DEVICE_ID_MB_5, "(Y) Super SKU"},
> + //
> + // PCH H LPC Device IDs
> + //
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A300_SKU, "CNL PCH-H SKU A300"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A303_SKU, "H310"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A304_SKU, "H370"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A305_SKU, "Z390"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A306_SKU, "Q370"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A309_SKU, "C246"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30A_SKU, "C242"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30B_SKU, "X399"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30C_SKU, "QM370"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30D_SKU, "HM370"},
> + {V_CNL_PCH_H_LPC_CFG_DEVICE_ID_A30E_SKU, "CM246"},
> + {0xFFFF, NULL}
> +};
> +
> +/**
> + Check whether integrated LAN controller is supported by PCH Series.
> +
> + @retval TRUE GbE is supported in current PCH
> + @retval FALSE GbE is not supported on current PCH
> +**/
> +BOOLEAN
> +PchIsGbeSupported (
> + VOID
> + )
> +{
> + return TRUE;
> +}
> +
> +/**
> + Get Pch Maximum Pcie Root Port Number
> +
> + @retval Pch Maximum Pcie Root Port Number
> +**/
> +UINT8
> +GetPchMaxPciePortNum (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return 16;
> + } else {
> + return 24;
> + }
> +}
> +
> +/**
> + Get Pch Usb2 Maximum Physical Port Number
> +
> + @retval Pch Usb2 Maximum Physical Port Number
> +**/
> +UINT8
> +GetPchUsb2MaxPhysicalPortNum (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return 10;
> + } else {
> + return 14;
> + }
> +}
> +
> +/**
> + Get Pch Maximum Usb2 Port Number of XHCI Controller
> +
> + @retval Pch Maximum Usb2 Port Number of XHCI Controller
> +**/
> +UINT8
> +GetPchXhciMaxUsb2PortNum (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return 12;
> + } else {
> + return 16;
> + }
> +}
> +
> +/**
> + Get Pch Maximum Usb3 Port Number of XHCI Controller
> +
> + @retval Pch Maximum Usb3 Port Number of XHCI Controller
> +**/
> +UINT8
> +GetPchXhciMaxUsb3PortNum (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return 6;
> + } else {
> + return 10;
> + }
> +}
> +
> +/**
> + Check if given Display Audio Link T-Mode is supported
> +
> + @param[in] Tmode T-mode support to be checked
> +
> + @retval TRUE T-mode supported
> + @retval FALSE T-mode not supported
> +**/
> +BOOLEAN
> +IsAudioIDispTmodeSupported (
> + IN PCH_HDAUDIO_IDISP_TMODE Tmode
> + )
> +{
> + //
> + // iDisplay Audio Link T-mode support per PCH Generation/Series:
> + // 1. 1T - CNP-LP
> + // 2. 2T - CNP-LP/H (default)
> + //
> + switch (Tmode) {
> + case PchHdaIDispMode1T:
> + return IsPchLp ();
> + case PchHdaIDispMode2T:
> + return TRUE;
> + case PchHdaIDispMode4T:
> + case PchHdaIDispMode8T:
> + case PchHdaIDispMode16T:
> + default:
> + return FALSE;
> + }
> +}
> +
> +/**
> + Gets the maximum number of UFS controller supported by this chipset.
> +
> + @return Number of supported UFS controllers
> +**/
> +UINT8
> +PchGetMaxUfsNum (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return 1;
> + } else {
> + return 0;
> + }
> +}
> +
> +/**
> + Check if this chipset supports eMMC controller
> +
> + @retval BOOLEAN TRUE if supported, FALSE otherwise
> +**/
> +BOOLEAN
> +IsPchEmmcSupported (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Check if this chipset supports SD controller
> +
> + @retval BOOLEAN TRUE if supported, FALSE otherwise
> +**/
> +BOOLEAN
> +IsPchSdCardSupported (
> + VOID
> + )
> +{
> + return TRUE;
> +}
> +
> +/**
> + Check if this chipset supports UFS controller
> +
> + @retval BOOLEAN TRUE if supported, FALSE otherwise
> +**/
> +BOOLEAN
> +IsPchUfsSupported (
> + VOID
> + )
> +{
> + if (IsPchLp ()) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Check if link between PCH and CPU is an P-DMI
> +
> + @retval TRUE P-DMI link
> + @retval FALSE Not an P-DMI link
> +**/
> +BOOLEAN
> +IsPchWithPdmi (
> + VOID
> + )
> +{
> + return IsPchH ();
> +}
> +
> +/**
> + Check if link between PCH and CPU is an OP-DMI
> +
> + @retval TRUE OP-DMI link
> + @retval FALSE Not an OP-DMI link
> +**/
> +BOOLEAN
> +IsPchWithOpdmi (
> + VOID
> + )
> +{
> + return !IsPchH ();
> +}
> +
> +/**
> + Check if link between PCH and CPU is an F-DMI
> +
> + @retval TRUE F-DMI link
> + @retval FALSE Not an F-DMI link
> +**/
> +BOOLEAN
> +IsPchWithFdmi (
> + VOID
> + )
> +{
> + return FALSE;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pc
> hPcieRpLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pc
> hPcieRpLib.c
> new file mode 100644
> index 0000000000..9997c3612b
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/Pc
> hPcieRpLib.c
> @@ -0,0 +1,183 @@
> +/** @file
> + PCH PCIE root port library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchPcieRpLib.h>
> +#include <PcieRegs.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsPcie.h>
> +#include <Register/PchRegsPcr.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_PCIE_CONTROLLER_INFO
> mPchPcieControllerInfo[] = {
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPA, 0 },
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPB, 4 },
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPC, 8 },
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPD, 12 },
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPE, 16 }, // PCH-H only
> + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPF, 20 } // PCH-H only
> +};
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32
> mPchPcieControllerInfoSize = sizeof (mPchPcieControllerInfo) / sizeof
> (mPchPcieControllerInfo[0]);
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8
> mPchLpRstPcieStorageSupportedPort[] = {
> + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID,
> RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, //
> RP1..RP4
> + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1,
> RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP5..RP8
> + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2,
> RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP9..RP12
> + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3,
> RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 //
> RP13..RP16
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8
> mPchHRstPcieStorageSupportedPort[] = {
> + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID,
> RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, //
> RP1..RP4
> + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID,
> RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, //
> RP5..RP8
> + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1,
> RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12
> + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID,
> RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, //
> RP13..RP16
> + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3,
> RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, //
> RP17..RP20
> + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2,
> RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2 //
> RP21..RP24
> +};
> +
> +/**
> + Get Pch Pcie Root Port Device and Function Number by Root Port physical
> Number
> +
> + @param[in] RpNumber Root port physical number. (0-based)
> + @param[out] RpDev Return corresponding root port device
> number.
> + @param[out] RpFun Return corresponding root port function
> number.
> +
> + @retval EFI_SUCCESS Root port device and function is retrieved
> + @retval EFI_INVALID_PARAMETER RpNumber is invalid
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetPchPcieRpDevFun (
> + IN UINTN RpNumber,
> + OUT UINTN *RpDev,
> + OUT UINTN *RpFun
> + )
> +{
> + UINTN Index;
> + UINTN FuncIndex;
> + UINT32 PciePcd;
> +
> + if (RpNumber >= GetPchMaxPciePortNum ()) {
> + DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x",
> RpNumber));
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS;
> + FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase;
> + *RpDev = mPchPcieControllerInfo[Index].DevNum;
> + PciePcd = PchPcrRead32 (mPchPcieControllerInfo[Index].Pid,
> R_SPX_PCR_PCD);
> + *RpFun = (PciePcd >> (FuncIndex * S_SPX_PCR_PCD_RP_FIELD)) &
> B_SPX_PCR_PCD_RP1FN;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get Root Port physical Number by Pch Pcie Root Port Device and Function
> Number
> +
> + @param[in] RpDev Root port device number.
> + @param[in] RpFun Root port function number.
> + @param[out] RpNumber Return corresponding physical Root
> Port index (0-based)
> +
> + @retval EFI_SUCCESS Physical root port is retrieved
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetPchPcieRpNumber (
> + IN UINTN RpDev,
> + IN UINTN RpFun,
> + OUT UINTN *RpNumber
> + )
> +{
> + UINT64 RpBase;
> +
> + RpBase = PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH,
> RpDev, RpFun, 0);
> + *RpNumber = (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) >>
> N_PCH_PCIE_CFG_LCAP_PN) -1;
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Gets pci segment base address of PCIe root port.
> +
> + @param RpIndex Root Port Index (0 based)
> + @return PCIe port base address.
> +**/
> +UINT64
> +PchPcieBase (
> + IN UINT32 RpIndex
> + )
> +{
> + UINTN RpDevice;
> + UINTN RpFunction;
> +
> + GetPchPcieRpDevFun (RpIndex, &RpDevice, &RpFunction);
> +
> + return PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH,
> (UINT32) RpDevice, (UINT32) RpFunction, 0);
> +}
> +
> +/**
> + Determines whether L0s is supported on current stepping.
> +
> + @return TRUE if L0s is supported, FALSE otherwise
> +**/
> +BOOLEAN
> +PchIsPcieL0sSupported (
> + VOID
> + )
> +{
> + return TRUE;
> +}
> +
> +/**
> + Some early PCH steppings require Native ASPM to be disabled due to
> hardware issues:
> + - RxL0s exit causes recovery
> + - Disabling PCIe L0s capability disables L1
> + Use this function to determine affected steppings.
> +
> + @return TRUE if Native ASPM is supported, FALSE otherwise
> +**/
> +BOOLEAN
> +PchIsPcieNativeAspmSupported (
> + VOID
> + )
> +{
> + return PchIsPcieL0sSupported ();
> +}
> +
> +/**
> + Check the RST PCIe Storage Cycle Router number according to the root port
> number and PCH type
> +
> + @param[in] RootPortNum Root Port Number
> +
> + @return The RST PCIe Storage Cycle Router Number
> +**/
> +UINT8
> +RstGetCycleRouterNumber (
> + IN UINT32 RootPortNum
> + )
> +{
> + if (IsPchLp ()) {
> + if (RootPortNum < ARRAY_SIZE (mPchLpRstPcieStorageSupportedPort)) {
> + return mPchLpRstPcieStorageSupportedPort[RootPortNum];
> + }
> + } else if (IsPchH ()) {
> + if (RootPortNum < ARRAY_SIZE (mPchHRstPcieStorageSupportedPort)) {
> + return mPchHRstPcieStorageSupportedPort[RootPortNum];
> + }
> + }
> + return RST_PCIE_STORAGE_CR_INVALID;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPc
> rLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPc
> rLib.c
> new file mode 100644
> index 0000000000..6f70733fe7
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPc
> rLib.c
> @@ -0,0 +1,279 @@
> +/** @file
> + PCH PCR library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Register/PchRegsPcr.h>
> +
> +#ifndef MDEPKG_NDEBUG
> +/**
> + Checks if the offset is valid for a given memory access width
> +
> + @param[in] Offset Offset of a register
> + @param[in] Size Size of memory access in bytes
> +
> + @retval FALSE Offset is not valid for a given memory access
> + @retval TRUE Offset is valid
> +**/
> +STATIC
> +BOOLEAN
> +PchIsPcrOffsetValid (
> + IN UINT32 Offset,
> + IN UINTN Size
> + )
> +{
> + if (((Offset & (Size - 1)) != 0) || (Offset > 0xFFFF)) {
> + DEBUG ((DEBUG_ERROR, "PCR offset error. Invalid Offset: %x Size: %x",
> Offset, Size));
> + return FALSE;
> + } else {
> + return TRUE;
> + }
> +}
> +#endif
> +
> +/**
> + Read PCR register.
> + It returns PCR register and size in 4bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of this Port ID
> +
> + @retval UINT32 PCR register value.
> +**/
> +UINT32
> +PchPcrRead32 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset
> + )
> +{
> +#ifndef MDEPKG_NDEBUG
> + ASSERT (PchIsPcrOffsetValid (Offset, 4));
> +#endif
> + return MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
> +}
> +
> +/**
> + Read PCR register.
> + It returns PCR register and size in 2bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of this Port ID
> +
> + @retval UINT16 PCR register value.
> +**/
> +UINT16
> +PchPcrRead16 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset
> + )
> +{
> +#ifndef MDEPKG_NDEBUG
> + ASSERT (PchIsPcrOffsetValid (Offset, 2));
> +#endif
> + return MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
> +}
> +
> +/**
> + Read PCR register.
> + It returns PCR register and size in 1bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of this Port ID
> +
> + @retval UINT8 PCR register value
> +**/
> +UINT8
> +PchPcrRead8 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset
> + )
> +{
> + return MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 4bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] Data Input Data. Must be the same size as Size parameter.
> +
> + @retval UINT32 Value written to register
> +**/
> +UINT32
> +PchPcrWrite32 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT32 Data
> + )
> +{
> +#ifndef MDEPKG_NDEBUG
> + ASSERT (PchIsPcrOffsetValid (Offset, 4));
> +#endif
> + MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), Data);
> +
> + return Data;
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 2bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] Data Input Data. Must be the same size as Size parameter.
> +
> + @retval UINT16 Value written to register
> +**/
> +UINT16
> +PchPcrWrite16 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT16 Data
> + )
> +{
> +#ifndef MDEPKG_NDEBUG
> + ASSERT (PchIsPcrOffsetValid (Offset, 2));
> +#endif
> + MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), Data);
> +
> + return Data;
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 1bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] Data Input Data. Must be the same size as Size parameter.
> +
> + @retval UINT8 Value written to register
> +**/
> +UINT8
> +PchPcrWrite8 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT8 Data
> + )
> +{
> + MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), Data);
> +
> + return Data;
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 4bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] AndData AND Data. Must be the same size as Size parameter.
> + @param[in] OrData OR Data. Must be the same size as Size parameter.
> +
> + @retval UINT32 Value written to register
> +
> +**/
> +UINT32
> +PchPcrAndThenOr32 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT32 AndData,
> + IN UINT32 OrData
> + )
> +{
> + return PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData) |
> OrData);
> +}
> +
> +/**
> + Write PCR register and read back.
> + The read back ensures the PCR cycle is completed before next operation.
> + It programs PCR register and size in 4bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] AndData AND Data. Must be the same size as Size parameter.
> + @param[in] OrData OR Data. Must be the same size as Size parameter.
> +
> + @retval UINT32 Value read back from the register
> +**/
> +UINT32
> +PchPcrAndThenOr32WithReadback (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT32 AndData,
> + IN UINT32 OrData
> + )
> +{
> + PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData) |
> OrData);
> + return PchPcrRead32 (Pid, Offset);
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 2bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] AndData AND Data. Must be the same size as Size parameter.
> + @param[in] OrData OR Data. Must be the same size as Size parameter.
> +
> + @retval UINT16 Value written to register
> +
> +**/
> +UINT16
> +PchPcrAndThenOr16 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT16 AndData,
> + IN UINT16 OrData
> + )
> +{
> + return PchPcrWrite16 (Pid, Offset, (PchPcrRead16 (Pid, Offset) & AndData) |
> OrData);
> +}
> +
> +/**
> + Write PCR register.
> + It programs PCR register and size in 1bytes.
> + The Offset should not exceed 0xFFFF and must be aligned with size.
> +
> + @param[in] Pid Port ID
> + @param[in] Offset Register offset of Port ID.
> + @param[in] AndData AND Data. Must be the same size as Size parameter.
> + @param[in] OrData OR Data. Must be the same size as Size parameter.
> +
> + @retval UINT8 Value written to register
> +
> +**/
> +UINT8
> +PchPcrAndThenOr8 (
> + IN PCH_SBI_PID Pid,
> + IN UINT32 Offset,
> + IN UINT8 AndData,
> + IN UINT8 OrData
> + )
> +{
> + return PchPcrWrite8 (Pid, Offset, (PchPcrRead8 (Pid, Offset) & AndData) |
> OrData);
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchP
> mcLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchP
> mcLib.c
> new file mode 100644
> index 0000000000..2654a76983
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchP
> mcLib.c
> @@ -0,0 +1,101 @@
> +/** @file
> + PCH PMC Library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/MmPciLib.h>
> +#include <PchAccess.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/PchPmcLib.h>
> +
> +/**
> + Query PCH to determine the Pm Status
> + NOTE:
> + It's matter when did platform code use this library, since some status could
> be cleared by write one clear.
> + Therefore this funciton is not always return the same result in one boot.
> + It's suggested that platform code read this status in the beginning of post.
> + For the ColdBoot case, this function only returns one case of the cold boot.
> Some cold boot case might
> + depends on the power cycle scenario and should check with different
> condtion.
> +
> + @param[in] PmStatus - The Pch Pm Status to be probed
> +
> + @retval Return TRUE if Status querried is Valid or FALSE if otherwise
> +**/
> +BOOLEAN
> +GetPchPmStatus (
> + PCH_PM_STATUS PmStatus
> + )
> +{
> + UINTN PmcRegBase;
> + UINT32 GblRst0;
> +
> + PmcRegBase = MmPciBase (
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_PMC,
> + PCI_FUNCTION_NUMBER_PCH_PMC
> + );
> +
> + switch (PmStatus) {
> + case WarmBoot:
> + break;
> +
> + case PwrFlr:
> + break;
> +
> + case PwrFlrSys:
> + if (GblRst0 & BIT12) {
> + return TRUE;
> + }
> + break;
> +
> + case PwrFlrPch:
> + if (GblRst0 & BIT11) {
> + return TRUE;
> + }
> + break;
> +
> + case ColdBoot:
> + break;
> +
> + default:
> + break;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Funtion to check if Battery lost or CMOS cleared.
> +
> + @reval TRUE Battery is always present.
> + @reval FALSE CMOS is cleared.
> +**/
> +BOOLEAN
> +EFIAPI
> +PchIsRtcBatteryGood (
> + VOID
> + )
> +{
> + UINTN PmcBaseAddress;
> +
> + //
> + // Check if the CMOS battery is present
> + // Checks RTC_PWR_STS bit in the GEN_PMCON_3 register
> + //
> + PmcBaseAddress = MmPciBase (
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_PMC,
> + PCI_FUNCTION_NUMBER_PCH_PMC
> + );
> + return FALSE;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PchSbiAccessLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PchSbiAccessLib.c
> new file mode 100644
> index 0000000000..43690e2409
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib
> /PchSbiAccessLib.c
> @@ -0,0 +1,270 @@
> +/** @file
> + PCH SBI access library.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchSbiAccessLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsP2sb.h>
> +
> +/**
> + Execute PCH SBI message
> + Take care of that there is no lock protection when using SBI programming in
> both POST time and SMI.
> + It will clash with POST time SBI programming when SMI happen.
> + Programmer MUST do the save and restore opration while using the
> PchSbiExecution inside SMI
> + to prevent from racing condition.
> + This function will reveal P2SB and hide P2SB if it's originally hidden. If more
> than one SBI access
> + needed, it's better to unhide the P2SB before calling and hide it back after
> done.
> +
> + When the return value is "EFI_SUCCESS", the "Response" do not need to be
> checked as it would have been
> + SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would
> provide additional information
> + when needed.
> +
> + @param[in] Pid Port ID of the SBI message
> + @param[in] Offset Offset of the SBI message
> + @param[in] Opcode Opcode
> + @param[in] Posted Posted message
> + @param[in, out] Data32 Read/Write data
> + @param[out] Response Response
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_DEVICE_ERROR Transaction fail
> + @retval EFI_INVALID_PARAMETER Invalid parameter
> + @retval EFI_TIMEOUT Timeout while waiting for response
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchSbiExecution (
> + IN PCH_SBI_PID Pid,
> + IN UINT64 Offset,
> + IN PCH_SBI_OPCODE Opcode,
> + IN BOOLEAN Posted,
> + IN OUT UINT32 *Data32,
> + OUT UINT8 *Response
> + )
> +{
> + //
> + // Check address valid
> + //
> + if (((UINT32) Offset & 0x3) != 0) {
> + //
> + // Warning message for the address not DWORD alignment.
> + //
> + DEBUG ((DEBUG_INFO, "PchSbiExecution: Address is not DWORD
> aligned.\n"));
> + }
> +
> + return PchSbiExecutionEx ( Pid,
> + Offset,
> + Opcode,
> + Posted,
> + 0x000F,
> + 0x0000,
> + 0x0000,
> + Data32,
> + Response
> + );
> +}
> +
> +/**
> + Full function for executing PCH SBI message
> + Take care of that there is no lock protection when using SBI programming in
> both POST time and SMI.
> + It will clash with POST time SBI programming when SMI happen.
> + Programmer MUST do the save and restore opration while using the
> PchSbiExecution inside SMI
> + to prevent from racing condition.
> + This function will reveal P2SB and hide P2SB if it's originally hidden. If more
> than one SBI access
> + needed, it's better to unhide the P2SB before calling and hide it back after
> done.
> +
> + When the return value is "EFI_SUCCESS", the "Response" do not need to be
> checked as it would have been
> + SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would
> provide additional information
> + when needed.
> +
> + @param[in] Pid Port ID of the SBI message
> + @param[in] Offset Offset of the SBI message
> + @param[in] Opcode Opcode
> + @param[in] Posted Posted message
> + @param[in] Fbe First byte enable
> + @param[in] Bar Bar
> + @param[in] Fid Function ID
> + @param[in, out] Data32 Read/Write data
> + @param[out] Response Response
> +
> + @retval EFI_SUCCESS Successfully completed.
> + @retval EFI_DEVICE_ERROR Transaction fail
> + @retval EFI_INVALID_PARAMETER Invalid parameter
> + @retval EFI_TIMEOUT Timeout while waiting for response
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchSbiExecutionEx (
> + IN PCH_SBI_PID Pid,
> + IN UINT64 Offset,
> + IN PCH_SBI_OPCODE Opcode,
> + IN BOOLEAN Posted,
> + IN UINT16 Fbe,
> + IN UINT16 Bar,
> + IN UINT16 Fid,
> + IN OUT UINT32 *Data32,
> + OUT UINT8 *Response
> + )
> +{
> + UINT64 P2sbBase;
> + UINTN Timeout;
> + UINT16 SbiStat;
> +
> + //
> + // Check opcode valid
> + //
> + switch (Opcode) {
> + case MemoryRead:
> + case MemoryWrite:
> + case PciConfigRead:
> + case PciConfigWrite:
> + case PrivateControlRead:
> + case PrivateControlWrite:
> + case GpioLockUnlock:
> + break;
> + default:
> + return EFI_INVALID_PARAMETER;
> + break;
> + }
> +
> + P2sbBase = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_P2SB,
> + PCI_FUNCTION_NUMBER_PCH_P2SB,
> + 0
> + );
> + if (PciSegmentRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
> + ASSERT (FALSE);
> + return EFI_DEVICE_ERROR;
> + }
> + ///
> + /// BWG Section 2.2.1
> + /// 1. Poll P2SB PCI offset D8h[0] = 0b
> + /// Make sure the previous opeartion is completed.
> + ///
> + Timeout = 0xFFFFFFF;
> + while (Timeout > 0) {
> + SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
> + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
> + break;
> + }
> + Timeout--;
> + }
> + if (Timeout == 0) {
> + return EFI_TIMEOUT;
> + }
> + //
> + // Initial Response status
> + //
> + *Response = SBI_INVALID_RESPONSE;
> + SbiStat = 0;
> + ///
> + /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
> + ///
> + PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIADDR, (UINT32) ((Pid << 24)
> | (UINT16) Offset));
> + ///
> + /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is
> expected to be 0 in PCH.
> + ///
> + PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIEXTADDR, (UINT32)
> RShiftU64 (Offset, 16));
> + ///
> + /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
> + /// Set P2SB PCI offset D8h[15:8] = 00000111b for write
> + //
> + // Set SBISTAT[15:8] to the opcode passed in
> + // Set SBISTAT[7] to the posted passed in
> + //
> + PciSegmentAndThenOr16 (
> + (P2sbBase + R_P2SB_CFG_SBISTAT),
> + (UINT16) ~(B_P2SB_CFG_SBISTAT_OPCODE |
> B_P2SB_CFG_SBISTAT_POSTED),
> + (UINT16) ((Opcode << 8) | (Posted << 7))
> + );
> + ///
> + /// 6. Write P2SB PCI offset DAh[15:0] = F000h
> + ///
> + //
> + // Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
> + //
> + PciSegmentWrite16 (
> + (P2sbBase + R_P2SB_CFG_SBIRID),
> + (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
> + );
> +
> + switch (Opcode) {
> + case MemoryWrite:
> + case PciConfigWrite:
> + case PrivateControlWrite:
> + case GpioLockUnlock:
> + ///
> + /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
> + ///
> + PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), *Data32);
> + break;
> + default:
> + ///
> + /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
> + /// because all D0-DFh register range must be touched in PCH
> + /// for a successful SBI transaction.
> + ///
> + PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), 0);
> + break;
> + }
> + ///
> + /// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
> + ///
> + //
> + // Set SBISTAT[0] = 1b, trigger the SBI operation
> + //
> + PciSegmentOr16 (P2sbBase + R_P2SB_CFG_SBISTAT, (UINT16)
> B_P2SB_CFG_SBISTAT_INITRDY);
> + //
> + // Poll SBISTAT[0] = 0b, Polling for Busy bit
> + //
> + Timeout = 0xFFFFFFF;
> + while (Timeout > 0) {
> + SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
> + if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
> + break;
> + }
> + Timeout--;
> + }
> + if (Timeout == 0) {
> + //
> + // If timeout, it's fatal error.
> + //
> + return EFI_TIMEOUT;
> + } else {
> + ///
> + /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
> + ///
> + *Response = (UINT8) ((SbiStat & B_P2SB_CFG_SBISTAT_RESPONSE) >>
> N_P2SB_CFG_SBISTAT_RESPONSE);
> + if (*Response == SBI_SUCCESSFUL) {
> + switch (Opcode) {
> + case MemoryRead:
> + case PciConfigRead:
> + case PrivateControlRead:
> + ///
> + /// 9. Read P2SB PCI offset D4h[31:0] for SBI data
> + ///
> + *Data32 = PciSegmentRead32 (P2sbBase + R_P2SB_CFG_SBIDATA);
> + break;
> + default:
> + break;
> + }
> + return EFI_SUCCESS;
> + } else {
> + return EFI_DEVICE_ERROR;
> + }
> + }
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLib.c
> new file mode 100644
> index 0000000000..0e79d83a12
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLib.c
> @@ -0,0 +1,516 @@
> +/** @file
> + PCH Serial IO Lib implementation.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <SaAccess.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PcdLib.h>
> +#include <Private/Library/GpioPrivateLib.h>
> +#include <Library/PchSerialIoLib.h>
> +#include <Library/PchSerialIoUartLib.h>
> +#include <Include/PcieRegs.h>
> +#include <Private/Library/PchPsfPrivateLib.h>
> +#include <PchLimits.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsPcr.h>
> +#include <Register/PchRegsSerialIo.h>
> +
> +#define PCIEX_BAR_ADDR_MASK 0x0000007FFC000000
> +
> +typedef struct {
> + UINT32 Bar0;
> + UINT32 Bar1;
> +} SERIAL_IO_CONTROLLER_DESCRIPTOR;
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR
> mSerialIoAcpiAddress [PCH_MAX_SERIALIO_CONTROLLERS] =
> +{
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x1000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x3000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x5000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x7000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x9000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0xB000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0xD000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0xF000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x11000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x13000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x15000},
> + {PCH_SERIAL_IO_BASE_ADDRESS + 0x16000,
> PCH_SERIAL_IO_BASE_ADDRESS + 0x17000}
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchSerialIoPciCfgCtrAddr
> [PCH_MAX_SERIALIO_CONTROLLERS] =
> +{
> + R_SERIAL_IO_PCR_PCICFGCTRL1,
> + R_SERIAL_IO_PCR_PCICFGCTRL2,
> + R_SERIAL_IO_PCR_PCICFGCTRL3,
> + R_SERIAL_IO_PCR_PCICFGCTRL4,
> + R_SERIAL_IO_PCR_PCICFGCTRL5,
> + R_SERIAL_IO_PCR_PCICFGCTRL6,
> + R_SERIAL_IO_PCR_PCICFGCTRL13,
> + R_SERIAL_IO_PCR_PCICFGCTRL14,
> + R_SERIAL_IO_PCR_PCICFGCTRL9,
> + R_SERIAL_IO_PCR_PCICFGCTRL10,
> + R_SERIAL_IO_PCR_PCICFGCTRL11
> +};
> +
> +/**
> + Returns Serial IO Controller Type I2C, SPI or UART
> +
> + @param[in] Number Number of SerialIo controller
> +
> + @retval I2C, SPI or UART
> + @retval UNKNOWN - in case if undefined controller
> +**/
> +PCH_SERIAL_IO_CONTROLLER_TYPE
> +GetSerialIoControllerType (
> + IN PCH_SERIAL_IO_CONTROLLER Controller
> + )
> +{
> + if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber
> ()) {
> + return SERIAL_IO_I2C;
> + } else if (Controller >= PchSerialIoIndexSpi0 && Controller <
> (PchSerialIoIndexSpi0 + GetPchMaxSerialIoSpiControllersNum ())) {
> + return SERIAL_IO_SPI;
> + } else if (Controller >= PchSerialIoIndexUart0 && Controller <=
> PchSerialIoIndexUart2) {
> + return SERIAL_IO_UART;
> + }
> + return SERIAL_IO_UNKNOWN;
> +}
> +
> +/**
> + Checks if given Serial IO Controller Function equals 0
> +
> + @param[in] SerialIoNumber Serial IO device
> +
> + @retval TRUE if SerialIO Function is equal to 0
> + FALSE if Function is higher then 0
> +**/
> +BOOLEAN
> +IsSerialIoFunctionZero (
> + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
> + )
> +{
> + if (GetSerialIoFunctionNumber (SerialIoNumber) > 0) {
> + return FALSE;
> + }
> + return TRUE;
> +}
> +
> +/**
> + Checks if given Serial IO Controller is enabled or not
> +
> + @param[in] DeviceNumber device number
> + @param[in] FunctionNumber function number
> +
> + @retval TRUE TRUE if given serial io device is enabled.
> + @retval FALSE FALSE if given serial io device is disabled.
> +**/
> +BOOLEAN
> +IsSerialIoDeviceEnabled (
> + IN UINT8 DeviceNumber,
> + IN UINT8 FunctionNumber
> + )
> +{
> + if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH,
> DeviceNumber, FunctionNumber, PCI_DEVICE_ID_OFFSET)) != 0xFFFF) {
> + return TRUE;
> + }
> + return FALSE;
> +}
> +
> +/**
> + Checks if given device corresponds to any of LPSS Devices
> +
> + @param[in] DeviceNumber device number
> + @param[in] FunctionNumber function number
> +
> + @retval TRUE if SerialIO Device/Function Number is
> equal to any of LPSS devices
> + FALSE Device/Function is not in Serial IO scope
> +**/
> +BOOLEAN
> +IsSerialIoDevice (
> + IN UINT8 DeviceNumber,
> + IN UINT8 FunctionNumber
> + )
> +{
> + PCH_SERIAL_IO_CONTROLLER Controller;
> + PCH_SERIAL_IO_CONTROLLER ControllerMax;
> +
> + ControllerMax = GetPchMaxSerialIoControllersNum ();
> +
> + for (Controller = 0; Controller < ControllerMax; Controller++) {
> + if ((DeviceNumber == GetSerialIoDeviceNumber (Controller)) &&
> + (FunctionNumber == GetSerialIoFunctionNumber (Controller))) {
> + return TRUE;
> + }
> + }
> + return FALSE;
> +}
> +
> +/**
> + Gets Pci Config control offset
> +
> + @param[in] DeviceNumber device number
> + @param[in] FunctionNumber function number
> +
> + @retval CfgCtrAddr Offset of Pci config control
> + 0 if Device and Function do not correspond to
> Serial IO
> +**/
> +UINT16
> +GetSerialIoConfigControlOffset (
> + IN UINT8 DeviceNumber,
> + IN UINT8 FunctionNumber
> + )
> +{
> + PCH_SERIAL_IO_CONTROLLER Controller;
> + PCH_SERIAL_IO_CONTROLLER ControllerMax;
> +
> + ControllerMax = GetPchMaxSerialIoControllersNum ();
> +
> + for (Controller = 0; Controller < ControllerMax; Controller++) {
> + if ((DeviceNumber == GetSerialIoDeviceNumber (Controller)) &&
> + (FunctionNumber == GetSerialIoFunctionNumber (Controller))) {
> + return mPchSerialIoPciCfgCtrAddr[Controller];
> + }
> + }
> +
> + return 0;
> +}
> +
> +/**
> + Checks if Device with given AcpiHid string is one of SerialIo controllers
> + If yes, its number is returned through Number parameter, otherwise
> Number is not updated
> +
> + @param[in] AcpiHid String
> + @param[out] Number Number of SerialIo controller
> +
> + @retval TRUE yes it is a SerialIo controller
> + @retval FALSE no it isn't a SerialIo controller
> +**/
> +BOOLEAN
> +IsSerialIoAcpiHid (
> + IN CHAR8 *AcpiHid,
> + OUT PCH_SERIAL_IO_CONTROLLER *Number
> + )
> +{
> + PCH_SERIAL_IO_CONTROLLER Controller;
> + PCH_SERIAL_IO_CONTROLLER ControllerMax;
> +
> + ControllerMax = GetPchMaxSerialIoControllersNum ();
> +
> + for (Controller = 0; Controller < ControllerMax; Controller++) {
> + if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, GetSerialIoAcpiHid(Controller)))
> {
> + *Number = Controller;
> + return TRUE;
> + }
> + }
> + return FALSE;
> +}
> +
> +/**
> + Finds BAR values of SerialIo devices.
> + SerialIo devices can be configured to not appear on PCI so traditional
> method of reading BAR might not work.
> + If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG
> space instead
> +
> + @param[in] SerialIoDevice Serial IO device
> + @param[in] BarNumber 0=BAR0, 1=BAR1
> +
> + @retval SerialIo Bar value
> +**/
> +UINTN
> +FindSerialIoBar (
> + IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
> + IN UINT8 BarNumber
> + )
> +{
> + UINT64 Bar;
> + UINT64 PcieBase;
> + UINT64 PciSegBase;
> + UINT16 VenId;
> + UINT32 Device;
> + UINT32 Function;
> +
> + Device = GetSerialIoDeviceNumber (SerialIoDevice);
> + Function = GetSerialIoFunctionNumber (SerialIoDevice);
> +
> + PcieBase = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM,
> SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_PCIEXBAR)); // S0:B0:D0:F0:R60
> + PcieBase = (PcieBase & PCIEX_BAR_ADDR_MASK) + LShiftU64
> (DEFAULT_PCI_BUS_NUMBER_PCH, 20) + LShiftU64 (Device, 15) + LShiftU64
> (Function, 12);
> +
> + PciSegBase = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + Device,
> + Function,
> + 0
> + );
> +
> + VenId = PciSegmentRead16 (PciSegBase + PCI_VENDOR_ID_OFFSET) &
> 0xFFFF;
> + if (VenId == V_PCH_INTEL_VENDOR_ID) {
> + if (BarNumber == 1) {
> + return ((UINTN) PcieBase);
> + }
> + Bar = PciSegmentRead32 (PciSegBase + PCI_BASE_ADDRESSREG_OFFSET);
> + // For 64-Bit Memory Space BARs ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] &
> 0xFFFFFFFF) << 32)
> + if ((Bar & B_PCI_BAR_MEMORY_TYPE_MASK) ==
> B_PCI_BAR_MEMORY_TYPE_64) {
> + Bar = (Bar & 0xFFFFF000) + (UINTN) ((UINT64) LShiftU64
> ((PciSegmentRead32 (PciSegBase + PCI_BASE_ADDRESSREG_OFFSET + 4) &
> 0xFFFFFFFF), 32));
> + return (UINTN) Bar;
> + }
> + return (UINTN) (Bar & 0xFFFFF000);
> + }
> + //PCI mode failed? Try hardcoded addresses from ACPI
> + if (BarNumber == 0) {
> + Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar0;
> + } else {
> + Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar1;
> + }
> + return (UINTN) Bar;
> +}
> +
> +/**
> + Get PSF_PORT for a given Serial IO Controller
> +
> + @param[in] Controller Serial IO controller number
> +**/
> +STATIC
> +PSF_PORT
> +SerialIoPsfPort (
> + IN PCH_SERIAL_IO_CONTROLLER Controller
> + )
> +{
> + switch (GetSerialIoControllerType (Controller)) {
> + case SERIAL_IO_I2C:
> + return PsfSerialIoI2cPort (Controller - PchSerialIoIndexI2C0);
> + case SERIAL_IO_SPI:
> + return PsfSerialIoSpiPort (Controller - PchSerialIoIndexSpi0);
> + case SERIAL_IO_UART:
> + return PsfSerialIoUartPort (Controller - PchSerialIoIndexUart0);
> + case SERIAL_IO_UNKNOWN:
> + default:
> + return (PSF_PORT){0};
> + }
> +}
> +
> +/**
> + Configures Serial IO Controller
> +
> + @param[in] Controller Serial IO controller number
> + @param[in] DeviceMode Device operation mode
> + @param[in] PsfDisable Disable device at PSF level
> +
> + @retval None
> +**/
> +VOID
> +ConfigureSerialIoController (
> + IN PCH_SERIAL_IO_CONTROLLER Controller,
> + IN PCH_SERIAL_IO_MODE DeviceMode,
> + IN BOOLEAN PsfDisable
> + )
> +{
> + UINT64 PciCfgBase;
> + UINT32 Data32And;
> + UINT32 Data32Or;
> + UINT16 *SerialIoPciCfgCtrAddr;
> + UINT8 Uart8BitLoop;
> +
> +/*
> + Please do not add DEBUG message here because this routine is configuring
> SerialIoUart.
> + Printing DEBUG message before SerialIoUart initialization may cause system
> hang (in Debug build).
> +*/
> +
> + //
> + // This is to prevent from overflow of array access.
> + //
> + if (Controller >= PCH_MAX_SERIALIO_CONTROLLERS) {
> + return;
> + }
> +
> + if (GetSerialIoControllerType (Controller) == SERIAL_IO_UNKNOWN) {
> + return;
> + }
> +
> + PciCfgBase = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + GetSerialIoDeviceNumber (Controller),
> + GetSerialIoFunctionNumber (Controller),
> + 0
> + );
> + //
> + // Do not modify a device that has already been disabled/hidden
> + //
> + if (PciSegmentRead16 (PciCfgBase + PCI_VENDOR_ID_OFFSET) !=
> V_PCH_INTEL_VENDOR_ID) {
> + return;
> + }
> +
> + ///
> + /// Step 0. set Bit 16,17,18.
> + ///
> + PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_D0I3MAXDEVPG, BIT18 |
> BIT17 | BIT16);
> +
> + SerialIoPciCfgCtrAddr = mPchSerialIoPciCfgCtrAddr;
> +
> + switch (DeviceMode) {
> + case PchSerialIoDisabled:
> + ///
> + /// Step 1. Put device in D3
> + /// Step 2. Function Disable in PSF
> + ///
> + PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, BIT1 |
> BIT0);
> +
> + if (PsfDisable) {
> + PsfDisableDevice (SerialIoPsfPort (Controller));
> + }
> + break;
> + case PchSerialIoAcpi:
> + case PchSerialIoHidden:
> + ///
> + /// reenable BAR1 in case it was disabled earlier
> + /// Read back is needed to enforce the sideband and primary ordering.
> + ///
> + PchPcrAndThenOr32WithReadback (
> + PID_SERIALIO,
> + SerialIoPciCfgCtrAddr[Controller],
> + (UINT32) ~(B_SERIAL_IO_PCR_PCICFGCTRL_BAR1_DIS),
> + 0
> + );
> + PsfEnableDeviceBar (SerialIoPsfPort (Controller), BIT3 | BIT2);
> + ///
> + /// Step 1. Assign BAR0
> + /// Step 2. Assign BAR1
> + ///
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW,
> mSerialIoAcpiAddress[Controller].Bar0);
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0);
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR1_LOW,
> mSerialIoAcpiAddress[Controller].Bar1);
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR1_HIGH, 0x0);
> + ///
> + /// Step 3. Set Memory space Enable
> + ///
> + PciSegmentOr32 (PciCfgBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> + ///
> + /// Step 4. Disable device's PciCfg and enable ACPI interrupts
> + /// Read back is needed to enforce the sideband and primary
> ordering.
> + ///
> + PchPcrAndThenOr32WithReadback (
> + PID_SERIALIO,
> + SerialIoPciCfgCtrAddr[Controller],
> + ~0u,
> + (B_SERIAL_IO_PCR_PCICFGCTRL_PCI_CFG_DIS |
> B_SERIAL_IO_PCR_PCICFGCTRL_ACPI_INTR_EN)
> + );
> + ///
> + /// Step 5. Disable device's PciCfg in PSF
> + ///
> + PsfHideDevice (SerialIoPsfPort (Controller));
> + ///
> + /// get controller out of reset
> + ///
> + MmioOr32 (
> + mSerialIoAcpiAddress[Controller].Bar0 +
> R_SERIAL_IO_MEM_PPR_RESETS,
> + B_SERIAL_IO_MEM_PPR_RESETS_FUNC |
> B_SERIAL_IO_MEM_PPR_RESETS_APB |
> B_SERIAL_IO_MEM_PPR_RESETS_IDMA
> + );
> + break;
> + case PchSerialIoPci:
> + //
> + // Check If device is already initialized
> + //
> + if (PciSegmentRead32 (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET) &
> 0xFFFFF000) {
> + return;
> + }
> + ///
> + /// reenable PciCfg in case it was disabled earlier
> + /// Read back is needed to enforce the sideband and primary ordering.
> + ///
> + PchPcrAndThenOr32WithReadback (
> + PID_SERIALIO,
> + SerialIoPciCfgCtrAddr[Controller],
> + (UINT32) ~(B_SERIAL_IO_PCR_PCICFGCTRL_PCI_CFG_DIS |
> B_SERIAL_IO_PCR_PCICFGCTRL_ACPI_INTR_EN),
> + 0
> + );
> + PsfUnhideDevice (SerialIoPsfPort (Controller));
> + ///
> + /// Disable Bar1
> + /// Disable Bar1 in PSF
> + /// Read back is needed to enforce the sideband and primary ordering.
> + ///
> + PchPcrAndThenOr32WithReadback (
> + PID_SERIALIO,
> + SerialIoPciCfgCtrAddr[Controller],
> + ~0u,
> + B_SERIAL_IO_PCR_PCICFGCTRL_BAR1_DIS
> + );
> + PsfDisableDeviceBar (SerialIoPsfPort (Controller), BIT3 | BIT2);
> +
> + //
> + // Assign BAR0 and Set Memory space Enable
> + //
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW,
> mSerialIoAcpiAddress[Controller].Bar0);
> + PciSegmentWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0);
> + PciSegmentOr32 (PciCfgBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> + ///
> + /// get controller out of reset
> + ///
> + MmioOr32 (
> + mSerialIoAcpiAddress[Controller].Bar0 +
> R_SERIAL_IO_MEM_PPR_RESETS,
> + B_SERIAL_IO_MEM_PPR_RESETS_FUNC |
> B_SERIAL_IO_MEM_PPR_RESETS_APB |
> B_SERIAL_IO_MEM_PPR_RESETS_IDMA
> + );
> + break;
> + default:
> + return;
> + }
> +
> + ///
> + /// Step X. Program clock dividers for UARTs
> + /// Step Y. Enable Byte addressing for UARTs in legacy mode
> + ///
> + if ((Controller >= PchSerialIoIndexUart0 && Controller <=
> PchSerialIoIndexUart2) && (DeviceMode != PchSerialIoDisabled)) {
> + MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 +
> R_SERIAL_IO_MEM_PPR_CLK,
> + (B_SERIAL_IO_MEM_PPR_CLK_UPDATE |
> (V_SERIAL_IO_MEM_PPR_CLK_N_DIV << 16) |
> + (V_SERIAL_IO_MEM_PPR_CLK_M_DIV << 1) |
> B_SERIAL_IO_MEM_PPR_CLK_EN )
> + );
> +
> + Data32And = (UINT32)
> (~(B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller -
> PchSerialIoIndexUart0)));
> + Data32Or = 0x0;
> + if (DeviceMode == PchSerialIoHidden) {
> + Data32Or = (B_SERIAL_IO_PCR_GPPRVRW7_UART0_BYTE_ADDR_EN <<
> (Controller - PchSerialIoIndexUart0));
> + }
> + PchPcrAndThenOr32 (PID_SERIALIO,
> R_SERIAL_IO_PCR_GPPRVRW7,Data32And,Data32Or);
> + //
> + // Dummy read after setting any of GPPRVRW7.
> + // Required for UART 16550 8-bit Legacy mode to become active
> + //
> + MmioRead32 (mSerialIoAcpiAddress[Controller].Bar0 +
> R_SERIAL_IO_MEM_PPR_CLK);
> + //
> + // Loop until Uart has successfuly moved to 8 bit mode
> + //
> + if (DeviceMode == PchSerialIoHidden) {
> + Uart8BitLoop = 10;
> + while (Uart8BitLoop > 0) {
> + if (DetectAccessMode (mSerialIoAcpiAddress[Controller].Bar0) ==
> AccessMode8bit) {
> + return;
> + }
> + Uart8BitLoop--;
> + }
> + }
> + }
> +
> + ///
> + /// Step Z. Program I2C SDA hold registers
> + ///
> + if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber
> ()) {
> + if (DeviceMode != PchSerialIoDisabled) {
> + MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 +
> R_SERIAL_IO_MEM_I2C_SDA_HOLD,
> V_SERIAL_IO_MEM_I2C_SDA_HOLD_VALUE);
> + }
> + }
> +
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibCnl.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibCnl.c
> new file mode 100644
> index 0000000000..28ccd626af
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/P
> chSerialIoLibCnl.c
> @@ -0,0 +1,181 @@
> +/** @file
> + PCH Serial IO Lib implementation Cannon Lake specific.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PcdLib.h>
> +#include <Private/Library/GpioPrivateLib.h>
> +#include <Library/PchSerialIoLib.h>
> +#include <Private/Library/PchPsfPrivateLib.h>
> +
> +#include <PchLimits.h>
> +#include <Register/PchRegsSerialIoCnl.h>
> +#include "PchSerialIoLibInternal.h"
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
> mCnlAcpiHid[PCH_MAX_SERIALIO_CONTROLLERS][SERIALIO_HID_LENGTH] =
> +{
> + "INT34B2",
> + "INT34B3",
> + "INT34B4",
> + "INT34B5",
> + "INT34B6",
> + "INT34B7",
> + "INT34B0",
> + "INT34B1",
> + "INT34BC",
> + "INT34B8",
> + "INT34B9",
> + "INT34BA"
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mCnlPchLpSerialIoId
> [PCH_MAX_SERIALIO_CONTROLLERS] =
> +{
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C0_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C1_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C2_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C3_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C4_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_I2C5_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_SPI0_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_SPI1_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_UART0_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_UART1_DEVICE_ID,
> + V_CNL_PCH_LP_SERIAL_IO_CFG_UART2_DEVICE_ID
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mCnlPchHSerialIoId
> [PCH_MAX_SERIALIO_CONTROLLERS] =
> +{
> + V_CNL_PCH_H_SERIAL_IO_CFG_I2C0_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_I2C1_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_I2C2_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_I2C3_DEVICE_ID,
> + 0,
> + 0,
> + V_CNL_PCH_H_SERIAL_IO_CFG_SPI0_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_SPI1_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_UART0_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_UART1_DEVICE_ID,
> + V_CNL_PCH_H_SERIAL_IO_CFG_UART2_DEVICE_ID
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS
> mSerialIoBdf [PCH_MAX_SERIALIO_CONTROLLERS] =
> +{
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1},
> + {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2,
> PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2}
> +};
> +
> +
> +/**
> + Returns index of the last i2c controller
> +
> + @param[in] Number Number of SerialIo controller
> +
> + @retval Index of I2C controller
> +**/
> +PCH_SERIAL_IO_CONTROLLER
> +GetMaxI2cNumber (
> + VOID
> + )
> +{
> + if (IsPchH ()) {
> + return PchSerialIoIndexI2C3;
> + } else {
> + return PchSerialIoIndexI2C5;
> + }
> +}
> +
> +/**
> + Checks if Device with given PciDeviceId is one of SerialIo controllers
> + If yes, its number is returned through Number parameter, otherwise
> Number is not updated
> +
> + @param[in] PciDevId Device ID
> + @param[out] Number Number of SerialIo controller
> +
> + @retval TRUE Yes it is a SerialIo controller
> + @retval FALSE No it isn't a SerialIo controller
> +**/
> +BOOLEAN
> +IsSerialIoPciDevId (
> + IN UINT16 PciDevId,
> + OUT PCH_SERIAL_IO_CONTROLLER *Number
> + )
> +{
> + PCH_SERIAL_IO_CONTROLLER Controller;
> +
> + for (Controller = 0; Controller < GetPchMaxSerialIoControllersNum ();
> Controller++) {
> + if ((IsPchLp () && (PciDevId == mCnlPchLpSerialIoId[Controller])) ||
> + (IsPchH () && (PciDevId == mCnlPchHSerialIoId[Controller])))
> + {
> + *Number = Controller;
> + return TRUE;
> + }
> + }
> + return FALSE;
> +}
> +
> +/**
> + Finds PCI Device Number of SerialIo devices.
> +
> + @param[in] SerialIoNumber Serial IO device
> +
> + @retval SerialIo device number
> +**/
> +UINT8
> +GetSerialIoDeviceNumber (
> + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
> + )
> +{
> + return mSerialIoBdf[SerialIoNumber].DevNum;
> +}
> +
> +/**
> + Finds PCI Function Number of SerialIo devices.
> +
> + @param[in] SerialIoNumber Serial IO device
> +
> + @retval SerialIo funciton number
> +**/
> +UINT8
> +GetSerialIoFunctionNumber (
> + IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
> + )
> +{
> + return mSerialIoBdf[SerialIoNumber].FuncNum;
> +}
> +
> +/**
> + Returns string with AcpiHid assigned to selected SerialIo controller
> +
> + @param[in] Number Number of SerialIo controller
> +
> + @retval pointer to 8-byte string
> +**/
> +CHAR8*
> +GetSerialIoAcpiHid (
> + IN PCH_SERIAL_IO_CONTROLLER Number
> + )
> +{
> + return mCnlAcpiHid[Number];
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.c
> new file mode 100644
> index 0000000000..621a473cfa
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoUartL
> ib/PeiDxeSmmPchSerialIoUartLib.c
> @@ -0,0 +1,372 @@
> +/** @file
> + PCH Serial IO UART Lib implementation.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchSerialIoLib.h>
> +#include <Library/PchSerialIoUartLib.h>
> +#include <IndustryStandard/Pci30.h>
> +
> +#define MAX_BAUD_RATE 115200
> +
> +#define R_PCH_SERIAL_IO_8BIT_UART_RXBUF 0x00
> +#define R_PCH_SERIAL_IO_8BIT_UART_TXBUF 0x00
> +#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW 0x00
> +#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH 0x01
> +#define R_PCH_SERIAL_IO_8BIT_UART_FCR 0x02
> +#define R_PCH_SERIAL_IO_8BIT_UART_IIR 0x02
> +#define R_PCH_SERIAL_IO_8BIT_UART_LCR 0x03
> +#define R_PCH_SERIAL_IO_8BIT_UART_MCR 0x04
> +#define R_PCH_SERIAL_IO_8BIT_UART_LSR 0x05
> +#define R_PCH_SERIAL_IO_8BIT_UART_USR 0x1F
> +#define R_PCH_SERIAL_IO_32BIT_UART_CTR 0xFC //Component Type
> Register contains identification code
> +#define UART_COMPONENT_IDENTIFICATION_CODE 0x44570110
> +
> +#define B_PCH_SERIAL_IO_UART_IIR_FIFOSE BIT7|BIT6
> +#define B_PCH_SERIAL_IO_UART_LSR_RXDA BIT0
> +#define B_PCH_SERIAL_IO_UART_LSR_BI BIT4
> +#define B_PCH_SERIAL_IO_UART_LSR_TXRDY BIT5
> +#define B_PCH_SERIAL_IO_UART_LCR_DLAB BIT7
> +#define B_PCH_SERIAL_IO_UART_FCR_FCR BIT0
> +#define B_PCH_SERIAL_IO_UART_MCR_RTS BIT1
> +#define B_PCH_SERIAL_IO_UART_MCR_AFCE BIT5
> +#define B_PCH_SERIAL_IO_UART_USR_TFNF BIT1
> +
> +/**
> + Returns UART's currently active access mode, 8 or 32 bit
> +
> + @param[in] MmioBase Base address of UART MMIO space
> +
> + @retval AccessMode8bit
> + @retval AccessMode32bit
> +**/
> +UART_ACCESS_MODE
> +DetectAccessMode (
> + IN UINTN MmioBase
> + )
> +{
> + if (MmioRead32 (MmioBase + R_PCH_SERIAL_IO_32BIT_UART_CTR) ==
> UART_COMPONENT_IDENTIFICATION_CODE) {
> + return AccessMode32bit;
> + } else {
> + return AccessMode8bit;
> + }
> +}
> +
> +
> +/**
> + Register access helper. Depending on SerialIO UART mode,
> + its registers are aligned to 1 or 4 bytes and have 8 or 32bit size
> +
> + @param[in] AccessMode Selects between 8bit access to 1-byte aligned
> registers or 32bit access to 4-byte algined
> + @param[in] BaseAddress Base address of UART MMIO space
> + @param[in] Offset Register offset in 8bit mode
> + @param[in] Data Data to be written
> +**/
> +STATIC
> +VOID
> +WriteRegister (
> + IN UART_ACCESS_MODE AccessMode,
> + IN UINTN BaseAddress,
> + IN UINTN Offset,
> + IN UINT8 Data
> + )
> +{
> + if (AccessMode == AccessMode32bit) {
> + MmioWrite32 (BaseAddress + 4*Offset, Data);
> + } else {
> + MmioWrite8 (BaseAddress + Offset, Data);
> + }
> +}
> +
> +/**
> + Register access helper. Depending on SerialIO UART mode,
> + its registers are aligned to 1 or 4 bytes and have 8 or 32bit size
> +
> + @param[in] AccessMode Selects between 8bit access to 1-byte aligned
> registers or 32bit access to 4-byte algined
> + @param[in] BaseAddress Base address of UART MMIO space
> + @param[in] Offset Register offset in 8bit mode
> + @retval retrieved register value, always 8bit regardless of
> access mode
> +**/
> +STATIC
> +UINT8
> +ReadRegister (
> + IN UART_ACCESS_MODE AccessMode,
> + IN UINTN BaseAddress,
> + IN UINTN Offset
> + )
> +{
> + if (AccessMode == AccessMode32bit) {
> + return (UINT8) (0xFF & MmioRead32 (BaseAddress + 4*Offset));
> + } else {
> + return MmioRead8 (BaseAddress + Offset);
> + }
> +}
> +
> +/**
> + SerialIo UART in PCI mode will become unavailable when PCI enumerator
> + disables its memory space. This function re-enables it
> +
> + @param[in] UartNumber Selects Serial IO UART device (0-2)
> +**/
> +STATIC
> +VOID
> +EnablePciMse (
> + IN UINT8 UartNumber
> + )
> +{
> + UINTN CfgSpace;
> +
> + CfgSpace = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 1);
> + if (MmioRead16 (CfgSpace + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
> + return;
> + }
> + if ((MmioRead16 (CfgSpace + PCI_COMMAND_OFFSET) &
> EFI_PCI_COMMAND_MEMORY_SPACE) !=
> EFI_PCI_COMMAND_MEMORY_SPACE) {
> + if ((MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) &
> 0xFFFFF000) != 0x0 &&
> + (MmioRead32 (CfgSpace + PCI_BASE_ADDRESSREG_OFFSET) &
> 0xFFFFF000) != 0xFFFFF000 ) {
> + MmioOr8 (CfgSpace + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> + }
> + }
> +}
> +
> +/**
> + Initialize selected SerialIo UART.
> + This init function MUST be used prior any SerialIo UART functions to init
> serial io controller if platform is going use serialio UART as debug output.
> +
> + @param UartNumber Selects Serial IO UART device (0-2)
> + @param FifoEnable When TRUE, enables 64-byte FIFOs.
> + @param BaudRate Baud rate.
> + @param LineControl Data length, parity, stop bits.
> + @param HardwareFlowControl Automated hardware flow control. If
> TRUE, hardware automatically checks CTS when sending data, and sets RTS
> when receiving data.
> +**/
> +VOID
> +EFIAPI
> +PchSerialIoUartInit (
> + UINT8 UartNumber,
> + BOOLEAN FifoEnable,
> + UINT32 BaudRate,
> + UINT8 LineControl,
> + BOOLEAN HardwareFlowControl
> + )
> +{
> + UINTN Base;
> + UINTN Divisor;
> + UART_ACCESS_MODE AccessMode;
> +
> + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
> + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) {
> + //
> + // Base is not programmed, skip it.
> + //
> + return;
> + }
> + EnablePciMse (UartNumber);
> + AccessMode = DetectAccessMode (Base);
> +
> + Divisor = MAX_BAUD_RATE / BaudRate;
> +
> + //
> + // Configure baud rate
> + //
> + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR,
> B_PCH_SERIAL_IO_UART_LCR_DLAB);
> + WriteRegister (AccessMode, Base,
> R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));
> + WriteRegister (AccessMode, Base,
> R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));
> + //
> + // Configure Line control and switch back to bank 0
> + //
> + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LCR,
> LineControl & 0x1F);
> + //
> + // Enable and reset FIFOs
> + //
> + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_FCR,
> FifoEnable?B_PCH_SERIAL_IO_UART_FCR_FCR:0 );
> + //
> + // Put Modem Control Register(MCR) into its reset state of 0x00.
> + //
> + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_MCR,
> B_PCH_SERIAL_IO_UART_MCR_RTS |
> (HardwareFlowControl?B_PCH_SERIAL_IO_UART_MCR_AFCE:0));
> +}
> +
> +/**
> + Write data to serial device.
> +
> + If the buffer is NULL, then return 0;
> + if NumberOfBytes is zero, then return 0.
> +
> + @param UartNumber Selects Serial IO UART device (0-2)
> + @param Buffer Point of data buffer which need to be writed.
> + @param NumberOfBytes Number of output bytes which are cached in
> Buffer.
> +
> + @retval Actual number of bytes writed to serial device.
> +**/
> +UINTN
> +EFIAPI
> +PchSerialIoUartOut (
> + IN UINT8 UartNumber,
> + IN UINT8 *Buffer,
> + IN UINTN NumberOfBytes
> + )
> +{
> + UINTN BytesLeft;
> + UINTN Base;
> + UART_ACCESS_MODE AccessMode;
> +
> + if (NULL == Buffer) {
> + return 0;
> + }
> +
> + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
> + //
> + // Sanity checks to avoid infinite loop when trying to print through
> uninitialized UART
> + //
> + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) {
> + return 0;
> + }
> + EnablePciMse (UartNumber);
> + AccessMode = DetectAccessMode (Base);
> +
> + if (ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_USR) ==
> 0xFF) {
> + return 0;
> + }
> +
> + BytesLeft = NumberOfBytes;
> +
> + while (BytesLeft != 0) {
> + //
> + // Write data while there's room in TXFIFO. If HW Flow Control was enabled,
> it happens automatically on hardware level.
> + //
> + if (ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_USR)
> & B_PCH_SERIAL_IO_UART_USR_TFNF) {
> + WriteRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_TXBUF,
> *Buffer);
> + Buffer++;
> + BytesLeft--;
> + }
> + }
> +
> + return NumberOfBytes;
> +}
> +
> +/*
> + Read data from serial device and save the datas in buffer.
> +
> + If the buffer is NULL, then return 0;
> + if NumberOfBytes is zero, then return 0.
> +
> + @param UartNumber Selects Serial IO UART device (0-2)
> + @param Buffer Point of data buffer which need to be writed.
> + @param NumberOfBytes Number of output bytes which are cached
> in Buffer.
> + @param WaitUntilBufferFull When TRUE, function waits until whole
> buffer is filled. When FALSE, function returns as soon as no new characters are
> available.
> +
> + @retval Actual number of bytes raed to serial device.
> +
> +**/
> +UINTN
> +EFIAPI
> +PchSerialIoUartIn (
> + IN UINT8 UartNumber,
> + OUT UINT8 *Buffer,
> + IN UINTN NumberOfBytes,
> + IN BOOLEAN WaitUntilBufferFull
> + )
> +{
> + UINTN BytesReceived;
> + UINTN Base;
> + UART_ACCESS_MODE AccessMode;
> + UINT8 Lsr;
> + UINT8 Byte;
> +
> + if (NULL == Buffer) {
> + return 0;
> + }
> +
> + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
> + //
> + // Sanity checks to avoid infinite loop when trying to print through
> uninitialized UART
> + //
> + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) {
> + return 0;
> + }
> + EnablePciMse (UartNumber);
> + AccessMode = DetectAccessMode (Base);
> +
> + BytesReceived = 0;
> +
> + while (BytesReceived != NumberOfBytes) {
> + //
> + // Read the line status register
> + //
> + Lsr = ReadRegister(AccessMode, Base,
> R_PCH_SERIAL_IO_8BIT_UART_LSR);
> +
> + //
> + // If there is data in the RX buffer, read it.
> + //
> + if ((Lsr & B_PCH_SERIAL_IO_UART_LSR_RXDA) != 0) {
> + Byte = ReadRegister (AccessMode, Base,
> R_PCH_SERIAL_IO_8BIT_UART_RXBUF);
> + //
> + // Check if the break interrupt bit is set. If set, the byte read from the
> + // RX buffer is invalid and should be ignored. If not set, copy the byte into
> + // the receive buffer.
> + //
> + if ((Lsr & B_PCH_SERIAL_IO_UART_LSR_BI) == 0) {
> + *Buffer = Byte;
> + Buffer++;
> + BytesReceived++;
> + }
> + } else {
> + if (!WaitUntilBufferFull) {
> + //
> + // If there's no data and function shouldn't wait, exit early
> + //
> + return BytesReceived;
> + }
> + }
> + }
> + return BytesReceived;
> +}
> +
> +/**
> + Polls a serial device to see if there is any data waiting to be read.
> +
> + Polls a serial device to see if there is any data waiting to be read.
> + If there is data waiting to be read from the serial device, then TRUE is
> returned.
> + If there is no data waiting to be read from the serial device, then FALSE is
> returned.
> +
> + @param UartNumber Selects Serial IO UART device (0-2)
> +
> + @retval TRUE Data is waiting to be read from the serial device.
> + @retval FALSE There is no data waiting to be read from the serial
> device.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +PchSerialIoUartPoll (
> + IN UINT8 UartNumber
> + )
> +{
> + UINTN Base;
> + UART_ACCESS_MODE AccessMode;
> +
> + Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
> + //
> + // Sanity checks to avoid infinite loop when trying to print through
> uninitialized UART
> + //
> + if ((Base & 0xFFFFFF00) == 0x0 || (Base & 0xFFFFF000) == 0xFFFFF000) {
> + return 0;
> + }
> + EnablePciMse (UartNumber);
> + AccessMode = DetectAccessMode (Base);
> +
> + //
> + // Read the serial port status
> + //
> + if ((ReadRegister (AccessMode, Base, R_PCH_SERIAL_IO_8BIT_UART_LSR) &
> B_PCH_SERIAL_IO_UART_LSR_RXDA) != 0) {
> + return TRUE;
> + }
> + return FALSE;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/WdtCommon.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/WdtCommon.c
> new file mode 100644
> index 0000000000..679dcae0ab
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommo
> nLib/WdtCommon.c
> @@ -0,0 +1,242 @@
> +/** @file
> + Library that contains common parts of WdtPei and WdtDxe. Not a
> standalone module.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PmcLib.h>
> +#include <Register/PchRegsPmc.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mAllowExpectedReset = 0;
> +
> +/**
> + Reads LPC bridge to get Watchdog Timer address
> +
> +
> + @retval UINT32 Watchdog's address
> +**/
> +UINT32
> +WdtGetAddress (
> + VOID
> + )
> +{
> + return PmcGetAcpiBase () + R_ACPI_IO_OC_WDT_CTL;
> +}
> +
> +/**
> + Reloads WDT with new timeout value and starts it. Also sets Unexpected
> Reset bit, which
> + causes the next reset to be treated as watchdog expiration - unless
> AllowKnownReset()
> + function was called too.
> +
> + @param[in] TimeoutValue Time in seconds before WDT times out.
> Supported range = 1 - 1024.
> +
> + @retval EFI_SUCCESS if everything's OK
> + @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
> +**/
> +EFI_STATUS
> +EFIAPI
> +WdtReloadAndStart (
> + IN UINT32 TimeoutValue
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "\n(Wdt) ReloadAndStartTimer(%d)\n",
> TimeoutValue));
> +
> + if ((TimeoutValue > B_ACPI_IO_OC_WDT_CTL_TOV_MASK) ||
> (TimeoutValue == 0)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Readback = IoRead32 (WdtGetAddress ());
> + Readback |= (B_ACPI_IO_OC_WDT_CTL_EN |
> B_ACPI_IO_OC_WDT_CTL_FORCE_ALL | B_ACPI_IO_OC_WDT_CTL_ICCSURV);
> + if (mAllowExpectedReset == 0) {
> + Readback |= B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS;
> + }
> +
> + if (PcdGetBool (PcdOcEnableWdtforDebug) == FALSE) {
> + ///
> + /// WDT will not be turned on. This is to prevent platform reboots
> triggered
> + /// by WDT expiration, which can be expected when processor is halted for
> debugging
> + ///
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_EN |
> B_ACPI_IO_OC_WDT_CTL_FORCE_ALL |
> B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS);
> + DEBUG ((DEBUG_INFO, "(Wdt) Wdt disabled in Debug BIOS\n"));
> + }
> +
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_TOV_MASK);
> + Readback |= ((TimeoutValue - 1) & B_ACPI_IO_OC_WDT_CTL_TOV_MASK);
> + IoWrite32 (WdtGetAddress (), Readback);
> + Readback |= B_ACPI_IO_OC_WDT_CTL_RLD;
> + IoWrite32 (WdtGetAddress (), Readback);
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Disables WDT timer.
> +
> +
> +**/
> +VOID
> +EFIAPI
> +WdtDisable (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) DisableTimer\n"));
> +
> + Readback = IoRead32 (WdtGetAddress ());
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_EN |
> B_ACPI_IO_OC_WDT_CTL_FORCE_ALL |
> B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS);
> + IoWrite32 (WdtGetAddress (), Readback);
> +}
> +
> +/**
> + Returns WDT failure status.
> +
> +
> + @retval V_ACPI_IO_OC_WDT_CTL_STATUS_FAILURE If there was WDT
> expiration or unexpected reset
> + @retval V_ACPI_IO_OC_WDT_CTL_STATUS_OK Otherwise
> +**/
> +UINT8
> +EFIAPI
> +WdtCheckStatus (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) CheckTimerStatus\n"));
> +
> + Readback = IoRead32 (WdtGetAddress ());
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) Readback = (%x)\n", Readback));
> +
> + if (Readback & B_ACPI_IO_OC_WDT_CTL_FAILURE_STS) {
> + DEBUG ((DEBUG_INFO, "(Wdt) Status = FAILURE\n"));
> + return V_ACPI_IO_OC_WDT_CTL_STATUS_FAILURE;
> + } else {
> + return V_ACPI_IO_OC_WDT_CTL_STATUS_OK;
> + }
> +}
> +
> +/**
> + Normally, each reboot performed while watchdog runs is considered a
> failure.
> + This function allows platform to perform expected reboots with WDT
> running,
> + without being interpreted as failures.
> + In DXE phase, it is enough to call this function any time before reset.
> + In PEI phase, between calling this function and performing reset,
> ReloadAndStart()
> + must not be called.
> +
> +
> +**/
> +VOID
> +EFIAPI
> +WdtAllowKnownReset (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) AllowKnownReset\n"));
> +
> + mAllowExpectedReset = 1;
> +
> + Readback = IoRead32 (WdtGetAddress ());
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS |
> B_ACPI_IO_OC_WDT_CTL_FORCE_ALL);
> + IoWrite32 (WdtGetAddress (), Readback);
> +}
> +
> +/**
> + Returns information if WDT coverage for the duration of BIOS execution
> + was requested by an OS application
> +
> +
> + @retval TRUE if WDT was requested
> + @retval FALSE if WDT was not requested
> +**/
> +UINT8
> +EFIAPI
> +IsWdtRequired (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtRequired"));
> +
> + Readback = IoRead32 (WdtGetAddress ());
> +
> +
> + if ((Readback & B_ACPI_IO_OC_WDT_CTL_AFTER_POST) != 0) {
> + DEBUG ((DEBUG_INFO, " - yes\n"));
> + return TRUE;
> + } else {
> + DEBUG ((DEBUG_INFO, " - no\n"));
> + return FALSE;
> + }
> +
> +}
> +
> +/**
> + Returns WDT enabled/disabled status.
> +
> +
> + @retval TRUE if WDT is enabled
> + @retval FALSE if WDT is disabled
> +**/
> +UINT8
> +EFIAPI
> +IsWdtEnabled (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtEnabled"));
> +
> + Readback = IoRead32 (WdtGetAddress ());
> +
> +
> + if ((Readback & B_ACPI_IO_OC_WDT_CTL_EN) != 0) {
> + DEBUG ((DEBUG_INFO, " - yes\n"));
> + return TRUE;
> + } else {
> + DEBUG ((DEBUG_INFO, " - no\n"));
> + return FALSE;
> + }
> +
> +}
> +
> +/**
> + Returns WDT locked status.
> +
> +
> + @retval TRUE if WDT is locked
> + @retval FALSE if WDT is unlocked
> +**/
> +UINT8
> +EFIAPI
> +IsWdtLocked (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + DEBUG ((DEBUG_INFO, "(Wdt) IsWdtLocked"));
> +
> + Readback = IoRead32 (WdtGetAddress ());
> +
> +
> + if ((Readback & B_ACPI_IO_OC_WDT_CTL_LCK) != 0) {
> + DEBUG ((DEBUG_INFO, " - yes\n"));
> + return TRUE;
> + } else {
> + DEBUG ((DEBUG_INFO, " - no\n"));
> + return FALSE;
> + }
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib.c
> new file mode 100644
> index 0000000000..8e026b3ab6
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmPmcLib/PmcLib.c
> @@ -0,0 +1,330 @@
> +/** @file
> + PCH PMC Library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/PmcLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <PchReservedResources.h>
> +#include <Register/PchRegsPmc.h>
> +
> +/**
> + Get PCH ACPI base address.
> +
> + @retval Address Address of PWRM base address.
> +**/
> +UINT16
> +PmcGetAcpiBase (
> + VOID
> + )
> +{
> + return PcdGet16 (PcdAcpiBaseAddress);
> +}
> +
> +/**
> + Get PCH PWRM base address.
> +
> + @retval Address Address of PWRM base address.
> +**/
> +UINT32
> +PmcGetPwrmBase (
> + VOID
> + )
> +{
> + return PCH_PWRM_BASE_ADDRESS;
> +}
> +
> +/**
> + This function enables Power Button SMI
> +**/
> +VOID
> +PmcEnablePowerButtonSmi (
> + VOID
> + )
> +{
> + IoOr16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN,
> B_ACPI_IO_PM1_EN_PWRBTN);
> +}
> +
> +/**
> + This function disables Power Button SMI
> +**/
> +VOID
> +PmcDisablePowerButtonSmi (
> + VOID
> + )
> +{
> + IoAnd16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN,
> (UINT16)~B_ACPI_IO_PM1_EN_PWRBTN);
> +}
> +
> +/**
> + This function reads PM Timer Count driven by 3.579545 MHz clock
> +
> + @retval PM Timer Count
> +**/
> +UINT32
> +PmcGetTimerCount (
> + VOID
> + )
> +{
> + return IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_PM1_TMR) &
> B_ACPI_IO_PM1_TMR_VAL;
> +}
> +
> +/**
> + Get Sleep Type that platform has waken from
> +
> + @retval SleepType Sleep Type
> +**/
> +PMC_SLEEP_STATE
> +PmcGetSleepTypeAfterWake (
> + VOID
> + )
> +{
> + UINT16 AcpiBase;
> + UINT32 PmconA;
> +
> + AcpiBase = PmcGetAcpiBase ();
> + PmconA = MmioRead32 (PmcGetPwrmBase () +
> R_PMC_PWRM_GEN_PMCON_A);
> +
> + DEBUG ((DEBUG_INFO, "PWRM_PMCON_A = 0x%x\n", PmconA));
> +
> + //
> + // If Global Reset Status, Power Failure. Host Reset Status bits are set, return
> S5 State
> + //
> + if ((PmconA & (B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS |
> B_PMC_PWRM_GEN_PMCON_A_PWR_FLR |
> B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS)) != 0) {
> + return PmcNotASleepState;
> + }
> +
> + if (IoRead16 (AcpiBase + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_WAK)
> {
> + switch (IoRead16 (AcpiBase + R_ACPI_IO_PM1_CNT) &
> B_ACPI_IO_PM1_CNT_SLP_TYP) {
> + case V_ACPI_IO_PM1_CNT_S0:
> + return PmcInS0State;
> +
> + case V_ACPI_IO_PM1_CNT_S1:
> + return PmcS1SleepState;
> +
> + case V_ACPI_IO_PM1_CNT_S3:
> + return PmcS3SleepState;
> +
> + case V_ACPI_IO_PM1_CNT_S4:
> + return PmcS4SleepState;
> +
> + case V_ACPI_IO_PM1_CNT_S5:
> + return PmcS5SleepState;
> +
> + default:
> + ASSERT (FALSE);
> + return PmcUndefinedState;
> + }
> + } else {
> + return PmcNotASleepState;
> + }
> +}
> +
> +/**
> + Clear PMC Wake Status
> +**/
> +VOID
> +PmcClearWakeStatus (
> + VOID
> + )
> +{
> + IoWrite16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS,
> B_ACPI_IO_PM1_STS_WAK);
> +}
> +
> +/**
> + Check if platform boots after shutdown caused by power button override
> event
> +
> + @retval TRUE Power Button Override occurred in last system boot
> + @retval FALSE Power Button Override didn't occur
> +**/
> +BOOLEAN
> +PmcIsPowerButtonOverrideDetected (
> + VOID
> + )
> +{
> + return ((IoRead16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS) &
> B_ACPI_IO_PM1_STS_PRBTNOR) != 0);
> +}
> +
> +/**
> + This function checks if RTC Power Failure occurred by
> + reading RTC_PWR_FLR bit
> +
> + @retval RTC Power Failure state: TRUE - Battery is always present.
> + FALSE - CMOS is cleared.
> +**/
> +BOOLEAN
> +PmcIsRtcBatteryGood (
> + VOID
> + )
> +{
> + return ((MmioRead8 (PmcGetPwrmBase () +
> R_PMC_PWRM_GEN_PMCON_B) &
> B_PMC_PWRM_GEN_PMCON_B_RTC_PWR_STS) == 0);
> +}
> +
> +/**
> + This function checks if Power Failure occurred by
> + reading PWR_FLR bit
> +
> + @retval Power Failure state
> +**/
> +BOOLEAN
> +PmcIsPowerFailureDetected (
> + VOID
> + )
> +{
> + return ((MmioRead16 (PmcGetPwrmBase () +
> R_PMC_PWRM_GEN_PMCON_A) &
> B_PMC_PWRM_GEN_PMCON_A_PWR_FLR) != 0);
> +}
> +
> +/**
> + This function checks if RTC Power Failure occurred by
> + reading SUS_PWR_FLR bit
> +
> + @retval SUS Power Failure state
> +**/
> +BOOLEAN
> +PmcIsSusPowerFailureDetected (
> + VOID
> + )
> +{
> + return ((MmioRead32 (PmcGetPwrmBase () +
> R_PMC_PWRM_GEN_PMCON_B) &
> B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR) != 0);
> +}
> +
> +/**
> + This function clears Power Failure status (PWR_FLR)
> +**/
> +VOID
> +PmcClearPowerFailureStatus (
> + VOID
> + )
> +{
> + //
> + // Write 1 to clear PWR_FLR
> + // Avoid clearing other W1C bits
> + //
> + MmioAndThenOr8 (
> + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
> + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8),
> + B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8
> + );
> +}
> +
> +/**
> + This function clears Global Reset status (GBL_RST_STS)
> +**/
> +VOID
> +PmcClearGlobalResetStatus (
> + VOID
> + )
> +{
> + //
> + // Write 1 to clear GBL_RST_STS
> + // Avoid clearing other W1C bits
> + //
> + MmioAndThenOr8 (
> + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 3,
> + (UINT8) ~0,
> + B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS >> 24
> + );
> +}
> +
> +/**
> + This function clears Host Reset status (HOST_RST_STS)
> +**/
> +VOID
> +PmcClearHostResetStatus (
> + VOID
> + )
> +{
> + //
> + // Write 1 to clear HOST_RST_STS
> + // Avoid clearing other W1C bits
> + //
> + MmioAndThenOr8 (
> + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
> + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8),
> + B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8
> + );
> +}
> +
> +/**
> + This function clears SUS Power Failure status (SUS_PWR_FLR)
> +**/
> +VOID
> +PmcClearSusPowerFailureStatus (
> + VOID
> + )
> +{
> + //
> + // BIOS clears this bit by writing a '1' to it.
> + // Take care of other fields, so we don't clear them accidentally.
> + //
> + MmioAndThenOr8 (
> + PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 2,
> + (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_MS4V >> 16),
> + B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR >> 16
> + );
> +}
> +
> +/**
> + This function sets state to which platform will get after power is reapplied
> +
> + @param[in] PowerStateAfterG3 0: S0 state (boot)
> + 1: S5/S4 State
> +**/
> +VOID
> +PmcSetPlatformStateAfterPowerFailure (
> + IN UINT8 PowerStateAfterG3
> + )
> +{
> + UINT32 PchPwrmBase;
> +
> + PchPwrmBase = PmcGetPwrmBase ();
> +
> + if (PowerStateAfterG3) {
> + MmioOr8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
> B_PMC_PWRM_GEN_PMCON_A_AFTERG3_EN);
> + } else {
> + MmioAnd8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
> (UINT8)~B_PMC_PWRM_GEN_PMCON_A_AFTERG3_EN);
> + }
> +}
> +
> +/**
> + This function checks if SMI Lock is set
> +
> + @retval SMI Lock state
> +**/
> +BOOLEAN
> +PmcIsSmiLockSet (
> + VOID
> + )
> +{
> + return ((MmioRead8 ((UINTN) (PmcGetPwrmBase () +
> R_PMC_PWRM_GEN_PMCON_B)) &
> B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK) != 0);
> +}
> +
> +/**
> + Check global SMI enable is set
> +
> + @retval TRUE Global SMI enable is set
> + FALSE Global SMI enable is not set
> +**/
> +BOOLEAN
> +PmcIsGblSmiEn (
> + VOID
> + )
> +{
> + return !!(IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_SMI_EN) &
> B_ACPI_IO_SMI_EN_GBL_SMI);
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.
> c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.
> c
> new file mode 100644
> index 0000000000..05557931c2
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib.
> c
> @@ -0,0 +1,41 @@
> +/** @file
> + Pch SATA library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/SataLib.h>
> +#include <Register/PchRegs.h>
> +/**
> + Get SATA controller address that can be passed to the PCI Segment Library
> functions.
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SATA controller address in PCI Segment Library representation
> +**/
> +UINT64
> +GetSataRegBase (
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + return PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + GetSataPcieDeviceNum (SataCtrlIndex),
> + GetSataPcieFunctionNum (SataCtrlIndex),
> + 0
> + );
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibC
> df.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib
> Cdf.c
> new file mode 100644
> index 0000000000..5cec818dd6
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib
> Cdf.c
> @@ -0,0 +1,101 @@
> +/** @file
> + Pch SATA library for CedarFork SouthCluster.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/PchInfoLib.h>
> +#include <PchLimits.h>
> +#include <Register/PchRegsSata.h>
> +#include <Library/SataLib.h>
> +
> +/**
> + Get Maximum Sata Controller Number
> +
> + @param[in] None
> +
> + @retval Maximum Sata Controller Number
> +**/
> +UINT8
> +GetPchMaxSataControllerNum (
> + VOID
> + )
> +{
> + return 3;
> +}
> +
> +/**
> + Get Pch Maximum Sata Port Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval Pch Maximum Sata Port Number
> +**/
> +UINT8
> +GetPchMaxSataPortNum (
> + IN UINT8 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + return 8;
> +}
> +
> +/**
> + Get SATA controller PCIe Device Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SATA controller PCIe Device Number
> +**/
> +UINT8
> +GetSataPcieDeviceNum (
> + IN UINT8 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + if (SataCtrlIndex == SATA_1_CONTROLLER_INDEX) {
> + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_1;
> + } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) {
> + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_2;
> + } else if (SataCtrlIndex == SATA_3_CONTROLLER_INDEX) {
> + return PCI_DEVICE_NUMBER_CDF_PCH_SATA_3;
> + } else {
> + ASSERT (FALSE);
> + return 0;
> + }
> +}
> +
> +/**
> + Get SATA controller PCIe Function Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SATA controller PCIe Function Number
> +**/
> +UINT8
> +GetSataPcieFunctionNum (
> + IN UINT8 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + if (SataCtrlIndex == SATA_1_CONTROLLER_INDEX) {
> + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_1;
> + } else if (SataCtrlIndex == SATA_2_CONTROLLER_INDEX) {
> + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_2;
> + } else if (SataCtrlIndex == SATA_3_CONTROLLER_INDEX) {
> + return PCI_FUNCTION_NUMBER_CDF_PCH_SATA_3;
> + } else {
> + ASSERT (FALSE);
> + return 0;
> + }
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLibC
> nl.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib
> Cnl.c
> new file mode 100644
> index 0000000000..0eca692a74
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmSataLib/SataLib
> Cnl.c
> @@ -0,0 +1,88 @@
> +/** @file
> + Pch SATA library.
> + All function in this library is available for PEI, DXE, and SMM,
> + But do not support UEFI RUNTIME environment call.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <PchLimits.h>
> +#include <Register/PchRegsSata.h>
> +#include <Library/SataLib.h>
> +
> +/**
> + Get Maximum Sata Controller Number
> +
> + @param[in] None
> +
> + @retval Maximum Sata Controller Number
> +**/
> +UINT8
> +GetPchMaxSataControllerNum (
> + VOID
> + )
> +{
> + return 1;
> +}
> +
> +/**
> + Get Pch Maximum Sata Port Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval Pch Maximum Sata Port Number
> +**/
> +UINT8
> +GetPchMaxSataPortNum (
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + if (IsPchLp ()) {
> + return 3;
> + } else {
> + return 8;
> + }
> +}
> +
> +/**
> + Get SATA controller PCIe Device Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SATA controller PCIe Device Number
> +**/
> +UINT8
> +GetSataPcieDeviceNum (
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + return PCI_DEVICE_NUMBER_PCH_SATA;
> +}
> +
> +/**
> + Get SATA controller PCIe Function Number
> +
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SATA controller PCIe Function Number
> +**/
> +UINT8
> +GetSataPcieFunctionNum (
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + return PCI_FUNCTION_NUMBER_PCH_SATA;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
> new file mode 100644
> index 0000000000..22f6fb215f
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
> @@ -0,0 +1,130 @@
> +/** @file
> + The PEI Library Implements OcWdt Support.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Ppi/Wdt.h>
> +#include <Library/PchWdtCommonLib.h>
> +#include <Library/PmcLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/IoLib.h>
> +#include <Register/PchRegsPmc.h>
> +
> +static WDT_PPI mWdtPpi = {
> + WdtReloadAndStart,
> + WdtCheckStatus,
> + WdtDisable,
> + WdtAllowKnownReset,
> + IsWdtRequired,
> + IsWdtEnabled
> +};
> +
> +static EFI_PEI_PPI_DESCRIPTOR mInstallWdtPpi = {
> + (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> + &gWdtPpiGuid,
> + &mWdtPpi
> +};
> +
> +/**
> + Reads PCH registers to check if platform wakes from S3/S4
> +
> + @retval TRUE if platfrom wakes from S3/S4
> + @retval FALSE otherwise
> +**/
> +BOOLEAN
> +IsWakeFromS3S4 (
> + VOID
> + )
> +{
> + PMC_SLEEP_STATE SleepType;
> +
> + SleepType = PmcGetSleepTypeAfterWake ();
> + if ((SleepType == PmcS3SleepState) || (SleepType == PmcS4SleepState)) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +
> +}
> +
> +/**
> + Check for unexpected reset.
> + If there was an unexpected reset, enforces WDT expiration.
> +**/
> +VOID
> +OcWdtResetCheck (
> + VOID
> + )
> +{
> + UINT32 Readback;
> +
> + Readback = IoRead32 (WdtGetAddress ());
> + DEBUG ((DEBUG_INFO, "(WDT) OcWdtResetCheck()\n"));
> +
> + ///
> + /// If there was a WDT expiration, set Failure Status and clear timeout status
> bits
> + /// Timeout status bits are cleared by writing '1'
> + ///
> + if (Readback & (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS |
> B_ACPI_IO_OC_WDT_CTL_NO_ICCSURV_STS)) {
> + DEBUG ((DEBUG_ERROR, "(WDT) Expiration detected.\n", Readback));
> + Readback |= B_ACPI_IO_OC_WDT_CTL_FAILURE_STS;
> + Readback |= (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS |
> B_ACPI_IO_OC_WDT_CTL_NO_ICCSURV_STS);
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS);
> + } else {
> + ///
> + /// If there was unexpected reset but no WDT expiration and no resume
> from S3/S4,
> + /// clear unexpected reset status and enforce expiration. This is to inform
> Firmware
> + /// which has no access to unexpected reset status bit, that something
> went wrong.
> + ///
> + if ((Readback & B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS)
> && !IsWakeFromS3S4()) {
> + if (PcdGetBool (PcdOcEnableWdtforDebug)) {
> + DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected and
> ignored.\n"));
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS |
> B_ACPI_IO_OC_WDT_CTL_UNXP_RESET_STS);
> + Readback |= (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS |
> B_ACPI_IO_OC_WDT_CTL_NO_ICCSURV_STS);
> + } else {
> + DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected. Enforcing
> Wdt expiration.\n"));
> + WdtReloadAndStart (1);
> + ///
> + /// wait for reboot caused by WDT expiration
> + ///
> + CpuDeadLoop ();
> + }
> + } else {
> + ///
> + /// No WDT expiration and no unexpected reset - clear Failure status
> + ///
> + DEBUG ((DEBUG_INFO, "(WDT) Status OK.\n", Readback));
> + Readback &= ~(B_ACPI_IO_OC_WDT_CTL_FAILURE_STS);
> + Readback |= (B_ACPI_IO_OC_WDT_CTL_ICCSURV_STS |
> B_ACPI_IO_OC_WDT_CTL_NO_ICCSURV_STS);
> + }
> + }
> +
> + IoWrite32 (WdtGetAddress (), Readback);
> +
> + return;
> +}
> +
> +/**
> + This function install WDT PPI
> +
> + @retval EFI_STATUS Results of the installation of the WDT PPI
> +**/
> +EFI_STATUS
> +EFIAPI
> +OcWdtInit (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = PeiServicesInstallPpi (&mInstallWdtPpi);
> + ASSERT_EFI_ERROR (Status);
> +
> + return Status;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.c
> new file mode 100644
> index 0000000000..182218ffcf
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdt
> LibNull.c
> @@ -0,0 +1,23 @@
> +/** @file
> + The Null PEI Library Implements OcWdt Support.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +
> +/**
> + This function install WDT PPI
> +
> + @retval EFI_STATUS Results of the installation of the WDT PPI
> +**/
> +EFI_STATUS
> +EFIAPI
> +OcWdtInit (
> + VOID
> + )
> +{
> + return EFI_SUCCESS;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMem
> PrintPolicy.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMem
> PrintPolicy.c
> new file mode 100644
> index 0000000000..bd1e2711da
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMem
> PrintPolicy.c
> @@ -0,0 +1,307 @@
> +/** @file
> + Print whole PCH_PREMEM_POLICY_PPI
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PeiPchPolicyLibrary.h"
> +
> +/**
> + Print PCH_GENERAL_PREMEM_CONFIG and serial out.
> +
> + @param[in] PchGeneralPreMemConfig Pointer to a
> PCH_GENERAL_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintGeneralPreMemConfig (
> + IN CONST PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH General PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Port80Route= %x\n",
> PchGeneralPreMemConfig->Port80Route));
> +}
> +
> +/**
> + Print PCH_DCI_PREMEM_CONFIG and serial out.
> +
> + @param[in] DciPreMemConfig Pointer to a
> PCH_DCI_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintDciPreMemConfig (
> + IN CONST PCH_DCI_PREMEM_CONFIG *DciPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH DCI PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, "PlatformDebugConsent = %x\n",
> DciPreMemConfig->PlatformDebugConsent));
> + DEBUG ((DEBUG_INFO, "DciUsb3TypecUfpDbg = %x\n",
> DciPreMemConfig->DciUsb3TypecUfpDbg));
> +}
> +
> +/**
> + Print PCH_WDT_PREMEM_CONFIG and serial out.
> +
> + @param[in] WdtPreMemConfig Pointer to a
> PCH_WDT_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintWdtPreMemConfig (
> + IN CONST PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH WDT PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, "DisableAndLock= %x\n",
> WdtPreMemConfig->DisableAndLock));
> +}
> +
> +/**
> + Print PCH_TRACE_HUB_CONFIG and serial out.
> +
> + @param[in] TraceHubConfig Pointer to a
> PCH_TRACE_HUB_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintTraceHubPreMemConfig (
> + IN CONST PCH_TRACE_HUB_PREMEM_CONFIG
> *PchTraceHubPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH TraceHub PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, "EnableMode= %x\n",
> PchTraceHubPreMemConfig->EnableMode));
> + DEBUG ((DEBUG_INFO, "MemReg0Size= %x\n",
> PchTraceHubPreMemConfig->MemReg0Size));
> + DEBUG ((DEBUG_INFO, "MemReg1Size= %x\n",
> PchTraceHubPreMemConfig->MemReg1Size));
> +}
> +
> +/**
> + Print PCH_SMBUS_CONFIG and serial out.
> +
> + @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintSmbusPreMemConfig (
> + IN CONST PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH SMBUS PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Enable= %x\n", SmbusPreMemConfig->Enable));
> + DEBUG ((DEBUG_INFO, " ArpEnable= %x\n",
> SmbusPreMemConfig->ArpEnable));
> + DEBUG ((DEBUG_INFO, " DynamicPowerGating= %x\n",
> SmbusPreMemConfig->DynamicPowerGating));
> + DEBUG ((DEBUG_INFO, " SpdWriteDisable= %x\n",
> SmbusPreMemConfig->SpdWriteDisable));
> + DEBUG ((DEBUG_INFO, " SmbAlertEnable= %x\n",
> SmbusPreMemConfig->SmbAlertEnable));
> + DEBUG ((DEBUG_INFO, " SmbusIoBase= %x\n",
> SmbusPreMemConfig->SmbusIoBase));
> + DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses= %x\n",
> SmbusPreMemConfig->NumRsvdSmbusAddresses));
> + DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable= {"));
> + for (Index = 0; Index < SmbusPreMemConfig->NumRsvdSmbusAddresses;
> ++Index) {
> + DEBUG ((DEBUG_INFO, " %02xh",
> SmbusPreMemConfig->RsvdSmbusAddressTable[Index]));
> + }
> + DEBUG ((DEBUG_INFO, " }\n"));
> +}
> +
> +/**
> + Print PCH_LPC_PREMEM_CONFIG and serial out.
> +
> + @param[in] LpcPreMemConfig Pointer to a
> PCH_LPC_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintLpcPreMemConfig (
> + IN CONST PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH LPC PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, "EnhancePort8xhDecoding= %x\n",
> LpcPreMemConfig->EnhancePort8xhDecoding));
> +}
> +
> +/**
> + Print PCH_HSIO_PCIE_PREMEM_CONFIG and serial out.
> +
> + @param[in] HsioPciePreMemConfig Pointer to a
> PCH_HSIO_PCIE_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintHsioPciePreMemConfig (
> + IN CONST PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ HSIO PCIE PreMem Config
> ------------------\n"));
> + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtleEnable= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtle= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioRxSetCtle));
> + DEBUG ((DEBUG_INFO, " RootPort[%d]
> HsioTxGen1DownscaleAmpEnable= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmp= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " RootPort[%d]
> HsioTxGen2DownscaleAmpEnable= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmp= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " RootPort[%d]
> HsioTxGen3DownscaleAmpEnable= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmp= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmphEnable= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmph= %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5Enable=
> %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0Enable=
> %x\n", Index,
> HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0= %x\n",
> Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0));
> + }
> +}
> +
> +/**
> + Print PCH_HSIO_SATA_PREMEM_CONFIG and serial out.
> +
> + @param[in] SataCtrlIndex SATA controller index
> + @param[in] HsioSataPreMemConfig Pointer to a
> PCH_HSIO_SATA_PREMEM_CONFIG that provides the platform setting
> +**/
> +VOID
> +PchPrintHsioSataPreMemConfig (
> + IN UINT8 SataCtrlIndex,
> + IN CONST PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "---------------- HSIO SATA PreMem Config for
> controller %d ----------------\n", SataCtrlIndex));
> + for (Index = 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++) {
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioRxGen1EqBoostMagEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioRxGen2EqBoostMagEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioRxGen3EqBoostMagEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioTxGen1DownscaleAmpEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmpEnable)
> );
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioTxGen2DownscaleAmpEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmpEnable)
> );
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d]
> HsioTxGen3DownscaleAmpEnable= %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmpEnable)
> );
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph= %x\n",
> Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph= %x\n",
> Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable=
> %x\n", Index,
> HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph= %x\n",
> Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph));
> + }
> +}
> +
> +/**
> + Print PCH_PCIE_RP_PREMEM_CONFIG and serial out.
> +
> + @param[in] PcieRpPreMemConfig Pointer to a
> PCH_PCIE_RP_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintPcieRpPreMemConfig (
> + IN CONST PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig
> + )
> +{
> + UINT32 Index;
> + DEBUG ((DEBUG_INFO, "------------------ PCH PCIe RP PreMem Config
> ------------------\n"));
> +
> + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " Port[%d] RpEnabled= %x\n", Index,
> (PcieRpPreMemConfig->RpEnabledMask & (UINT32) (1 << Index)) != 0 ));
> + }
> + DEBUG ((DEBUG_INFO, " PcieImrEnabled= %x\n",
> PcieRpPreMemConfig->PcieImrEnabled));
> + DEBUG ((DEBUG_INFO, " PcieImrSize= %d MB\n",
> PcieRpPreMemConfig->PcieImrSize));
> + DEBUG ((DEBUG_INFO, " ImrRpSelection= %d\n",
> PcieRpPreMemConfig->ImrRpSelection));
> +}
> +
> +/**
> + Print PCH_HDAUDIO_PREMEM_CONFIG and serial out.
> +
> + @param[in] LpcPreMemConfig Pointer to a
> PCH_HDAUDIO_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintHdAudioPreMemConfig (
> + IN CONST PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ HD Audio PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Enable= %x\n", HdaPreMemConfig->Enable));
> +}
> +
> +/**
> + Print PCH_ISH_PREMEM_CONFIG and serial out.
> +
> + @param[in] IshPreMemConfig Pointer to a
> PCH_ISH_PREMEM_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintIshPreMemConfig (
> + IN CONST PCH_ISH_PREMEM_CONFIG *IshPreMemConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ ISH PreMem Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Enable= %x\n", IshPreMemConfig->Enable));
> +}
> +
> +
> +/**
> + Print whole PCH_POLICY_PPI and serial out.
> +
> + @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
> +
> +**/
> +VOID
> +EFIAPI
> +PchPreMemPrintPolicyPpi (
> + IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
> + )
> +{
> + DEBUG_CODE_BEGIN ();
> + EFI_STATUS Status;
> + PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
> + PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
> + PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
> + PCH_TRACE_HUB_PREMEM_CONFIG *PchTraceHubPreMemConfig;
> + PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
> + PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
> + PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
> + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
> + PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
> + PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig;
> + PCH_ISH_PREMEM_CONFIG *IshPreMemConfig;
> + UINT8 SataCtrlIndex;
> +
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gDciPreMemConfigGuid, (VOID *) &DciPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gWatchDogPreMemConfigGuid, (VOID *) &WdtPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gPchTraceHubPreMemConfigGuid, (VOID *) &PchTraceHubPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gSmbusPreMemConfigGuid, (VOID *) &SmbusPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gPcieRpPreMemConfigGuid, (VOID *) &PcieRpPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gHdAudioPreMemConfigGuid, (VOID *) &HdaPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gIshPreMemConfigGuid, (VOID *) &IshPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> + DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy Start
> ------------------------\n"));
> + DEBUG ((DEBUG_INFO, " Revision= %x\n",
> SiPreMemPolicyPpi->TableHeader.Header.Revision));
> +
> + PchPrintGeneralPreMemConfig (PchGeneralPreMemConfig);
> + PchPrintDciPreMemConfig (DciPreMemConfig);
> + PchPrintWdtPreMemConfig (WdtPreMemConfig);
> + PchPrintTraceHubPreMemConfig (PchTraceHubPreMemConfig);
> + PchPrintSmbusPreMemConfig (SmbusPreMemConfig);
> + PchPrintLpcPreMemConfig (LpcPreMemConfig);
> + PchPrintHsioPciePreMemConfig (HsioPciePreMemConfig);
> + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum ();
> SataCtrlIndex++) {
> + HsioSataPreMemConfig = GetPchHsioSataPreMemConfig
> (SiPreMemPolicyPpi, SataCtrlIndex);
> + PchPrintHsioSataPreMemConfig (SataCtrlIndex, HsioSataPreMemConfig);
> + }
> + PchPrintPcieRpPreMemConfig (PcieRpPreMemConfig);
> + PchPrintHdAudioPreMemConfig (HdaPreMemConfig);
> + PchPrintIshPreMemConfig (IshPreMemConfig);
> +
> + DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy End
> --------------------------\n"));
> + DEBUG_CODE_END ();
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPoli
> cy.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPoli
> cy.c
> new file mode 100644
> index 0000000000..d9005b50ef
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPoli
> cy.c
> @@ -0,0 +1,778 @@
> +/** @file
> + Print whole PCH_POLICY_PPI
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PeiPchPolicyLibrary.h"
> +#include <Private/PchHsio.h>
> +
> +/**
> + Print USB_CONFIG and serial out.
> +
> + @param[in] UsbConfig Pointer to a USB_CONFIG that provides the
> platform setting
> +
> +**/
> +VOID
> +PchPrintUsbConfig (
> + IN CONST USB_CONFIG *UsbConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH USB Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " EnableComplianceMode = %x\n",
> UsbConfig->EnableComplianceMode));
> + DEBUG ((DEBUG_INFO, " PdoProgramming = %x\n",
> UsbConfig->PdoProgramming));
> + DEBUG ((DEBUG_INFO, " OverCurrentEnable = %x\n",
> UsbConfig->OverCurrentEnable));
> + DEBUG ((DEBUG_INFO, " XhciOcLock = %x\n",
> UsbConfig->XhciOcLock));
> + DEBUG ((DEBUG_INFO, " Usb2PhySusPgEnable = %x\n",
> UsbConfig->Usb2PhySusPgEnable));
> +
> + for (Index = 0; Index < GetPchUsb2MaxPhysicalPortNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled = %x\n", Index,
> UsbConfig->PortUsb20[Index].Enable));
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin = OC%x\n", Index,
> UsbConfig->PortUsb20[Index].OverCurrentPin));
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset = %x\n", Index,
> UsbConfig->PortUsb20[Index].Afe.Petxiset));
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset = %x\n", Index,
> UsbConfig->PortUsb20[Index].Afe.Txiset));
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp = %x\n", Index,
> UsbConfig->PortUsb20[Index].Afe.Predeemp));
> + DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit = %x\n", Index,
> UsbConfig->PortUsb20[Index].Afe.Pehalfbit));
> + }
> +
> + for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled = %x\n",
> Index, UsbConfig->PortUsb30[Index].Enable));
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin =
> OC%x\n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin));
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable =
> %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable));
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph = %x\n",
> Index, UsbConfig->PortUsb30[Index].HsioTxDeEmph));
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable =
> %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable));
> + DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp =
> %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp));
> +
> + DEBUG ((DEBUG_INFO, "
> PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfgEnable = %x\n", Index,
> UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffsetCfgEnable));
> + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioCtrlAdaptOffsetCfg
> = %x\n", Index,
> UsbConfig->PortUsb30HsioRx[Index].HsioCtrlAdaptOffsetCfg));
> + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelNEnable
> = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelNEnable));
> + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelN
> = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelN));
> + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelPEnable
> = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelPEnable));
> + DEBUG ((DEBUG_INFO, " PortUsb30HsioRx[%d].HsioFilterSelP
> = %x\n", Index, UsbConfig->PortUsb30HsioRx[Index].HsioFilterSelP));
> + DEBUG ((DEBUG_INFO, "
> PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnResEnable = %x\n", Index,
> UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpDwnResEnable));
> + DEBUG ((DEBUG_INFO, "
> PortUsb30HsioRx[%d].HsioOlfpsCfgPullUpDwnRes = %x\n", Index,
> UsbConfig->PortUsb30HsioRx[Index].HsioOlfpsCfgPullUpDwnRes));
> + }
> +
> + DEBUG ((DEBUG_INFO, " XdciConfig.Enable= %x\n",
> UsbConfig->XdciConfig.Enable));
> +
> +}
> +
> +/**
> + Print PCH_PCIE_CONFIG and serial out.
> +
> + @param[in] PcieConfig Pointer to a PCH_PCIE_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintPcieConfig (
> + IN CONST PCH_PCIE_CONFIG *PcieConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config ------------------\n"));
> + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug= %x\n", Index,
> PcieConfig->RootPort[Index].HotPlug));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci= %x\n", Index,
> PcieConfig->RootPort[Index].PmSci));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync= %x\n", Index,
> PcieConfig->RootPort[Index].ExtSync));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect= %x\n", Index,
> PcieConfig->RootPort[Index].ClkReqDetect));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport=
> %x\n", Index, PcieConfig->RootPort[Index].UnsupportedRequestReport));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport= %x\n", Index,
> PcieConfig->RootPort[Index].FatalErrorReport));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport= %x\n", Index,
> PcieConfig->RootPort[Index].NoFatalErrorReport));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport= %x\n",
> Index, PcieConfig->RootPort[Index].CorrectableErrorReport));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError= %x\n",
> Index, PcieConfig->RootPort[Index].SystemErrorOnFatalError));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError=
> %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnNonFatalError));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError=
> %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnCorrectableError));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload= %x\n", Index,
> PcieConfig->RootPort[Index].MaxPayload));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotImplemented= %x\n", Index,
> PcieConfig->RootPort[Index].SlotImplemented));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled= %x\n", Index,
> PcieConfig->RootPort[Index].AcsEnabled));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] PtmEnabled= %x\n", Index,
> PcieConfig->RootPort[Index].PtmEnabled));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting= %x\n",
> Index, PcieConfig->RootPort[Index].AdvancedErrorReporting));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing= %x\n",
> Index, PcieConfig->RootPort[Index].TransmitterHalfSwing));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed= %x\n", Index,
> PcieConfig->RootPort[Index].PcieSpeed));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method= %x\n", Index,
> PcieConfig->RootPort[Index].Gen3EqPh3Method));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber= %x\n", Index,
> PcieConfig->RootPort[Index].PhysicalSlotNumber));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout= %x\n", Index,
> PcieConfig->RootPort[Index].CompletionTimeout));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm= %x\n", Index,
> PcieConfig->RootPort[Index].Aspm));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates= %x\n", Index,
> PcieConfig->RootPort[Index].L1Substates));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable= %x\n", Index,
> PcieConfig->RootPort[Index].LtrEnable));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock= %x\n", Index,
> PcieConfig->RootPort[Index].LtrConfigLock));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency= %x\n",
> Index, PcieConfig->RootPort[Index].LtrMaxSnoopLatency));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency= %x\n",
> Index, PcieConfig->RootPort[Index].LtrMaxNoSnoopLatency));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode=
> %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMode));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier=
> %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMultiplier));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue=
> %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideValue));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode=
> %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMode));
> + DEBUG ((DEBUG_INFO, " RootPort[%d]
> NonSnoopLatencyOverrideMultiplier= %x\n", Index,
> PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue=
> %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideValue));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] ForceLtrOverride= %x\n", Index,
> PcieConfig->RootPort[Index].ForceLtrOverride));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] DetectTimeoutMs= %x\n", Index,
> PcieConfig->RootPort[Index].DetectTimeoutMs));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale= %x\n", Index,
> PcieConfig->RootPort[Index].SlotPowerLimitScale));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue= %x\n", Index,
> PcieConfig->RootPort[Index].SlotPowerLimitValue));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp= %x\n", Index,
> PcieConfig->RootPort[Index].Uptp));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp= %x\n", Index,
> PcieConfig->RootPort[Index].Dptp));
> + DEBUG ((DEBUG_INFO, " RootPort[%d] EnableCpm= %x\n", Index,
> PcieConfig->RootPort[Index].EnableCpm));
> +
> + }
> + for (Index = 0; Index < GetPchMaxPcieClockNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " Clock[%d] Usage= %x\n", Index,
> PcieConfig->PcieClock[Index].Usage));
> + DEBUG ((DEBUG_INFO, " Clock[%d] ClkReq= %x\n", Index,
> PcieConfig->PcieClock[Index].ClkReq));
> + }
> + for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) {
> + DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] = %x\n", Index,
> PcieConfig->SwEqCoeffList[Index].Cm));
> + DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] = %x\n", Index,
> PcieConfig->SwEqCoeffList[Index].Cp));
> + }
> + DEBUG ((DEBUG_INFO, " EnablePort8xhDecode= %x\n",
> PcieConfig->EnablePort8xhDecode));
> + DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex= %x\n",
> PcieConfig->PchPciePort8xhDecodePortIndex));
> + DEBUG ((DEBUG_INFO, " DisableRootPortClockGating= %x\n",
> PcieConfig->DisableRootPortClockGating));
> + DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite= %x\n",
> PcieConfig->EnablePeerMemoryWrite));
> + DEBUG ((DEBUG_INFO, " ComplianceTestMode= %x\n",
> PcieConfig->ComplianceTestMode));
> + DEBUG ((DEBUG_INFO, " RpFunctionSwap= %x\n",
> PcieConfig->RpFunctionSwap));
> + DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr= %x\n",
> PcieConfig->PcieDeviceOverrideTablePtr));
> +}
> +
> +/**
> + Print PCH_SATA_CONFIG and serial out.
> +
> + @param[in] SataCtrlIndex SATA controller index
> + @param[in] SataConfig Pointer to a PCH_SATA_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintSataConfig (
> + IN UINT32 SataCtrlIndex,
> + IN CONST PCH_SATA_CONFIG *SataConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "--------------- PCH SATA Config for controller %d
> -----------\n", SataCtrlIndex));
> + DEBUG ((DEBUG_INFO, " Enable= %x\n", SataConfig->Enable));
> + DEBUG ((DEBUG_INFO, " SataMode= %x\n", SataConfig->SataMode));
> +
> + for (Index = 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++) {
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled= %x\n", Index,
> SataConfig->PortSettings[Index].Enable));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug= %x\n", Index,
> SataConfig->PortSettings[Index].HotPlug));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw= %x\n", Index,
> SataConfig->PortSettings[Index].InterlockSw));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] External= %x\n", Index,
> SataConfig->PortSettings[Index].External));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp= %x\n", Index,
> SataConfig->PortSettings[Index].SpinUp));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive= %x\n", Index,
> SataConfig->PortSettings[Index].SolidStateDrive));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp= %x\n", Index,
> SataConfig->PortSettings[Index].DevSlp));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig= %x\n", Index,
> SataConfig->PortSettings[Index].EnableDitoConfig));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal= %x\n", Index,
> SataConfig->PortSettings[Index].DmVal));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal= %x\n", Index,
> SataConfig->PortSettings[Index].DitoVal));
> + DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd= %x\n", Index,
> SataConfig->PortSettings[Index].ZpOdd));
> + }
> +
> + DEBUG ((DEBUG_INFO, " RaidDeviceId= %x\n",
> SataConfig->Rst.RaidDeviceId));
> + DEBUG ((DEBUG_INFO, " Sata interrupt mode = %x\n",
> SataConfig->Rst.SataRstInterrupt));
> + DEBUG ((DEBUG_INFO, " Raid0= %x\n", SataConfig->Rst.Raid0));
> + DEBUG ((DEBUG_INFO, " Raid1= %x\n", SataConfig->Rst.Raid1));
> + DEBUG ((DEBUG_INFO, " Raid10= %x\n", SataConfig->Rst.Raid10));
> + DEBUG ((DEBUG_INFO, " Raid5= %x\n", SataConfig->Rst.Raid5));
> + DEBUG ((DEBUG_INFO, " Irrt= %x\n", SataConfig->Rst.Irrt));
> + DEBUG ((DEBUG_INFO, " OromUiBanner= %x\n",
> SataConfig->Rst.OromUiBanner));
> + DEBUG ((DEBUG_INFO, " OromUiDelay= %x\n",
> SataConfig->Rst.OromUiDelay));
> + DEBUG ((DEBUG_INFO, " HddUnlock= %x\n", SataConfig->Rst.HddUnlock));
> + DEBUG ((DEBUG_INFO, " LedLocate= %x\n", SataConfig->Rst.LedLocate));
> + DEBUG ((DEBUG_INFO, " IrrtOnly= %x\n", SataConfig->Rst.IrrtOnly));
> + DEBUG ((DEBUG_INFO, " SmartStorage= %x\n",
> SataConfig->Rst.SmartStorage));
> + DEBUG ((DEBUG_INFO, " LegacyOrom= %x\n",
> SataConfig->Rst.LegacyOrom));
> + DEBUG ((DEBUG_INFO, " OptaneMemory= %x\n",
> SataConfig->Rst.OptaneMemory));
> + DEBUG ((DEBUG_INFO, " CpuAttachedStorage= %x\n",
> SataConfig->Rst.CpuAttachedStorage));
> +
> + DEBUG ((DEBUG_INFO, " SpeedSupport= %x\n", SataConfig->SpeedLimit));
> + DEBUG ((DEBUG_INFO, " EsataSpeedLimit= %x\n",
> SataConfig->EsataSpeedLimit));
> + DEBUG ((DEBUG_INFO, " LedEnable= %x\n", SataConfig->LedEnable));
> + DEBUG ((DEBUG_INFO, " TestMode= %x\n", SataConfig->TestMode));
> + DEBUG ((DEBUG_INFO, " SalpSupport= %x\n", SataConfig->SalpSupport));
> + DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n",
> SataConfig->PwrOptEnable));
> +
> + for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
> + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable =
> %x\n", Index, SataConfig->RstPcieStorageRemap[Index].Enable));
> + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort
> = %x\n", Index,
> SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort));
> + DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay
> = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay));
> + }
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T1M %x\n",
> SataConfig->ThermalThrottling.P0T1M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T2M %x\n",
> SataConfig->ThermalThrottling.P0T2M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0T3M %x\n",
> SataConfig->ThermalThrottling.P0T3M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDisp %x\n",
> SataConfig->ThermalThrottling.P0TDisp));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0Tinact %x\n",
> SataConfig->ThermalThrottling.P0Tinact));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P0TDispFinit %x\n",
> SataConfig->ThermalThrottling.P0TDispFinit));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T1M %x\n",
> SataConfig->ThermalThrottling.P1T1M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T2M %x\n",
> SataConfig->ThermalThrottling.P1T2M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1T3M %x\n",
> SataConfig->ThermalThrottling.P1T3M));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDisp %x\n",
> SataConfig->ThermalThrottling.P1TDisp));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1Tinact %x\n",
> SataConfig->ThermalThrottling.P1Tinact));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling P1TDispFinit %x\n",
> SataConfig->ThermalThrottling.P1TDispFinit));
> + DEBUG ((DEBUG_INFO, " ThermalThrottling SuggestedSetting %x\n",
> SataConfig->ThermalThrottling.SuggestedSetting));
> +}
> +
> +/**
> + Print PCH_IOAPIC_CONFIG and serial out.
> +
> + @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintIoApicConfig (
> + IN CONST PCH_IOAPIC_CONFIG *IoApicConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " IoApicEntry24_119= %x\n",
> IoApicConfig->IoApicEntry24_119));
> + DEBUG ((DEBUG_INFO, " Enable8254ClockGating= %x\n",
> IoApicConfig->Enable8254ClockGating));
> + DEBUG ((DEBUG_INFO, " Enable8254ClockGatingOnS3= %x\n",
> IoApicConfig->Enable8254ClockGatingOnS3));
> + DEBUG ((DEBUG_INFO, " IoApicId= %x\n", IoApicConfig->IoApicId));
> +}
> +
> +/**
> + Print PCH_LOCK_DOWN_CONFIG and serial out.
> +
> + @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG
> that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintLockDownConfig (
> + IN CONST PCH_LOCK_DOWN_CONFIG *LockDownConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH Lock Down Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " GlobalSmi= %x\n", LockDownConfig->GlobalSmi));
> + DEBUG ((DEBUG_INFO, " BiosInterface= %x\n",
> LockDownConfig->BiosInterface));
> + DEBUG ((DEBUG_INFO, " RtcMemoryLock= %x\n",
> LockDownConfig->RtcMemoryLock));
> + DEBUG ((DEBUG_INFO, " BiosLock= %x\n", LockDownConfig->BiosLock));
> + DEBUG ((DEBUG_INFO, " UnlockGpioPads= %x\n",
> LockDownConfig->UnlockGpioPads));
> +}
> +
> +/**
> + Print PCH_HDAUDIO_CONFIG and serial out.
> +
> + @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintHdAudioConfig (
> + IN CONST PCH_HDAUDIO_CONFIG *HdaConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " DSP Enable = %x\n",
> HdaConfig->DspEnable));
> + DEBUG ((DEBUG_INFO, " DSP UAA Compliance = %x\n",
> HdaConfig->DspUaaCompliance));
> + DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect = %x\n",
> HdaConfig->IDispCodecDisconnect));
> + DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme));
> + DEBUG ((DEBUG_INFO, " Codec Sx Wake Capability = %x\n",
> HdaConfig->CodecSxWakeCapability));
> + DEBUG ((DEBUG_INFO, " VC Type = %x\n",
> HdaConfig->VcType));
> + DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n",
> HdaConfig->HdAudioLinkFrequency));
> + DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n",
> HdaConfig->IDispLinkFrequency));
> + DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n",
> HdaConfig->IDispLinkTmode));
> + DEBUG ((DEBUG_INFO, " Audio Link: HDA Link = %x\n",
> HdaConfig->AudioLinkHda));
> + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#0 = %x\n",
> HdaConfig->AudioLinkDmic0));
> + DEBUG ((DEBUG_INFO, " Audio Link: DMIC#1 = %x\n",
> HdaConfig->AudioLinkDmic1));
> + DEBUG ((DEBUG_INFO, " Audio Link: SSP#0 = %x\n",
> HdaConfig->AudioLinkSsp0));
> + DEBUG ((DEBUG_INFO, " Audio Link: SSP#1 = %x\n",
> HdaConfig->AudioLinkSsp1));
> + DEBUG ((DEBUG_INFO, " Audio Link: SSP#2 = %x\n",
> HdaConfig->AudioLinkSsp1));
> + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#1 = %x\n",
> HdaConfig->AudioLinkSndw1));
> + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#2 = %x\n",
> HdaConfig->AudioLinkSndw2));
> + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#3 = %x\n",
> HdaConfig->AudioLinkSndw3));
> + DEBUG ((DEBUG_INFO, " Audio Link: SoundWire#4 = %x\n",
> HdaConfig->AudioLinkSndw4));
> + DEBUG ((DEBUG_INFO, " SoundWire Buffer RCOMP = %x\n",
> HdaConfig->SndwBufferRcomp));
> + DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n",
> HdaConfig->ResetWaitTimer));
> + DEBUG ((DEBUG_INFO, " VerbTableEntryNum = %x\n",
> HdaConfig->VerbTableEntryNum));
> + DEBUG ((DEBUG_INFO, " VerbTablePtr = %x\n",
> HdaConfig->VerbTablePtr));
> +}
> +
> +/**
> + Print PCH_PM_CONFIG and serial out.
> +
> + @param[in] PmConfig Pointer to a PCH_PM_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintPmConfig (
> + IN CONST PCH_PM_CONFIG *PmConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH PM Config ------------------\n"));
> +
> + DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis = %x\n",
> PmConfig->WakeConfig.PmeB0S5Dis));
> + DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride = %x\n",
> PmConfig->WakeConfig.WolEnableOverride));
> + DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx = %x\n",
> PmConfig->WakeConfig.LanWakeFromDeepSx));
> + DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx = %x\n",
> PmConfig->WakeConfig.PcieWakeFromDeepSx));
> + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable = %x\n",
> PmConfig->WakeConfig.WoWlanEnable));
> + DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable = %x\n",
> PmConfig->WakeConfig.WoWlanDeepSxEnable));
> +
> + DEBUG ((DEBUG_INFO, " PchDeepSxPol = %x\n",
> PmConfig->PchDeepSxPol));
> + DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert = %x\n",
> PmConfig->PchSlpS3MinAssert));
> + DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert = %x\n",
> PmConfig->PchSlpS4MinAssert));
> + DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert = %x\n",
> PmConfig->PchSlpSusMinAssert));
> + DEBUG ((DEBUG_INFO, " PchSlpAMinAssert = %x\n",
> PmConfig->PchSlpAMinAssert));
> + DEBUG ((DEBUG_INFO, " LpcClockRun = %x\n",
> PmConfig->LpcClockRun));
> + DEBUG ((DEBUG_INFO, " SlpStrchSusUp = %x\n",
> PmConfig->SlpStrchSusUp));
> + DEBUG ((DEBUG_INFO, " SlpLanLowDc = %x\n",
> PmConfig->SlpLanLowDc));
> + DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n",
> PmConfig->PwrBtnOverridePeriod));
> + DEBUG ((DEBUG_INFO, " DisableEnergyReport = %x\n",
> PmConfig->DisableEnergyReport));
> + DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown = %x\n",
> PmConfig->DisableDsxAcPresentPulldown));
> + DEBUG ((DEBUG_INFO, " PchPwrCycDur = %x\n",
> PmConfig->PchPwrCycDur));
> + DEBUG ((DEBUG_INFO, " PciePllSsc = %x\n",
> PmConfig->PciePllSsc));
> + DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n",
> PmConfig->DisableNativePowerButton));
> + DEBUG ((DEBUG_INFO, " SlpS0Enabled = %x\n",
> PmConfig->SlpS0Enable));
> + DEBUG ((DEBUG_INFO, " MeWakeSts = %x\n",
> PmConfig->MeWakeSts));
> + DEBUG ((DEBUG_INFO, " WolOvrWkSts = %x\n",
> PmConfig->WolOvrWkSts));
> + DEBUG ((DEBUG_INFO, " EnableTcoTimer = %x\n",
> PmConfig->EnableTcoTimer));
> + DEBUG ((DEBUG_INFO, " VrAlert = %x\n",
> PmConfig->VrAlert));
> + DEBUG ((DEBUG_INFO, " PowerButtonDebounce = %x\n",
> PmConfig->PowerButtonDebounce));
> + DEBUG ((DEBUG_INFO, " SlpS0VmRuntimeControl = %x\n",
> PmConfig->SlpS0VmRuntimeControl));
> + DEBUG ((DEBUG_INFO, " SlpS0Vm070VSupport = %x\n",
> PmConfig->SlpS0Vm070VSupport));
> + DEBUG ((DEBUG_INFO, " SlpS0Vm075VSupport = %x\n",
> PmConfig->SlpS0Vm075VSupport));
> + DEBUG ((DEBUG_INFO, " SlpS0Override = %x\n",
> PmConfig->SlpS0Override));
> + DEBUG ((DEBUG_INFO, " SlpS0DisQForDebug = %x\n",
> PmConfig->SlpS0DisQForDebug));
> + DEBUG ((DEBUG_INFO, " PsOnEnable = %x\n",
> PmConfig->PsOnEnable));
> + DEBUG ((DEBUG_INFO, " CpuC10GatePinEnable = %x\n",
> PmConfig->CpuC10GatePinEnable));
> + DEBUG ((DEBUG_INFO, " PmcDbgMsgEn = %x\n",
> PmConfig->PmcDbgMsgEn));
> + DEBUG ((DEBUG_INFO, " ModPhySusPgEnable = %x\n",
> PmConfig->ModPhySusPgEnable));
> + DEBUG ((DEBUG_INFO, " SlpS0WithGbeSupport = %x\n",
> PmConfig->SlpS0WithGbeSupport));
> +}
> +
> +/**
> + Print PCH_DMI_CONFIG and serial out.
> +
> + @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintDmiConfig (
> + IN CONST PCH_DMI_CONFIG *DmiConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n",
> DmiConfig->PwrOptEnable));
> + DEBUG ((DEBUG_INFO, " DmiAspmCtrl= %x\n", DmiConfig->DmiAspmCtrl));
> +}
> +/**
> + Print PCH_LPC_SIRQ_CONFIG and serial out.
> +
> + @param[in] SerialIrqConfig Pointer to a PCH_LPC_SIRQ_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintSerialIrqConfig (
> + IN CONST PCH_LPC_SIRQ_CONFIG *SerialIrqConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH LPC SIRQ Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " SirqEnable= %x\n", SerialIrqConfig->SirqEnable));
> + DEBUG ((DEBUG_INFO, " SirqMode= %x\n", SerialIrqConfig->SirqMode));
> + DEBUG ((DEBUG_INFO, " StartFramePulse= %x\n",
> SerialIrqConfig->StartFramePulse));
> +}
> +/**
> + Print PCH_THERMAL_CONFIG and serial out.
> +
> + @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintThermalConfig (
> + IN CONST PCH_THERMAL_CONFIG *ThermalConfig
> + )
> +{
> + UINTN Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " TsmicLock= %x\n", ThermalConfig->TsmicLock));
> + DEBUG ((DEBUG_INFO, " TTLevels T0Level %x centigrade degree\n",
> ThermalConfig->TTLevels.T0Level));
> + DEBUG ((DEBUG_INFO, " TTLevels T1Level %x centigrade degree\n",
> ThermalConfig->TTLevels.T1Level));
> + DEBUG ((DEBUG_INFO, " TTLevels T2Level %x centigrade degree\n",
> ThermalConfig->TTLevels.T2Level));
> + DEBUG ((DEBUG_INFO, " TTLevels TTEnable %x\n",
> ThermalConfig->TTLevels.TTEnable));
> + DEBUG ((DEBUG_INFO, " TTLevels TTState13Enable %x\n",
> ThermalConfig->TTLevels.TTState13Enable));
> + DEBUG ((DEBUG_INFO, " TTLevels TTLock %x\n",
> ThermalConfig->TTLevels.TTLock));
> + DEBUG ((DEBUG_INFO, " TTLevels SuggestedSetting %x\n",
> ThermalConfig->TTLevels.SuggestedSetting));
> + DEBUG ((DEBUG_INFO, " TTLevels PchCrossThrottling %x\n",
> ThermalConfig->TTLevels.PchCrossThrottling));
> +
> + DEBUG ((DEBUG_INFO, " DmiHaAWC DmiTsawEn %x\n",
> ThermalConfig->DmiHaAWC.DmiTsawEn));
> + DEBUG ((DEBUG_INFO, " DmiHaAWC TS0TW %x\n",
> ThermalConfig->DmiHaAWC.TS0TW));
> + DEBUG ((DEBUG_INFO, " DmiHaAWC TS1TW %x\n",
> ThermalConfig->DmiHaAWC.TS1TW));
> + DEBUG ((DEBUG_INFO, " DmiHaAWC TS2TW %x\n",
> ThermalConfig->DmiHaAWC.TS2TW));
> + DEBUG ((DEBUG_INFO, " DmiHaAWC TS3TW %x\n",
> ThermalConfig->DmiHaAWC.TS3TW));
> + DEBUG ((DEBUG_INFO, " DmiHaAWC SuggestedSetting %x\n",
> ThermalConfig->DmiHaAWC.SuggestedSetting));
> +
> + DEBUG ((DEBUG_INFO, " MemoryThrottling Enable= %x\n",
> ThermalConfig->MemoryThrottling.Enable));
> + for (Index = 0; Index < MaxTsGpioPin; Index++) {
> + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting
> PmsyncEnable= %x\n",
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PmsyncEnable));
> + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting
> C0TransmitEnable= %x\n",
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].C0TransmitEnabl
> e));
> + DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting
> PinSelection= %x\n",
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PinSelection));
> + }
> + DEBUG ((DEBUG_INFO, " PchHotEnable = %x\n",
> ThermalConfig->PchHotEnable));
> + DEBUG ((DEBUG_INFO, " PchHotLevel = %x\n",
> ThermalConfig->PchHotLevel));
> +}
> +
> +/**
> + Print PCH_GENERAL_CONFIG and serial out.
> +
> + @param[in] PchGeneralConfig Pointer to a PCH_GENERAL_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintGeneralConfig (
> + IN CONST PCH_GENERAL_CONFIG *PchGeneralConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH General Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Crid= %x\n", PchGeneralConfig->Crid));
> + DEBUG ((DEBUG_INFO, " LegacyIoLowLatency = %x\n",
> PchGeneralConfig->LegacyIoLowLatency));
> +}
> +
> +/**
> + Print PCH_LAN_CONFIG and serial out.
> +
> + @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintLanConfig (
> + IN CONST PCH_LAN_CONFIG *LanConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Enable= %x\n", LanConfig->Enable));
> + DEBUG ((DEBUG_INFO, " LtrEnable= %x\n", LanConfig->LtrEnable));
> +}
> +
> +/**
> + Print PCH_SERIAL_IO_CONFIG and serial out.
> +
> + @param[in] SerialIoConfig Pointer to a PCH_SERIAL_IO_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintSerialIoConfig (
> + IN CONST PCH_SERIAL_IO_CONFIG *SerialIoConfig
> + )
> +{
> + UINTN Index;
> +#ifndef MDEPKG_NDEBUG
> + static UINT8 DeviceName[PCH_MAX_SERIALIO_CONTROLLERS][5] =
> {"I2C0","I2C1","I2C2","I2C3","I2C4","I2C5","SPI0","SPI1","SPI2","UA00","UA01"
> ,"UA02"};
> +#endif
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH Serial IO Config
> ------------------\n"));
> + DEBUG_CODE_BEGIN ();
> + for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " SerialIoController %a: Mode 0x%x\n",
> DeviceName[Index], SerialIoConfig->DevMode[Index]));
> + }
> + DEBUG_CODE_END ();
> + for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " SpiCsPolarity[%d] = 0x%x\n", Index,
> SerialIoConfig->SpiCsPolarity[Index]));
> + }
> + for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
> + DEBUG ((DEBUG_INFO, " UartHwFlowCtrl[%d] = 0x%x\n", Index,
> SerialIoConfig->UartHwFlowCtrl[Index]));
> + }
> + for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index ++) {
> + DEBUG ((DEBUG_INFO, " I2cPadsTermination[%d] = 0x%x\n", Index,
> SerialIoConfig->I2cPadsTermination[Index]));
> + }
> + DEBUG ((DEBUG_INFO, " DebugUartNumber = 0x%x\n",
> SerialIoConfig->DebugUartNumber));
> + DEBUG ((DEBUG_INFO, " EnableDebugUartAfterPost = 0x%x\n",
> SerialIoConfig->EnableDebugUartAfterPost));
> + DEBUG ((DEBUG_INFO, " Uart0PinMuxing = 0x%x\n",
> SerialIoConfig->Uart0PinMuxing));
> +}
> +
> +/**
> + Print PCH_INTERRUPT_CONFIG and serial out
> +
> + @param[in] InterruptConfig Pointer to Interrupt Configuration
> structure
> +
> +**/
> +VOID
> +PchPrintInterruptConfig (
> + IN CONST PCH_INTERRUPT_CONFIG *InterruptConfig
> + )
> +{
> + UINTN Index;
> + //
> + // Print interrupt information
> + //
> + DEBUG ((DEBUG_INFO, "------------------ PCH Interrupt Config
> ------------------\n"));
> + DEBUG ((DEBUG_INFO, " Interrupt assignment:\n"));
> + DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n"));
> + for (Index = 0; Index < InterruptConfig->NumOfDevIntConfig; Index++) {
> + DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
> + InterruptConfig->DevIntConfig[Index].Device,
> + InterruptConfig->DevIntConfig[Index].Function,
> + InterruptConfig->DevIntConfig[Index].IntX,
> + InterruptConfig->DevIntConfig[Index].Irq));
> + }
> + DEBUG ((DEBUG_INFO, " Legacy PIC interrupt routing:\n"));
> + DEBUG ((DEBUG_INFO, " PIRQx IRQx\n"));
> + for (Index = 0; Index < PCH_MAX_PXRC_CONFIG; Index++) {
> + DEBUG ((DEBUG_INFO, " PIRQ%c -> IRQ%d\n", Index + 65,
> InterruptConfig->PxRcConfig[Index]));
> + }
> + DEBUG ((DEBUG_INFO, " Other interrupt configuration:\n"));
> + DEBUG ((DEBUG_INFO, " GpioIrqRoute= %d\n",
> InterruptConfig->GpioIrqRoute));
> + DEBUG ((DEBUG_INFO, " SciIrqSelect= %d\n",
> InterruptConfig->SciIrqSelect));
> + DEBUG ((DEBUG_INFO, " TcoIrqEnable= %d\n",
> InterruptConfig->TcoIrqEnable));
> + DEBUG ((DEBUG_INFO, " TcoIrqSelect= %d\n",
> InterruptConfig->TcoIrqSelect));
> +}
> +
> +/**
> + Print PCH_SCS_CONFIG and serial out.
> +
> + @param[in] ScsConfig Pointer to a PCH_SCS_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintScsConfig (
> + IN CONST PCH_SCS_CONFIG *ScsConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH SCS Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " ScsEmmcEnabled = %x\n",
> ScsConfig->ScsEmmcEnabled));
> + DEBUG ((DEBUG_INFO, " ScsSdcardEnabled = %x\n",
> ScsConfig->ScsSdcardEnabled));
> + DEBUG ((DEBUG_INFO, " SdCardPowerEnableActiveHigh = %x\n",
> ScsConfig->SdCardPowerEnableActiveHigh));
> + DEBUG ((DEBUG_INFO, " ScsUfsEnabled = %x\n",
> ScsConfig->ScsUfsEnabled));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400Enabled = %x\n",
> ScsConfig->ScsEmmcHs400Enabled));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TuningRequired = %x\n",
> ScsConfig->ScsEmmcHs400TuningRequired));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DllDataValid = %x\n",
> ScsConfig->ScsEmmcHs400DllDataValid));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400RxStrobeDll1 = %x\n",
> ScsConfig->ScsEmmcHs400RxStrobeDll1));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400TxDataDll = %x\n",
> ScsConfig->ScsEmmcHs400TxDataDll));
> + DEBUG ((DEBUG_INFO, " ScsEmmcHs400DriverStrength = %x\n",
> ScsConfig->ScsEmmcHs400DriverStrength));
> +}
> +
> +/**
> + Print PCH_ISH_CONFIG and serial out.
> +
> + @param[in] IshConfig Pointer to a PCH_ISH_CONFIG that provides
> the platform setting
> +
> +**/
> +VOID
> +PchPrintIshConfig (
> + IN CONST PCH_ISH_CONFIG *IshConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH ISH Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " SPI GPIO Assigned = %x\n",
> IshConfig->SpiGpioAssign));
> + DEBUG ((DEBUG_INFO, " UART0 GPIO Assigned = %x\n",
> IshConfig->Uart0GpioAssign));
> + DEBUG ((DEBUG_INFO, " UART1 GPIO Assigned = %x\n",
> IshConfig->Uart1GpioAssign));
> + DEBUG ((DEBUG_INFO, " I2C0 GPIO Assigned = %x\n",
> IshConfig->I2c0GpioAssign));
> + DEBUG ((DEBUG_INFO, " I2C1 GPIO Assigned = %x\n",
> IshConfig->I2c1GpioAssign));
> + DEBUG ((DEBUG_INFO, " I2C2 GPIO Assigned = %x\n",
> IshConfig->I2c2GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_0 GPIO Assigned = %x\n",
> IshConfig->Gp0GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_1 GPIO Assigned = %x\n",
> IshConfig->Gp1GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_2 GPIO Assigned = %x\n",
> IshConfig->Gp2GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_3 GPIO Assigned = %x\n",
> IshConfig->Gp3GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_4 GPIO Assigned = %x\n",
> IshConfig->Gp4GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_5 GPIO Assigned = %x\n",
> IshConfig->Gp5GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_6 GPIO Assigned = %x\n",
> IshConfig->Gp6GpioAssign));
> + DEBUG ((DEBUG_INFO, " GP_7 GPIO Assigned = %x\n",
> IshConfig->Gp7GpioAssign));
> +}
> +
> +/**
> + Print PCH_FLASH_PROTECTION_CONFIG and serial out.
> +
> + @param[in] FlashProtectConfig Pointer to a
> PCH_FLASH_PROTECTION_CONFIG that provides the platform setting
> +
> +**/
> +VOID
> +PchPrintFlashProtectionConfig (
> + IN CONST PCH_FLASH_PROTECTION_CONFIG *FlashProtectConfig
> + )
> +{
> + UINT32 Index;
> +
> + DEBUG ((DEBUG_INFO, "------------------ PCH Flash Protection Config
> ------------------\n"));
> + for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
> + DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d] = %x\n", Index,
> FlashProtectConfig->ProtectRange[Index].WriteProtectionEnable));
> + DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d] = %x\n", Index,
> FlashProtectConfig->ProtectRange[Index].ReadProtectionEnable));
> + DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d] = %x\n", Index,
> FlashProtectConfig->ProtectRange[Index].ProtectedRangeLimit));
> + DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d] = %x\n", Index,
> FlashProtectConfig->ProtectRange[Index].ProtectedRangeBase));
> + }
> +}
> +
> +/**
> + Print PCH_P2SB_CONFIG and serial out.
> +
> + @param[in] P2sbConfig Pointer to a PCH_P2SB_CONFIG that
> provides the platform setting
> +
> +**/
> +VOID
> +PchPrintP2sbConfig (
> + IN CONST PCH_P2SB_CONFIG *P2sbConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH P2SB Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, "SbAccessUnlock= %x\n",
> P2sbConfig->SbAccessUnlock));
> +}
> +
> +/**
> + Print PCH_ESPI_CONFIG.
> +
> + @param[in] EspiConfig Pointer to a PCH_ESPI_CONFIG that provides
> the eSPI setting
> +
> +**/
> +VOID
> +PchPrintEspiConfig (
> + IN CONST PCH_ESPI_CONFIG *EspiConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH eSPI Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " LGMR Enable %x\n", EspiConfig->LgmrEnable));
> + DEBUG ((DEBUG_INFO, " BME for Master and Slave Enabled %x\n",
> EspiConfig->BmeMasterSlaveEnabled));
> +}
> +
> +/**
> + Print PCH_CNVI_CONFIG.
> +
> + @param[in] CnviConfig Pointer to a PCH_CNVI_CONFIG that provides
> the CNVi settings
> +
> +**/
> +VOID
> +PchPrintCnviConfig (
> + IN CONST PCH_CNVI_CONFIG *CnviConfig
> + )
> +{
> + DEBUG ((DEBUG_INFO, "------------------ PCH CNVi Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, "CNVi Mode = %x\n", CnviConfig->Mode));
> + DEBUG ((DEBUG_INFO, "CNVi MfUart1 type = %x\n",
> CnviConfig->MfUart1Type));
> +}
> +
> +/**
> + Print PCH_HSIO_CONFIG.
> +
> + @param[in] HsioConfig Pointer to a PCH_HSIO_CONFIG that provides
> the eSPI setting
> +
> +**/
> +VOID
> +PchPrintHsioConfig (
> + IN CONST PCH_HSIO_CONFIG *HsioConfig
> + )
> +{
> + PCH_HSIO_VER_INFO *BiosChipsetInitVerInfoPtr;
> + DEBUG ((DEBUG_INFO, "------------------ PCH HSIO Config ------------------\n"));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Pointer = %x\n",
> HsioConfig->ChipsetInitBinPtr));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Length = %x\n",
> HsioConfig->ChipsetInitBinLen));
> + BiosChipsetInitVerInfoPtr = (PCH_HSIO_VER_INFO *)
> HsioConfig->ChipsetInitBinPtr;
> + if (HsioConfig->ChipsetInitBinPtr && HsioConfig->ChipsetInitBinLen) {
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC = %x\n",
> BiosChipsetInitVerInfoPtr->BaseCrc));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC = %x\n",
> BiosChipsetInitVerInfoPtr->OemCrc));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC = %x\n",
> BiosChipsetInitVerInfoPtr->SusCrc));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Version = %x\n",
> BiosChipsetInitVerInfoPtr->Version));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Product = %x\n",
> BiosChipsetInitVerInfoPtr->Product));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Metal Layer = %x\n",
> BiosChipsetInitVerInfoPtr->MetalLayer));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base Layer = %x\n",
> BiosChipsetInitVerInfoPtr->BaseLayer));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM Version = %x\n",
> BiosChipsetInitVerInfoPtr->OemVersion));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Debug Mode = %x\n",
> BiosChipsetInitVerInfoPtr->DebugMode));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary OEM CRC Valid = %x\n",
> BiosChipsetInitVerInfoPtr->OemCrcValid));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary SUS CRC Valid = %x\n",
> BiosChipsetInitVerInfoPtr->SusCrcValid));
> + DEBUG ((DEBUG_INFO, " ChipsetInit Binary Base CRC Valid = %x\n",
> BiosChipsetInitVerInfoPtr->BaseCrcValid));
> + }
> +}
> +
> +/**
> + Print whole PCH config blocks and serial out.
> +
> + @param[in] SiPolicyPpi The RC Policy PPI instance
> +
> +**/
> +VOID
> +EFIAPI
> +PchPrintPolicyPpi (
> + IN SI_POLICY_PPI *SiPolicyPpi
> + )
> +{
> +DEBUG_CODE_BEGIN();
> + EFI_STATUS Status;
> + PCH_GENERAL_CONFIG *PchGeneralConfig;
> + PCH_PCIE_CONFIG *PcieRpConfig;
> + PCH_SATA_CONFIG *SataConfig;
> + PCH_IOAPIC_CONFIG *IoApicConfig;
> + PCH_DMI_CONFIG *DmiConfig;
> + PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
> + PCH_HDAUDIO_CONFIG *HdAudioConfig;
> + PCH_INTERRUPT_CONFIG *InterruptConfig;
> + PCH_ISH_CONFIG *IshConfig;
> + PCH_LAN_CONFIG *LanConfig;
> + PCH_P2SB_CONFIG *P2sbConfig;
> + PCH_LOCK_DOWN_CONFIG *LockDownConfig;
> + PCH_PM_CONFIG *PmConfig;
> + PCH_SCS_CONFIG *ScsConfig;
> + PCH_SERIAL_IO_CONFIG *SerialIoConfig;
> + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig;
> + PCH_THERMAL_CONFIG *ThermalConfig;
> + USB_CONFIG *UsbConfig;
> + PCH_ESPI_CONFIG *EspiConfig;
> + PCH_CNVI_CONFIG *CnviConfig;
> + PCH_HSIO_CONFIG *HsioConfig;
> + UINT32 SataCtrlIndex;
> +
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPchGeneralConfigGuid,
> (VOID *) &PchGeneralConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPcieRpConfigGuid, (VOID *)
> &PcieRpConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIoApicConfigGuid, (VOID *)
> &IoApicConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gDmiConfigGuid, (VOID *)
> &DmiConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gFlashProtectionConfigGuid,
> (VOID *) &FlashProtectionConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHdAudioConfigGuid, (VOID
> *) &HdAudioConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gInterruptConfigGuid, (VOID
> *) &InterruptConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIshConfigGuid, (VOID *)
> &IshConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLanConfigGuid, (VOID *)
> &LanConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLockDownConfigGuid,
> (VOID *) &LockDownConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gP2sbConfigGuid, (VOID *)
> &P2sbConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPmConfigGuid, (VOID *)
> &PmConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gScsConfigGuid, (VOID *)
> &ScsConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIoConfigGuid, (VOID *)
> &SerialIoConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIrqConfigGuid, (VOID
> *) &SerialIrqConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gThermalConfigGuid, (VOID
> *) &ThermalConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gUsbConfigGuid, (VOID *)
> &UsbConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gEspiConfigGuid, (VOID *)
> &EspiConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCnviConfigGuid, (VOID *)
> &CnviConfig);
> + ASSERT_EFI_ERROR (Status);
> + Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHsioConfigGuid, (VOID *)
> &HsioConfig);
> + ASSERT_EFI_ERROR (Status);
> +
> + DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy Start
> ------------------------\n"));
> + DEBUG ((DEBUG_INFO, " Revision= %x\n",
> SiPolicyPpi->TableHeader.Header.Revision));
> +
> + PchPrintGeneralConfig (PchGeneralConfig);
> + PchPrintPcieConfig (PcieRpConfig);
> + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum ();
> SataCtrlIndex++) {
> + SataConfig = GetPchSataConfig (SiPolicyPpi, SataCtrlIndex);
> + PchPrintSataConfig (SataCtrlIndex, SataConfig);
> + }
> + PchPrintUsbConfig (UsbConfig);
> + PchPrintIoApicConfig (IoApicConfig);
> + PchPrintHdAudioConfig (HdAudioConfig);
> + PchPrintLanConfig (LanConfig);
> + PchPrintLockDownConfig (LockDownConfig);
> + PchPrintThermalConfig (ThermalConfig);
> + PchPrintPmConfig (PmConfig);
> + PchPrintDmiConfig (DmiConfig);
> + PchPrintSerialIrqConfig (SerialIrqConfig);
> + PchPrintSerialIoConfig (SerialIoConfig);
> + PchPrintInterruptConfig (InterruptConfig);
> + PchPrintScsConfig (ScsConfig);
> + PchPrintIshConfig (IshConfig);
> + PchPrintFlashProtectionConfig (FlashProtectionConfig);
> + PchPrintP2sbConfig (P2sbConfig);
> + PchPrintEspiConfig (EspiConfig);
> + PchPrintCnviConfig (CnviConfig);
> + PchPrintHsioConfig (HsioConfig);
> +
> + DEBUG ((DEBUG_INFO, "------------------------ PCH Print Platform Protocol End
> --------------------------\n"));
> +DEBUG_CODE_END();
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLib.c
> new file mode 100644
> index 0000000000..2a1da20667
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLib.c
> @@ -0,0 +1,739 @@
> +/** @file
> + This file is PeiPchPolicy library.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PeiPchPolicyLibrary.h"
> +#include <Library/PchPcieRpLib.h>
> +#include <Library/CpuPlatformLib.h>
> +#include <Register/PchRegsLpcCnl.h>
> +
> +/**
> + mPxRcConfig[] table contains data for 8259 routing (how PIRQx is mapped to
> IRQy).
> + This information is used by systems which choose to use legacy PIC
> + interrupt controller. Only IRQ3-7,9-12,14,15 are valid. Values from this table
> + will be programmed into ITSS.PxRC registers.
> +**/
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPxRcConfig[] = {
> + 11, // PARC: PIRQA -> IRQ11
> + 10, // PBRC: PIRQB -> IRQ10
> + 11, // PCRC: PIRQC -> IRQ11
> + 11, // PDRC: PIRQD -> IRQ11
> + 11, // PERC: PIRQE -> IRQ11
> + 11, // PFRC: PIRQF -> IRQ11
> + 11, // PGRC: PIRQG -> IRQ11
> + 11 // PHRC: PIRQH -> IRQ11
> +};
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPchGeneralConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_GENERAL_CONFIG *PchGeneralConfig;
> + PchGeneralConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Name =
> %g\n", &PchGeneralConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PchGeneralConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> PchGeneralConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + PCH general configuration
> + ********************************/
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPcieRpConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + UINTN Index;
> + PCH_PCIE_CONFIG *PcieRpConfig;
> +
> + PcieRpConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Name = %g\n",
> &PcieRpConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PcieRpConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> PcieRpConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + PCI Express related settings
> + ********************************/
> + PcieRpConfig->RpFunctionSwap = TRUE;
> +
> + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> + PcieRpConfig->RootPort[Index].Aspm =
> PchPcieAspmAutoConfig;
> + PcieRpConfig->RootPort[Index].PmSci = TRUE;
> + PcieRpConfig->RootPort[Index].AcsEnabled = TRUE;
> + PcieRpConfig->RootPort[Index].PtmEnabled = TRUE;
> + PcieRpConfig->RootPort[Index].DpcEnabled = TRUE;
> + PcieRpConfig->RootPort[Index].RpDpcExtensionsEnabled = TRUE;
> + PcieRpConfig->RootPort[Index].MaxPayload =
> PchPcieMaxPayload256;
> + PcieRpConfig->RootPort[Index].SlotImplemented = TRUE;
> + PcieRpConfig->RootPort[Index].PhysicalSlotNumber = (UINT8) Index;
> + PcieRpConfig->RootPort[Index].L1Substates =
> PchPcieL1SubstatesL1_1_2;
> + PcieRpConfig->RootPort[Index].EnableCpm = TRUE;
> + PcieRpConfig->RootPort[Index].Gen3EqPh3Method =
> PchPcieEqHardware;
> +
> + //
> + // PCIe LTR Configuration.
> + //
> + PcieRpConfig->RootPort[Index].LtrEnable = TRUE;
> +
> + PcieRpConfig->RootPort[Index].LtrMaxSnoopLatency = 0x1003;
> + PcieRpConfig->RootPort[Index].LtrMaxNoSnoopLatency =
> 0x1003;
> +
> + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMode = 2;
> + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMultiplier = 2;
> + PcieRpConfig->RootPort[Index].SnoopLatencyOverrideValue = 60;
> + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMode =
> 2;
> + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier =
> 2;
> + PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideValue =
> 60;
> +
> + PcieRpConfig->RootPort[Index].Uptp = 5;
> + PcieRpConfig->RootPort[Index].Dptp = 7;
> +
> + PcieRpConfig->EqPh3LaneParam[Index].Cm = 6;
> + PcieRpConfig->EqPh3LaneParam[Index].Cp = 2;
> + }
> +
> + PcieRpConfig->SwEqCoeffList[0].Cm = 4;
> + PcieRpConfig->SwEqCoeffList[0].Cp = 8;
> + PcieRpConfig->SwEqCoeffList[1].Cm = 6;
> + PcieRpConfig->SwEqCoeffList[1].Cp = 2;
> + PcieRpConfig->SwEqCoeffList[2].Cm = 8;
> + PcieRpConfig->SwEqCoeffList[2].Cp = 6;
> + PcieRpConfig->SwEqCoeffList[3].Cm = 10;
> + PcieRpConfig->SwEqCoeffList[3].Cp = 8;
> + PcieRpConfig->SwEqCoeffList[4].Cm = 12;
> + PcieRpConfig->SwEqCoeffList[4].Cp = 2;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadSataConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + UINTN PortIndex;
> + UINTN Index;
> + UINT32 SataCtrlIndex;
> + PCH_SATA_CONFIG *SataConfig;
> +
> + SataConfig = (PCH_SATA_CONFIG *)ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Name = %g\n",
> &SataConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", SataConfig->Header.GuidHob.Header.HobLength));
> +
> + for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum ();
> SataCtrlIndex++, SataConfig++) {
> + /********************************
> + SATA related settings
> + ********************************/
> + SataConfig->Enable = TRUE;
> + SataConfig->SalpSupport = TRUE;
> + SataConfig->SataMode = PchSataModeAhci;
> +
> + for (PortIndex = 0; PortIndex < GetPchMaxSataPortNum (SataCtrlIndex);
> PortIndex++) {
> + SataConfig->PortSettings[PortIndex].Enable = TRUE;
> + SataConfig->PortSettings[PortIndex].DmVal = 15;
> + SataConfig->PortSettings[PortIndex].DitoVal = 625;
> + }
> +
> + SataConfig->Rst.Raid0 = TRUE;
> + SataConfig->Rst.Raid1 = TRUE;
> + SataConfig->Rst.Raid10 = TRUE;
> + SataConfig->Rst.Raid5 = TRUE;
> + SataConfig->Rst.Irrt = TRUE;
> + SataConfig->Rst.OromUiBanner = TRUE;
> + SataConfig->Rst.OromUiDelay = PchSataOromDelay2sec;
> + SataConfig->Rst.HddUnlock = TRUE;
> + SataConfig->Rst.LedLocate = TRUE;
> + SataConfig->Rst.IrrtOnly = TRUE;
> + SataConfig->Rst.SmartStorage = TRUE;
> + SataConfig->Rst.OptaneMemory = TRUE;
> + SataConfig->Rst.CpuAttachedStorage = TRUE;
> +
> + for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
> + SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay =
> 100;
> + }
> +
> + SataConfig->PwrOptEnable = TRUE;
> + SataConfig->ThermalThrottling.SuggestedSetting = TRUE;
> + }
> +}
> +
> +/**
> + Get Sata Config Policy
> +
> + @param[in] SiPolicy The RC Policy PPI instance
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval SataConfig Pointer to Sata Config Policy
> +**/
> +PCH_SATA_CONFIG *
> +GetPchSataConfig (
> + IN SI_POLICY_PPI *SiPolicy,
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + PCH_SATA_CONFIG *SataConfig;
> + EFI_STATUS Status;
> +
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + Status = GetConfigBlock ((VOID *) SiPolicy, &gSataConfigGuid, (VOID *)
> &SataConfig);
> + ASSERT_EFI_ERROR (Status);
> +
> + SataConfig += SataCtrlIndex;
> +
> + return SataConfig;
> +}
> +
> +/**
> + Load Config block default
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadIoApicConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_IOAPIC_CONFIG *IoApicConfig;
> + IoApicConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Name = %g\n",
> &IoApicConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Header.HobLength
> = 0x%x\n", IoApicConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Io Apic configuration
> + ********************************/
> + IoApicConfig->IoApicId = 0x02;
> + IoApicConfig->IoApicEntry24_119 = TRUE;
> + IoApicConfig->Enable8254ClockGating = TRUE;
> + IoApicConfig->Enable8254ClockGatingOnS3 = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadDmiConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_DMI_CONFIG *DmiConfig;
> + DmiConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Name = %g\n",
> &DmiConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", DmiConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + DMI related settings
> + ********************************/
> + DmiConfig->DmiAspmCtrl = PchPcieAspmAutoConfig;
> +}
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadFlashProtectionConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
> + FlashProtectionConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Name =
> %g\n", &FlashProtectionConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "FlashProtectionConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> FlashProtectionConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadHdAudioConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_HDAUDIO_CONFIG *HdAudioConfig;
> + HdAudioConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "HdAudioConfig->Header.GuidHob.Name = %g\n",
> &HdAudioConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "HdAudioConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> HdAudioConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + HD-Audio configuration
> + ********************************/
> + HdAudioConfig->DspEnable = TRUE;
> + HdAudioConfig->HdAudioLinkFrequency = PchHdaLinkFreq24MHz;
> + HdAudioConfig->IDispLinkFrequency = PchHdaLinkFreq96MHz;
> + HdAudioConfig->IDispLinkTmode = PchHdaIDispMode2T;
> + HdAudioConfig->ResetWaitTimer = 600; // Must be at least 521us (25
> frames)
> + HdAudioConfig->AudioLinkHda = TRUE;
> + HdAudioConfig->AudioLinkDmic0 = TRUE;
> + HdAudioConfig->AudioLinkDmic1 = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadInterruptConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_INTERRUPT_CONFIG *InterruptConfig;
> + InterruptConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Name = %g\n",
> &InterruptConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "InterruptConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> InterruptConfig->Header.GuidHob.Header.HobLength));
> +
> + LoadDeviceInterruptConfig (InterruptConfig);
> +
> + ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <=
> PCH_MAX_PXRC_CONFIG);
> + CopyMem (
> + InterruptConfig->PxRcConfig,
> + mPxRcConfig,
> + sizeof (mPxRcConfig)
> + );
> +
> + InterruptConfig->GpioIrqRoute = 14;
> + InterruptConfig->SciIrqSelect = 9;
> + InterruptConfig->TcoIrqSelect = 9;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadIshConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_ISH_CONFIG *IshConfig;
> + IshConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Name = %g\n",
> &IshConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", IshConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadLanConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_LAN_CONFIG *LanConfig;
> + UINT16 LpcDid;
> +
> + LanConfig = ConfigBlockPointer;
> + LpcDid = PchGetLpcDid ();
> +
> + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Name = %g\n",
> &LanConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", LanConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Lan configuration
> + ********************************/
> + LanConfig->Enable = TRUE;
> + LanConfig->LtrEnable = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadLockDownConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_LOCK_DOWN_CONFIG *LockDownConfig;
> + LockDownConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Name = %g\n",
> &LockDownConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "LockDownConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> LockDownConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Lockdown configuration
> + ********************************/
> + LockDownConfig->GlobalSmi = TRUE;
> + LockDownConfig->BiosInterface = TRUE;
> + LockDownConfig->RtcMemoryLock = TRUE;
> + LockDownConfig->BiosLock = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadP2sbConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_P2SB_CONFIG *P2sbConfig;
> + P2sbConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Name = %g\n",
> &P2sbConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", P2sbConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPmConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_PM_CONFIG *PmConfig;
> + PmConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Name = %g\n",
> &PmConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", PmConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + MiscPm Configuration
> + ********************************/
> + PmConfig->MeWakeSts = TRUE;
> + PmConfig->WolOvrWkSts = TRUE;
> +
> + PmConfig->WakeConfig.WolEnableOverride = TRUE;
> + PmConfig->WakeConfig.LanWakeFromDeepSx = TRUE;
> +
> + PmConfig->PchSlpS3MinAssert = PchSlpS350ms;
> + PmConfig->PchSlpS4MinAssert = PchSlpS41s;
> + PmConfig->PchSlpSusMinAssert = PchSlpSus4s;
> + PmConfig->PchSlpAMinAssert = PchSlpA2s;
> +
> + PmConfig->SlpLanLowDc = TRUE;
> + PmConfig->PciePllSsc = 0xFF;
> + PmConfig->LpcClockRun = TRUE;
> + PmConfig->SlpS0Enable = TRUE;
> + PmConfig->CpuC10GatePinEnable = TRUE;
> + if (IsWhlCpu () && (GetCpuStepping () == EnumCflV0)) {
> + PmConfig->SlpS0WithGbeSupport = FALSE;
> + } else {
> + PmConfig->SlpS0WithGbeSupport = TRUE;
> + }
> +
> + if (IsPchLp ()) {
> + PmConfig->ModPhySusPgEnable = TRUE;
> + }
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadScsConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_SCS_CONFIG *ScsConfig;
> + ScsConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Name = %g\n",
> &ScsConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", ScsConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + SCS Configuration
> + ********************************/
> + ScsConfig->ScsEmmcEnabled = IsPchLp () ? TRUE : FALSE; // eMMC present
> on PCH-LP only
> + ScsConfig->ScsEmmcHs400DriverStrength = DriverStrength40Ohm;
> + //Enable Sd Card controller for Non-Desktop sku platforms
> + if (GetCpuSku () != EnumCpuTrad) {
> + ScsConfig->ScsSdcardEnabled = TRUE;
> + }
> + ScsConfig->SdCardPowerEnableActiveHigh = TRUE;
> + ScsConfig->ScsUfsEnabled = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadSerialIoConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + UINTN Index;
> + PCH_SERIAL_IO_CONFIG *SerialIoConfig;
> + SerialIoConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Name = %g\n",
> &SerialIoConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "SerialIoConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> SerialIoConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + SerialIo Configuration
> + ********************************/
> + for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) {
> + SerialIoConfig->DevMode[Index] = PchSerialIoPci;
> + }
> + SerialIoConfig->DebugUartNumber = PcdGet8
> (PcdSerialIoUartNumber);
> +}
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadSerialIrqConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig;
> + SerialIrqConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Name = %g\n",
> &SerialIrqConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "SerialIrqConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> SerialIrqConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Serial IRQ Configuration
> + ********************************/
> + SerialIrqConfig->SirqEnable = TRUE;
> + SerialIrqConfig->SirqMode = PchQuietMode;
> + SerialIrqConfig->StartFramePulse = PchSfpw4Clk;
> +}
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadThermalConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_THERMAL_CONFIG *ThermalConfig;
> + ThermalConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Name = %g\n",
> &ThermalConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "ThermalConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> ThermalConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Thermal configuration.
> + ********************************/
> + ThermalConfig->TsmicLock = TRUE;
> + ThermalConfig->PchHotLevel = 0x154;
> + ThermalConfig->TTLevels.SuggestedSetting = TRUE;
> + ThermalConfig->TTLevels.PchCrossThrottling = TRUE;
> + ThermalConfig->DmiHaAWC.SuggestedSetting = TRUE;
> +
> +
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable
> = TRUE;
> +
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEn
> able = TRUE;
> +
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable
> = TRUE;
> +
> ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEn
> able = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadUsbConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + UINTN PortIndex;
> + USB_CONFIG *UsbConfig;
> + UsbConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Name = %g\n",
> &UsbConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", UsbConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + USB related configuration
> + ********************************/
> + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++)
> {
> + UsbConfig->PortUsb20[PortIndex].Enable = TRUE;
> + }
> +
> + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++)
> {
> + UsbConfig->PortUsb30[PortIndex].Enable = TRUE;
> + }
> +
> + //
> + // BIOS should program PDO in PEI phase by default
> + //
> + UsbConfig->PdoProgramming = TRUE;
> +
> + //
> + // Default values of USB2 AFE settings.
> + //
> + UsbConfig->Usb2PhySusPgEnable = TRUE;
> + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++)
> {
> + UsbConfig->PortUsb20[PortIndex].Afe.Petxiset = 3;
> + UsbConfig->PortUsb20[PortIndex].Afe.Txiset = 2;
> + UsbConfig->PortUsb20[PortIndex].Afe.Predeemp = 1;
> + UsbConfig->PortUsb20[PortIndex].Afe.Pehalfbit = 1;
> + }
> +
> + for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++)
> {
> + UsbConfig->PortUsb30HsioRx[PortIndex].HsioOlfpsCfgPullUpDwnRes = 3;
> + }
> +
> + UsbConfig->XhciOcLock = TRUE;
> +
> + //
> + // xDCI configuration
> + //
> + UsbConfig->XdciConfig.Enable = FALSE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadEspiConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_ESPI_CONFIG *EspiConfig;
> + EspiConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Name = %g\n",
> &EspiConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", EspiConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Espi configuration.
> + ********************************/
> + EspiConfig->BmeMasterSlaveEnabled = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadCnviConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_CNVI_CONFIG *CnviConfig;
> + CnviConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Name = %g\n",
> &CnviConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "CnviConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", CnviConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + Cnvi configuration.
> + ********************************/
> + CnviConfig->Mode = CnviModeAuto; // Automatic detection
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadHsioConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_HSIO_CONFIG *HsioConfig;
> + HsioConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Name = %g\n",
> &HsioConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO, "HsioConfig->Header.GuidHob.Header.HobLength =
> 0x%x\n", HsioConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY
> mPchIpBlocks [] = {
> + {&gPchGeneralConfigGuid, sizeof (PCH_GENERAL_CONFIG),
> PCH_GENERAL_CONFIG_REVISION, LoadPchGeneralConfigDefault},
> + {&gPcieRpConfigGuid, sizeof (PCH_PCIE_CONFIG),
> PCIE_RP_CONFIG_REVISION, LoadPcieRpConfigDefault},
> + {&gSataConfigGuid, sizeof (PCH_SATA_CONFIG),
> SATA_CONFIG_REVISION, LoadSataConfigDefault},
> + {&gIoApicConfigGuid, sizeof (PCH_IOAPIC_CONFIG),
> IOAPIC_CONFIG_REVISION, LoadIoApicConfigDefault},
> + {&gDmiConfigGuid, sizeof (PCH_DMI_CONFIG),
> DMI_CONFIG_REVISION, LoadDmiConfigDefault},
> + {&gFlashProtectionConfigGuid, sizeof (PCH_FLASH_PROTECTION_CONFIG),
> FLASH_PROTECTION_CONFIG_REVISION, LoadFlashProtectionConfigDefault},
> + {&gHdAudioConfigGuid, sizeof (PCH_HDAUDIO_CONFIG),
> HDAUDIO_CONFIG_REVISION, LoadHdAudioConfigDefault},
> + {&gInterruptConfigGuid, sizeof (PCH_INTERRUPT_CONFIG),
> INTERRUPT_CONFIG_REVISION, LoadInterruptConfigDefault},
> + {&gIshConfigGuid, sizeof (PCH_ISH_CONFIG),
> ISH_CONFIG_REVISION, LoadIshConfigDefault},
> + {&gLanConfigGuid, sizeof (PCH_LAN_CONFIG),
> LAN_CONFIG_REVISION, LoadLanConfigDefault},
> + {&gLockDownConfigGuid, sizeof (PCH_LOCK_DOWN_CONFIG),
> LOCK_DOWN_CONFIG_REVISION, LoadLockDownConfigDefault},
> + {&gP2sbConfigGuid, sizeof (PCH_P2SB_CONFIG),
> P2SB_CONFIG_REVISION, LoadP2sbConfigDefault},
> + {&gPmConfigGuid, sizeof (PCH_PM_CONFIG),
> PM_CONFIG_REVISION, LoadPmConfigDefault},
> + {&gScsConfigGuid, sizeof (PCH_SCS_CONFIG),
> SCS_CONFIG_REVISION, LoadScsConfigDefault},
> + {&gSerialIoConfigGuid, sizeof (PCH_SERIAL_IO_CONFIG),
> SERIAL_IO_CONFIG_REVISION, LoadSerialIoConfigDefault},
> + {&gSerialIrqConfigGuid, sizeof (PCH_LPC_SIRQ_CONFIG),
> SERIAL_IRQ_CONFIG_REVISION, LoadSerialIrqConfigDefault},
> + {&gThermalConfigGuid, sizeof (PCH_THERMAL_CONFIG),
> THERMAL_CONFIG_REVISION, LoadThermalConfigDefault},
> + {&gUsbConfigGuid, sizeof (USB_CONFIG),
> USB_CONFIG_REVISION, LoadUsbConfigDefault},
> + {&gEspiConfigGuid, sizeof (PCH_ESPI_CONFIG),
> ESPI_CONFIG_REVISION, LoadEspiConfigDefault},
> + {&gCnviConfigGuid, sizeof (PCH_CNVI_CONFIG),
> CNVI_CONFIG_REVISION, LoadCnviConfigDefault},
> + {&gHsioConfigGuid, sizeof (PCH_HSIO_CONFIG),
> HSIO_CONFIG_REVISION, LoadHsioConfigDefault},
> +};
> +
> +/**
> + Get PCH config block table total size.
> +
> + @retval Size of PCH config block table
> +**/
> +UINT16
> +EFIAPI
> +PchGetConfigBlockTotalSize (
> + VOID
> + )
> +{
> + return GetComponentConfigBlockTotalSize (&mPchIpBlocks[0], sizeof
> (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
> +}
> +
> +/**
> + PchAddConfigBlocks add all PCH config blocks.
> +
> + @param[in] ConfigBlockTableAddress The pointer to add PCH config
> blocks
> +
> + @retval EFI_SUCCESS The policy default is initialized.
> + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create
> buffer
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchAddConfigBlocks (
> + IN VOID *ConfigBlockTableAddress
> + )
> +{
> + DEBUG ((DEBUG_INFO, "PCH AddConfigBlocks\n"));
> +
> + return AddComponentConfigBlocks (ConfigBlockTableAddress,
> &mPchIpBlocks[0], sizeof (mPchIpBlocks) / sizeof
> (COMPONENT_BLOCK_ENTRY));
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.c
> new file mode 100644
> index 0000000000..d19692ff2c
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolic
> yLibCnl.c
> @@ -0,0 +1,169 @@
> +/** @file
> + This file is PeiPchPolicy library Cannon Lake specific.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PeiPchPolicyLibrary.h"
> +#include <Library/PchPcieRpLib.h>
> +#include <Library/CpuPlatformLib.h>
> +
> +/**
> + mDevIntConfig[] table contains data on INTx and IRQ for each device.
> + IRQ value for devices which use ITSS INTx->PIRQx mapping need to be set in
> a way
> + that for each multifunctional Dxx:Fy same interrupt pins must map to the
> same IRQ.
> + Those IRQ values will be used to update ITSS.PIRx register.
> + In APIC relationship between PIRQs and IRQs is:
> + PIRQA -> IRQ16
> + PIRQB -> IRQ17
> + PIRQC -> IRQ18
> + PIRQD -> IRQ19
> + PIRQE -> IRQ20
> + PIRQF -> IRQ21
> + PIRQG -> IRQ22
> + PIRQH -> IRQ23
> +
> + Devices which use INTx->PIRQy mapping are: cAVS(in PCI mode), SMBus, GbE,
> TraceHub, PCIe,
> + SATA, HECI, IDE-R, KT Redirection, xHCI, Thermal Subsystem, Camera IO Host
> Controller
> +
> + PCI Express Root Ports mapping should be programmed only with values as
> in below table (D27/28/29)
> + otherwise _PRT methods in ACPI for RootPorts would require additional
> patching as
> + PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy
> Mapping
> +
> + Configured IRQ values are not used if an OS chooses to be in PIC instead of
> APIC mode
> +**/
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG
> mDevIntConfig[] = {
> +// {31, 0, PchNoInt, 0}, // LPC/eSPI Interface, doesn't use interrupts
> +// {31, 1, PchNoInt, 0}, // P2SB, doesn't use interrupts
> +// {31, 2, PchNoInt, 0}, // PMC , doesn't use interrupts
> + {31, 3, PchIntA, 16}, // cAVS(Audio, Voice, Speach), INTA is default,
> programmed in PciCfgSpace 3Dh
> + {31, 4, PchIntA, 16}, // SMBus Controller, no default value, programmed in
> PciCfgSpace 3Dh
> +// {31, 5, PchNoInt, 0}, // SPI , doesn't use interrupts
> + {31, 7, PchIntA, 16}, // TraceHub, INTA is default, RO register
> + {30, 0, PchIntA, 20}, // SerialIo: UART #0, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[7]
> + {30, 1, PchIntB, 21}, // SerialIo: UART #1, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[8]
> + {30, 2, PchIntC, 22}, // SerialIo: SPI #0, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[10]
> + {30, 3, PchIntD, 23}, // SerialIo: SPI #1, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[11]
> + {28, 0, PchIntA, 16}, // PCI Express Port 1, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 1, PchIntB, 17}, // PCI Express Port 2, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 2, PchIntC, 18}, // PCI Express Port 3, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 3, PchIntD, 19}, // PCI Express Port 4, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 4, PchIntA, 16}, // PCI Express Port 5, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 5, PchIntB, 17}, // PCI Express Port 6, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 6, PchIntC, 18}, // PCI Express Port 7, INT is default, programmed in
> PciCfgSpace + FCh
> + {28, 7, PchIntD, 19}, // PCI Express Port 8, INT is default, programmed in
> PciCfgSpace + FCh
> + {25, 2, PchIntC, 34}, // SerialIo UART Controller #2, INTA is default,
> programmed in PCR[SERIALIO] + PCICFGCTRL[9]
> +// {24, 0, 0, 0}, // Reserved (used by RST PCIe Storage Cycle Router)
> + {23, 0, PchIntA, 16}, // SATA Controller, INTA is default, programmed in
> PciCfgSpace + 3Dh
> + {22, 0, PchIntA, 16}, // CSME: HECI #1
> + {22, 1, PchIntB, 17}, // CSME: HECI #2
> + {22, 4, PchIntA, 16}, // CSME: HECI #3
> +// {22, 7, PchNoInt, 0}, // CSME: WLAN
> + {21, 0, PchIntA, 16}, // SerialIo I2C Controller #0, INTA is default,
> programmed in PCR[SERIALIO] + PCICFGCTRL[1]
> + {21, 1, PchIntB, 17}, // SerialIo I2C Controller #1, INTA is default, programmed
> in PCR[SERIALIO] + PCICFGCTRL[2]
> + {21, 2, PchIntC, 18}, // SerialIo I2C Controller #2, INTA is default, programmed
> in PCR[SERIALIO] + PCICFGCTRL[3]
> + {21, 3, PchIntD, 19}, // SerialIo I2C Controller #3, INTA is default, programmed
> in PCR[SERIALIO] + PCICFGCTRL[4]
> + {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value,
> programmed in PciCfgSpace 3Dh
> + {20, 1, PchIntB, 17}, // USB Device Controller (OTG)
> + //{20, 2, PchNoInt, 0}, // Shared SRAM, no interrupts
> + {20, 3, PchIntA, 16}, // CNVi WiFir
> +// {20, 4, 0, 0}, // TraceHub Phantom (ACPI) Function
> + {20, 5, PchIntD, 19}, // SCS: SDCard
> +// {18, 0, PchNoInt, 0}, // CSME: KVMcc, doesn't use interrupts
> +// {18, 1, PchNoInt, 0}, // CSME: Clink, doesn't use interrupts
> +// {18, 2, PchNoInt, 0}, // CSME: PMT, doesn't use interrupts
> +// {18, 3, 0, 0}, // CSME: CSE UMA
> +// {18, 4, 0, 0} // CSME: fTPM DMA
> + {18, 5, PchIntA, 16} // SCS: UFS
> +};
> +
> +//
> +// mCnlPchLpOnlyDevIntConfig[] table contains data on INTx and IRQ for
> devices that exist on PCH-LP
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG
> mPchLpOnlyDevIntConfig[] = {
> + {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in
> PciCfgSpace 3Dh
> + {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 4, PchIntA, 16}, // PCI Express Port 13, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 5, PchIntB, 17}, // PCI Express Port 14, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 6, PchIntC, 18}, // PCI Express Port 15, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 7, PchIntD, 19}, // PCI Express Port 16, INT is default, programmed in
> PciCfgSpace + FCh
> + {26, 0, PchIntA, 16}, // SCS: eMMC
> + {25, 0, PchIntA, 32}, // SerialIo I2C Controller #4, INTA is default,
> programmed in PCR[SERIALIO] + PCICFGCTRL[5]
> + {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, programmed
> in PCR[SERIALIO] + PCICFGCTRL[6]
> + {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R)
> + {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection
> + {19, 0, PchIntA, 20}, // Integrated Sensor Hub
> + {18, 0, PchIntA, 16}, // Thermal Subsystem
> + {18, 6, PchIntB, 24} // SerialIo: SPI #2, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[12]
> +};
> +
> +//
> +// mPchHOnlyDevIntConfig[] table contains data on INTx and IRQ for devices
> that exist on PCH-H
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG
> mPchHOnlyDevIntConfig[] = {
> + {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in
> PciCfgSpace 3Dh
> + {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 4, PchIntA, 16}, // PCI Express Port 13, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 5, PchIntB, 17}, // PCI Express Port 14, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 6, PchIntC, 18}, // PCI Express Port 15, INT is default, programmed in
> PciCfgSpace + FCh
> + {29, 7, PchIntD, 19}, // PCI Express Port 16, INT is default, programmed in
> PciCfgSpace + FCh
> + {27, 0, PchIntA, 16}, // PCI Express Port 17, INT is default, programmed in
> PciCfgSpace + FCh
> + {27, 1, PchIntB, 17}, // PCI Express Port 18, INT is default, programmed in
> PciCfgSpace + FCh
> + {27, 2, PchIntC, 18}, // PCI Express Port 19, INT is default, programmed in
> PciCfgSpace + FCh
> + {27, 3, PchIntD, 19}, // PCI Express Port 20, INT is default, programmed in
> PciCfgSpace + FCh
> + {27, 4, PchIntA, 16}, // PCI Express Port 21
> + {27, 5, PchIntB, 17}, // PCI Express Port 22
> + {27, 6, PchIntC, 18}, // PCI Express Port 23
> + {27, 7, PchIntD, 19}, // PCI Express Port 24
> + {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R)
> + {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection
> + {19, 0, PchIntA, 20}, // Integrated Sensor Hub
> + {18, 0, PchIntA, 16}, // Thermal Subsystem
> + {18, 6, PchIntB, 24} // SerialIo: SPI #2, INTA is default, programmed in
> PCR[SERIALIO] + PCICFGCTRL[12]
> +};
> +
> +/**
> + Adds interrupt configuration for device
> +
> + @param[in/out] InterruptConfig Pointer to interrupt config
> +**/
> +VOID
> +LoadDeviceInterruptConfig (
> + IN OUT PCH_INTERRUPT_CONFIG *InterruptConfig
> + )
> +{
> + UINT8 IntConfigTableEntries;
> +
> + IntConfigTableEntries = ARRAY_SIZE (mDevIntConfig);
> + ASSERT (IntConfigTableEntries <= PCH_MAX_DEVICE_INTERRUPT_CONFIG);
> + InterruptConfig->NumOfDevIntConfig = IntConfigTableEntries;
> + CopyMem (
> + InterruptConfig->DevIntConfig,
> + mDevIntConfig,
> + sizeof (mDevIntConfig)
> + );
> +
> + if (IsPchLp ()) {
> + CopyMem (
> +
> &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig]),
> + mPchLpOnlyDevIntConfig,
> + sizeof (mPchLpOnlyDevIntConfig)
> + );
> + InterruptConfig->NumOfDevIntConfig += ARRAY_SIZE
> (mPchLpOnlyDevIntConfig);
> + } else if (IsPchH ()) {
> + CopyMem (
> +
> &(InterruptConfig->DevIntConfig[InterruptConfig->NumOfDevIntConfig]),
> + mPchHOnlyDevIntConfig,
> + sizeof (mPchHOnlyDevIntConfig)
> + );
> + InterruptConfig->NumOfDevIntConfig += ARRAY_SIZE
> (mPchHOnlyDevIntConfig);
> + }
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreM
> emPolicyLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreM
> emPolicyLib.c
> new file mode 100644
> index 0000000000..dfab5d29c2
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreM
> emPolicyLib.c
> @@ -0,0 +1,318 @@
> +/** @file
> + This file is PeiPchPreMemPolicy library.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PeiPchPolicyLibrary.h"
> +#include <Library/CpuPlatformLib.h>
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPchGeneralPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
> + PchGeneralPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO,
> "PchGeneralPreMemConfig->Header.GuidHob.Name = %g\n",
> &PchGeneralPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + PCH general premem configuration
> + ********************************/
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadDciPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
> + DciPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Name =
> %g\n", &DciPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "DciPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> DciPreMemConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + DCI Configuration
> + ********************************/
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadWatchDogPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
> + WdtPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Name =
> %g\n", &WdtPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "WdtPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> WdtPreMemConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPchTraceHubPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_TRACE_HUB_PREMEM_CONFIG *PchTraceHubPreMemConfig;
> + PchTraceHubPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO,
> "PchTraceHubPreMemConfig->Header.GuidHob.Name = %g\n",
> &PchTraceHubPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PchTraceHubPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> PchTraceHubPreMemConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = {
> + 0xA0,
> + 0xA2,
> + 0xA4,
> + 0xA6
> +};
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadSmbusPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
> + SmbusPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Name =
> %g\n", &SmbusPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "SmbusPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> SmbusPreMemConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + SMBus configuration
> + ********************************/
> + SmbusPreMemConfig->Enable = TRUE;
> + SmbusPreMemConfig->DynamicPowerGating = TRUE;
> + SmbusPreMemConfig->SpdWriteDisable = TRUE;
> + SmbusPreMemConfig->SmbusIoBase = PcdGet16
> (PcdSmbusBaseAddress);
> + ASSERT (sizeof (mSmbusRsvdAddresses) <=
> PCH_MAX_SMBUS_RESERVED_ADDRESS);
> + SmbusPreMemConfig->NumRsvdSmbusAddresses = sizeof
> (mSmbusRsvdAddresses);
> + CopyMem (
> + SmbusPreMemConfig->RsvdSmbusAddressTable,
> + mSmbusRsvdAddresses,
> + sizeof (mSmbusRsvdAddresses)
> + );
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadLpcPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
> + LpcPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Name =
> %g\n", &LpcPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "LpcPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> LpcPreMemConfig->Header.GuidHob.Header.HobLength));
> +
> + /********************************
> + LPC Configuration
> + ********************************/
> + LpcPreMemConfig->EnhancePort8xhDecoding = TRUE;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadHsioPciePreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
> + HsioPciePreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Name =
> %g\n", &HsioPciePreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "HsioPciePreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> HsioPciePreMemConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadHsioSataPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
> + HsioSataPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Name =
> %g\n", &HsioSataPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "HsioSataPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> HsioSataPreMemConfig->Header.GuidHob.Header.HobLength));
> +}
> +
> +/**
> + Get Hsio Sata Pre Mem Config Policy
> +
> + @param[in] SiPolicy The RC Policy PPI instance
> + @param[in] SataCtrlIndex SATA controller index
> +
> + @retval Pointer to Hsio Sata Pre Mem Config Policy
> +**/
> +PCH_HSIO_SATA_PREMEM_CONFIG *
> +GetPchHsioSataPreMemConfig (
> + IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy,
> + IN UINT32 SataCtrlIndex
> + )
> +{
> + PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
> + EFI_STATUS Status;
> +
> + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ());
> +
> + Status = GetConfigBlock ((VOID *) SiPreMemPolicy,
> &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
> + ASSERT_EFI_ERROR (Status);
> +
> + HsioSataPreMemConfig += SataCtrlIndex;
> +
> + return HsioSataPreMemConfig;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadPcieRpPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
> + UINT32 RpIndex;
> +
> + PcieRpPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =
> %g\n", &PcieRpPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> PcieRpPreMemConfig->Header.GuidHob.Header.HobLength));
> +
> + for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); RpIndex ++) {
> + PcieRpPreMemConfig->RpEnabledMask |= (UINT32) (1 << RpIndex);
> + }
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadHdAudioPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_HDAUDIO_PREMEM_CONFIG *HdaPreMemConfig;
> + HdaPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =
> %g\n", &HdaPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> HdaPreMemConfig->Header.GuidHob.Header.HobLength));
> + HdaPreMemConfig->Enable = 1;
> +}
> +
> +/**
> + Load Config block default
> +
> + @param[in] ConfigBlockPointer Pointer to config block
> +**/
> +VOID
> +LoadIshPreMemConfigDefault (
> + IN VOID *ConfigBlockPointer
> + )
> +{
> + PCH_ISH_PREMEM_CONFIG *IshPreMemConfig;
> + IshPreMemConfig = ConfigBlockPointer;
> +
> + DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name =
> %g\n", &IshPreMemConfig->Header.GuidHob.Name));
> + DEBUG ((DEBUG_INFO,
> "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n",
> IshPreMemConfig->Header.GuidHob.Header.HobLength));
> + //Enable ISH controller for Non-Desktop sku platforms
> + if (GetCpuSku () != EnumCpuTrad) {
> + IshPreMemConfig->Enable = TRUE;
> + }
> +}
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY
> mPchIpBlocksPreMem [] = {
> + {&gPchGeneralPreMemConfigGuid, sizeof
> (PCH_GENERAL_PREMEM_CONFIG),
> PCH_GENERAL_PREMEM_CONFIG_REVISION,
> LoadPchGeneralPreMemConfigDefault},
> + {&gDciPreMemConfigGuid, sizeof (PCH_DCI_PREMEM_CONFIG),
> DCI_PREMEM_CONFIG_REVISION, LoadDciPreMemConfigDefault},
> + {&gWatchDogPreMemConfigGuid, sizeof
> (PCH_WDT_PREMEM_CONFIG),
> WATCH_DOG_PREMEM_CONFIG_REVISION,
> LoadWatchDogPreMemConfigDefault},
> + {&gPchTraceHubPreMemConfigGuid, sizeof
> (PCH_TRACE_HUB_PREMEM_CONFIG),
> PCH_TRACEHUB_PREMEM_CONFIG_REVISION,
> LoadPchTraceHubPreMemConfigDefault},
> + {&gSmbusPreMemConfigGuid, sizeof
> (PCH_SMBUS_PREMEM_CONFIG), SMBUS_PREMEM_CONFIG_REVISION,
> LoadSmbusPreMemConfigDefault},
> + {&gLpcPreMemConfigGuid, sizeof (PCH_LPC_PREMEM_CONFIG),
> LPC_PREMEM_CONFIG_REVISION, LoadLpcPreMemConfigDefault},
> + {&gHsioPciePreMemConfigGuid, sizeof
> (PCH_HSIO_PCIE_PREMEM_CONFIG),
> HSIO_PCIE_PREMEM_CONFIG_REVISION,
> LoadHsioPciePreMemConfigDefault},
> + {&gHsioSataPreMemConfigGuid, sizeof
> (PCH_HSIO_SATA_PREMEM_CONFIG),
> HSIO_SATA_PREMEM_CONFIG_REVISION,
> LoadHsioSataPreMemConfigDefault},
> + {&gPcieRpPreMemConfigGuid, sizeof
> (PCH_PCIE_RP_PREMEM_CONFIG), PCIE_RP_PREMEM_CONFIG_REVISION,
> LoadPcieRpPreMemConfigDefault},
> + {&gHdAudioPreMemConfigGuid, sizeof
> (PCH_HDAUDIO_PREMEM_CONFIG),
> HDAUDIO_PREMEM_CONFIG_REVISION,
> LoadHdAudioPreMemConfigDefault},
> + {&gIshPreMemConfigGuid, sizeof (PCH_ISH_PREMEM_CONFIG),
> ISH_PREMEM_CONFIG_REVISION, LoadIshPreMemConfigDefault},
> +};
> +
> +/**
> + Get PCH PREMEM config block table total size.
> +
> + @retval Size of PCH PREMEM config block table
> +**/
> +UINT16
> +EFIAPI
> +PchGetPreMemConfigBlockTotalSize (
> + VOID
> + )
> +{
> + return GetComponentConfigBlockTotalSize (&mPchIpBlocksPreMem[0],
> sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
> +}
> +
> +/**
> + PchAddPreMemConfigBlocks add all PCH PREMEM config blocks.
> +
> + @param[in] ConfigBlockTableAddress The pointer to add PCH PREMEM
> config blocks
> +
> + @retval EFI_SUCCESS The policy default is initialized.
> + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create
> buffer
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchAddPreMemConfigBlocks (
> + IN VOID *ConfigBlockTableAddress
> + )
> +{
> + DEBUG ((DEBUG_INFO, "PCH AddPreMemConfigBlocks\n"));
> +
> + return AddComponentConfigBlocks (ConfigBlockTableAddress,
> &mPchIpBlocksPreMem[0], sizeof (mPchIpBlocksPreMem) / sizeof
> (COMPONENT_BLOCK_ENTRY));
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
> new file mode 100644
> index 0000000000..2210344462
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
> @@ -0,0 +1,109 @@
> +/** @file
> + PCH RESET PEIM DRIVER.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Ppi/Reset2.h>
> +#include <Ppi/PchReset.h>
> +#include <Library/PchResetLib.h>
> +#include <Library/ResetSystemLib.h>
> +
> +
> +/**
> + Resets the entire platform.
> +
> + @param[in] ResetType UEFI defined reset type.
> + @param[in] ResetStatus The status code for the reset.
> + @param[in] DataSize The size of ResetData in bytes.
> + @param[in] ResetData Optional element used to introduce a
> platform specific reset.
> + The exact type of the reset is defined by the
> EFI_GUID that follows
> + the Null-terminated Unicode string.
> +
> +**/
> +VOID
> +EFIAPI
> +ResetSystem (
> + IN EFI_RESET_TYPE ResetType,
> + IN EFI_STATUS ResetStatus,
> + IN UINTN DataSize,
> + IN VOID *ResetData OPTIONAL
> + )
> +{
> + switch (ResetType) {
> + case EfiResetWarm:
> + ResetWarm ();
> + break;
> +
> + case EfiResetCold:
> + ResetCold ();
> + break;
> +
> + case EfiResetShutdown:
> + ResetShutdown ();
> + return;
> +
> + case EfiResetPlatformSpecific:
> + ResetPlatformSpecific (DataSize, ResetData);
> + return;
> +
> + default:
> + return;
> + }
> +
> + //
> + // Given we should have reset getting here would be bad
> + //
> + ASSERT (FALSE);
> + CpuDeadLoop();
> +}
> +
> +/**
> + Initialize PCH Reset APIs
> +
> + @retval EFI_SUCCESS APIs are installed successfully
> + @retval EFI_OUT_OF_RESOURCES Can't allocate pool
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchInitializeReset (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> + EFI_PEI_RESET2_PPI *EfiPeiReset2Ppi;
> + EFI_PEI_PPI_DESCRIPTOR *EfiPeiReset2Descriptor;
> +
> + DEBUG ((DEBUG_INFO, "PchInitializeReset() Start\n"));
> +
> +
> + EfiPeiReset2Descriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool
> (sizeof (EFI_PEI_PPI_DESCRIPTOR));
> + EfiPeiReset2Ppi = (EFI_PEI_RESET2_PPI *) AllocateZeroPool (sizeof
> (EFI_PEI_RESET2_PPI));
> + if ((EfiPeiReset2Descriptor == NULL) ||
> + (EfiPeiReset2Ppi == NULL)) {
> + ASSERT (FALSE);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ///
> + /// Initialize the EFI Reset2 ppi instance
> + ///
> + EfiPeiReset2Ppi->ResetSystem = ResetSystem;
> +
> + EfiPeiReset2Descriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
> + EfiPeiReset2Descriptor->Guid = &gEfiPeiReset2PpiGuid;
> + EfiPeiReset2Descriptor->Ppi = EfiPeiReset2Ppi;
> +
> + Status = PeiServicesInstallPpi (EfiPeiReset2Descriptor);
> + ASSERT_EFI_ERROR (Status);
> +
> + DEBUG ((DEBUG_INFO, "PchInitializeReset() End\n"));
> +
> + return Status;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.c
> new file mode 100644
> index 0000000000..58f2d86103
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiReset
> SystemLib.c
> @@ -0,0 +1,257 @@
> +/** @file
> + System reset library services.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/PchResetLib.h>
> +#include <Library/ResetSystemLib.h>
> +#include <Library/PmcLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Ppi/PchReset.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsPmc.h>
> +
> +/**
> + Dump reset message for debug build readability
> +**/
> +VOID
> +DumpResetMessage (
> + VOID
> + )
> +{
> + DEBUG_CODE_BEGIN ();
> + UINTN Index;
> + //
> + // ******************************
> + // ** SYSTEM REBOOT !!! **
> + // ******************************
> + //
> + for (Index = 0; Index < 30; Index++) {
> + DEBUG ((DEBUG_INFO, "*"));
> + }
> + DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
> + for (Index = 0; Index < 30; Index++) {
> + DEBUG ((DEBUG_INFO, "*"));
> + }
> + DEBUG ((DEBUG_INFO, "\n"));
> + DEBUG_CODE_END ();
> +}
> +/**
> + Execute call back function for Pch Reset.
> +
> + @param[in] ResetType Reset Types which includes GlobalReset.
> + @param[in] ResetTypeGuid Pointer to an EFI_GUID, which is the Reset
> Type Guid.
> +**/
> +VOID
> +PchResetCallback (
> + IN EFI_RESET_TYPE ResetType,
> + IN EFI_GUID *ResetTypeGuid
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Instance;
> + PCH_RESET_CALLBACK_PPI *PchResetCallbackPpi;
> +
> + Instance = 0;
> + do {
> + Status = PeiServicesLocatePpi (
> + &gPchResetCallbackPpiGuid,
> + Instance,
> + NULL,
> + (VOID **) &PchResetCallbackPpi
> + );
> +
> + switch (Status) {
> + case EFI_SUCCESS:
> + PchResetCallbackPpi->ResetCallback (ResetType, ResetTypeGuid);
> + break;
> + case EFI_NOT_FOUND:
> + break;
> + default:
> + ASSERT_EFI_ERROR (Status);
> + break;
> + }
> + ++Instance;
> + } while (Status == EFI_SUCCESS);
> +}
> +
> +/**
> + Calling this function causes a system-wide reset. This sets
> + all circuitry within the system to its initial state. This type of reset
> + is asynchronous to system operation and operates without regard to
> + cycle boundaries.
> +
> + System reset should not return, if it returns, it means the system does
> + not support cold reset.
> +**/
> +VOID
> +EFIAPI
> +ResetCold (
> + VOID
> + )
> +{
> + //
> + // Loop through callback functions of PchResetCallback PPI
> + //
> + PchResetCallback (EfiResetCold, NULL);
> + DumpResetMessage ();
> +
> + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
> +}
> +
> +/**
> + Calling this function causes a system-wide initialization. The processors
> + are set to their initial state, and pending cycles are not corrupted.
> +
> + System reset should not return, if it returns, it means the system does
> + not support warm reset.
> +**/
> +VOID
> +EFIAPI
> +ResetWarm (
> + VOID
> + )
> +{
> + //
> + // Loop through callback functions of PchResetCallback PPI
> + //
> + PchResetCallback (EfiResetWarm, NULL);
> + DumpResetMessage ();
> +
> + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_HARDRESET);
> +}
> +
> +/**
> + Calling this function causes the system to enter a power state equivalent
> + to the ACPI G2/S5 or G3 states.
> +
> + System shutdown should not return, if it returns, it means the system does
> + not support shut down reset.
> +**/
> +VOID
> +EFIAPI
> +ResetShutdown (
> + VOID
> + )
> +{
> + UINT16 ABase;
> + UINT32 Data32;
> +
> + //
> + // Loop through callback functions of PchResetCallback PPI
> + //
> + PchResetCallback (EfiResetShutdown, NULL);
> +
> + ABase = PmcGetAcpiBase ();
> + ///
> + /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the
> system from S5
> + ///
> + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_GPE0_EN_127_96), 0);
> +
> + ///
> + /// Secondly, PwrSts register must be cleared
> + ///
> + /// Write a "1" to bit[8] of power button status register at
> + /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
> + ///
> + IoWrite16 ((UINTN) (ABase + R_ACPI_IO_PM1_STS),
> B_ACPI_IO_PM1_STS_PWRBTN);
> +
> + ///
> + /// Finally, transform system into S5 sleep state
> + ///
> + Data32 = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT));
> +
> + Data32 = (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP +
> B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5);
> +
> + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT), Data32);
> +
> + Data32 = Data32 | B_ACPI_IO_PM1_CNT_SLP_EN;
> +
> + DumpResetMessage ();
> +
> + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_PM1_CNT), Data32);
> +
> + return;
> +}
> +
> +/**
> + Internal function to execute the required HECI command for GlobalReset,
> + if failed will use PCH Reest.
> +
> +**/
> +STATIC
> +VOID
> +PchGlobalReset (
> + VOID
> + )
> +{
> + //
> + // Loop through callback functions of PchResetCallback PPI
> + //
> + PchResetCallback (EfiResetPlatformSpecific, &gPchGlobalResetGuid);
> +
> + //
> + // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
> + //
> + PmcEnableCf9GlobalReset ();
> +
> + DumpResetMessage ();
> +
> + IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
> +}
> +
> +/**
> + Calling this function causes the system to enter a power state for platform
> specific.
> +
> + @param[in] DataSize The size of ResetData in bytes.
> + @param[in] ResetData Optional element used to introduce a
> platform specific reset.
> + The exact type of the reset is defined by the
> EFI_GUID that follows
> + the Null-terminated Unicode string.
> +
> +**/
> +VOID
> +EFIAPI
> +ResetPlatformSpecific (
> + IN UINTN DataSize,
> + IN VOID *ResetData OPTIONAL
> + )
> +{
> + EFI_GUID *GuidPtr;
> +
> + if (ResetData == NULL) {
> + DEBUG ((DEBUG_ERROR, "[PeiResetSystemLib] ResetData is not
> available.\n"));
> + return;
> + }
> + GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
> + if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
> + PchGlobalReset();
> + } else {
> + return;
> + }
> +}
> +
> +/**
> + Calling this function causes the system to enter a power state for capsule
> update.
> +
> + Reset update should not return, if it returns, it means the system does
> + not support capsule update.
> +
> +**/
> +VOID
> +EFIAPI
> +EnterS3WithImmediateWake (
> + VOID
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c
> new file mode 100644
> index 0000000000..1a5db7f24a
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiSpiLib/PchSpi.c
> @@ -0,0 +1,217 @@
> +/** @file
> + PCH SPI PEI Library implements the SPI Host Controller Compatibility
> Interface.
> +
> + Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Ppi/Spi.h>
> +#include <Private/Library/PchSpiCommonLib.h>
> +#include <PchReservedResources.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +
> +typedef struct {
> + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
> + SPI_INSTANCE SpiInstance;
> +} PEI_SPI_INSTANCE;
> +
> +/**
> + PCI Enumeratuion is not done till later in DXE
> + Initlialize SPI BAR0 to a default value till enumeration is done
> + also enable memory space decoding for SPI
> +
> +**/
> +VOID
> +InitSpiBar0 (
> + VOID
> + )
> +{
> + UINT64 PchSpiBase;
> + PchSpiBase = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + 0
> + );
> + PciSegmentAnd8 (PchSpiBase + PCI_COMMAND_OFFSET, (UINT8)
> ~EFI_PCI_COMMAND_MEMORY_SPACE);
> + PciSegmentWrite32 (PchSpiBase + R_SPI_CFG_BAR0,
> PCH_SPI_BASE_ADDRESS);
> + PciSegmentOr8 (PchSpiBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> +}
> +
> +/**
> + This function Initial SPI services
> +
> + @retval EFI_STATUS Results of the installation of the SPI services
> +**/
> +EFI_STATUS
> +EFIAPI
> +SpiServiceInit (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> + PEI_SPI_INSTANCE *PeiSpiInstance;
> + SPI_INSTANCE *SpiInstance;
> + PCH_SPI_PPI *SpiPpi;
> +
> + Status = PeiServicesLocatePpi (
> + &gPchSpiPpiGuid,
> + 0,
> + NULL,
> + (VOID **)&SpiPpi
> + );
> +
> + if (Status != EFI_SUCCESS) {
> + DEBUG ((DEBUG_INFO, "SpiServiceInit() Start\n"));
> +
> + //
> + // PCI Enumeratuion is not done till later in DXE
> + // Initlialize SPI BAR0 to a default value till enumeration is done
> + // also enable memory space decoding for SPI
> + //
> + InitSpiBar0 ();
> +
> + PeiSpiInstance = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof
> (PEI_SPI_INSTANCE));
> + if (NULL == PeiSpiInstance) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + SpiInstance = &(PeiSpiInstance->SpiInstance);
> + SpiProtocolConstructor (SpiInstance);
> +
> + PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
> + PeiSpiInstance->PpiDescriptor.Guid = &gPchSpiPpiGuid;
> + PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol);
> +
> + ///
> + /// Install the SPI PPI
> + ///
> + DEBUG ((DEBUG_INFO, "SPI PPI Installed\n"));
> + Status = PeiServicesInstallPpi (&PeiSpiInstance->PpiDescriptor);
> + ASSERT_EFI_ERROR (Status);
> +
> + DEBUG ((DEBUG_INFO, "SpiServiceInit() End\n"));
> + }
> + else {
> + DEBUG ((DEBUG_INFO, "SPI PPI already installed\n"));
> + }
> + return Status;
> +}
> +
> +/**
> + Acquire pch spi mmio address.
> +
> + @param[in] SpiInstance Pointer to SpiInstance to initialize
> +
> + @retval PchSpiBar0 return SPI MMIO address
> +**/
> +UINTN
> +AcquireSpiBar0 (
> + IN SPI_INSTANCE *SpiInstance
> + )
> +{
> + return PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) &
> ~(B_SPI_CFG_BAR0_MASK);
> +}
> +
> +/**
> + Release pch spi mmio address. Do nothing.
> +
> + @param[in] SpiInstance Pointer to SpiInstance to initialize
> +
> + @retval None
> +**/
> +VOID
> +ReleaseSpiBar0 (
> + IN SPI_INSTANCE *SpiInstance
> + )
> +{
> +}
> +
> +/**
> + This function is a hook for Spi to disable BIOS Write Protect
> +
> + @retval EFI_SUCCESS The protocol instance was properly
> initialized
> + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in
> SMM phase
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DisableBiosWriteProtect (
> + VOID
> + )
> +{
> + UINT64 SpiBaseAddress;
> +
> + SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + 0
> + );
> + if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) &
> B_SPI_CFG_BC_EISS) != 0) {
> + return EFI_ACCESS_DENIED;
> + }
> + ///
> + /// Enable the access to the BIOS space for both read and write cycles
> + ///
> + PciSegmentOr8 (
> + SpiBaseAddress + R_SPI_CFG_BC,
> + B_SPI_CFG_BC_WPD
> + );
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This function is a hook for Spi to enable BIOS Write Protect
> +
> +
> +**/
> +VOID
> +EFIAPI
> +EnableBiosWriteProtect (
> + VOID
> + )
> +{
> + UINT64 SpiBaseAddress;
> +
> + SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> + DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> + DEFAULT_PCI_BUS_NUMBER_PCH,
> + PCI_DEVICE_NUMBER_PCH_SPI,
> + PCI_FUNCTION_NUMBER_PCH_SPI,
> + 0
> + );
> + ///
> + /// Disable the access to the BIOS space for write cycles
> + ///
> + PciSegmentAnd8 (
> + SpiBaseAddress + R_SPI_CFG_BC,
> + (UINT8) (~B_SPI_CFG_BC_WPD)
> + );
> +}
> +
> +/**
> + Check if it's granted to do flash write.
> +
> + @retval TRUE It's secure to do flash write.
> + @retval FALSE It's not secure to do flash write.
> +**/
> +BOOLEAN
> +IsSpiFlashWriteGranted (
> + VOID
> + )
> +{
> + return TRUE;
> +}
> --
> 2.16.2.windows.1
next prev parent reply other threads:[~2019-08-17 1:13 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 [this message]
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 20/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 22/37] CoffeelakeSiliconPkg/Pch: Add DXE private " Kubacki, Michael A
2019-08-17 0:52 ` Nate DeSimone
2019-08-17 1:13 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 24/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 25/37] CoffeelakeSiliconPkg/SystemAgent: Add " Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 27/37] CoffeelakeSiliconPkg/Pch: Add PchSmiDispatcher Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 28/37] CoffeelakeSiliconPkg/SystemAgent: Add modules Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 29/37] CoffeelakeSiliconPkg: Add package DSC files Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:14 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 30/37] Maintainers.txt: Add CoffeelakeSiliconPkg maintainers Kubacki, Michael A
2019-08-17 0:53 ` Nate DeSimone
2019-08-17 1:15 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 31/37] WhiskeylakeOpenBoardPkg: Add package and headers Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-19 18:09 ` Sinha, Ankit
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 32/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add headers Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:15 ` [edk2-platforms][PATCH V1 33/37] WhiskeylakeOpenBoardPkg: Add library instances Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 34/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: " Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 20:08 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 35/37] WhiskeylakeOpenBoardPkg: Add modules Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 7:50 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 36/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add DSC and build files Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:16 ` Chiu, Chasel
2019-08-17 20:11 ` Chaganty, Rangasai V
2019-08-17 0:16 ` [edk2-platforms][PATCH V1 37/37] Add WhiskeylakeOpenBoardPkg to global build config and documentation Kubacki, Michael A
2019-08-17 0:54 ` Nate DeSimone
2019-08-17 1:17 ` Chiu, Chasel
2019-08-17 20:00 ` Chaganty, Rangasai V
2019-08-19 18:14 ` [edk2-platforms][PATCH V1 00/37] Coffee Lake and Whiskey Lake support Sinha, Ankit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3C3EFB470A303B4AB093197B6777CCEC5046234E@PGSMSX111.gar.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