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