From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: nathaniel.l.desimone@intel.com) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by groups.io with SMTP; Fri, 16 Aug 2019 17:53:52 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Aug 2019 17:53:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,395,1559545200"; d="scan'208";a="195104912" Received: from orsmsx105.amr.corp.intel.com ([10.22.225.132]) by fmsmga001.fm.intel.com with ESMTP; 16 Aug 2019 17:53:50 -0700 Received: from orsmsx112.amr.corp.intel.com (10.22.240.13) by ORSMSX105.amr.corp.intel.com (10.22.225.132) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 16 Aug 2019 17:53:49 -0700 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.96]) by ORSMSX112.amr.corp.intel.com ([169.254.3.253]) with mapi id 14.03.0439.000; Fri, 16 Aug 2019 17:53:49 -0700 From: "Nate DeSimone" To: "Kubacki, Michael A" , "devel@edk2.groups.io" CC: "Chaganty, Rangasai V" , "Chiu, Chasel" , "Gao, Liming" , "Kinney, Michael D" , "Sinha, Ankit" Subject: Re: [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI private library instances Thread-Topic: [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI private library instances Thread-Index: AQHVVJEaP/yCByZjgkq0QDrRMm5VMqb+g0GQ Date: Sat, 17 Aug 2019 00:53:48 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE12AA1@ORSMSX114.amr.corp.intel.com> References: <20190817001603.30632-1-michael.a.kubacki@intel.com> <20190817001603.30632-24-michael.a.kubacki@intel.com> In-Reply-To: <20190817001603.30632-24-michael.a.kubacki@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiM2E2NDZmZTQtNGYwNi00ZjAwLWI1Y2QtODRiN2QzMjlkMDhkIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiaWRwaVwvY1FMdVwvOFUzTVdwKzRuZk5INTBqNDE2MFZ5b0EzWGt6T1IxVkxOdlhBS1R5enBoK0JtSWxESHRJS0lWIn0= x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.139] MIME-Version: 1.0 Return-Path: nathaniel.l.desimone@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone -----Original Message----- From: Kubacki, Michael A=20 Sent: Friday, August 16, 2019 5:16 PM To: devel@edk2.groups.io Cc: Chaganty, Rangasai V ; Chiu, Chasel ; Desimone, Nathaniel L = ; Gao, Liming ; Kinney, Michael D ; Sinha, Ankit Subject: [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI= private library instances REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D2082 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 Cc: Chasel Chiu Cc: Nate DeSimone Cc: Liming Gao Cc: Michael D Kinney Cc: Ankit Sinha Signed-off-by: Michael Kubacki --- Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/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/PeiDxeSmmPchInitCom= monLib/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/PeiDxeSmmPmcPrivate= Lib/PeiDxeSmmPmcPrivateLibCnl.inf | 48 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PeiDxeSmmPmcPrivateLibWithS3.inf | 39 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PeiPmcPrivateLibCnl.inf | 40 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/P= eiGpioHelpersLib.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/PeiDxeSmmPmcPrivate= Lib/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/PeiDxeSmmPchInitCom= monLib/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/PeiDxeSmmPmcPrivate= Lib/PeiPmcPrivateLib.c | 92 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PmcPrivateLib.c | 1033 +++++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PmcPrivateLibClient.c | 73 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PmcPrivateLibCnl.c | 360 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivate= Lib/PmcPrivateLibWithS3.c | 194 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpersLib/P= eiGpioHelpersLib.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/PeiDxeS= mmGpioPrivateLib/PeiDxeSmmGpioPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeS= iliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateL= ibCnl.inf new file mode 100644 index 0000000000..318b54a99c --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/PeiDxeSmmGpioPrivateLibCnl.inf @@ -0,0 +1,45 @@ +## @file +# Component description file for the PeiDxeSmmGpioPrivateLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmGpioPrivateLibCnl +FILE_GUID =3D E078A734-BEA0-47CF-A476-3742316D01FC +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D GpioPrivateLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmPchDmiLib/PeiDxeSmmPchDmiLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch= /Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf new file mode 100644 index 0000000000..b36fc15901 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PeiDxeSmmPchDmiLib.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for the PeiDxeSmmPchDmiLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchDmiLib +FILE_GUID =3D 067DC1C4-2668-4F06-9921-307514B66B34 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchDmiLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf b/Silicon/Intel/CoffeelakeSiliconP= kg/Pch/Library/Private/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf new file mode 100644 index 0000000000..1eda7cdba8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PeiDxeSmmPchDmiWithS3Lib.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for the PeiDxeSmmPchDmiWithS3Lib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchDmiWithS3Lib +FILE_GUID =3D 32CCA047-6AF0-46FF-83DA-32BA62484075 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchDmiWithS3Lib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf b/Silicon/Intel/Coffeelake= SiliconPkg/Pch/Library/Private/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCo= mmonLib.inf new file mode 100644 index 0000000000..d81c428a1c --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchIn= itCommonLib/PeiDxeSmmPchInitCommonLib.inf @@ -0,0 +1,34 @@ +## @file +# Component description file for the PchInitCommonLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PeiDxeSmmPchInitCommonLib + FILE_GUID =3D E9C4FE04-8A79-43FA-B3E0-603359C31B43 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D 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/PeiDxeS= mmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf b/Silicon/In= tel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersL= ib/PeiDxeSmmPchPciExpressHelpersLib.inf new file mode 100644 index 0000000000..16b1c019b8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPc= iExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf @@ -0,0 +1,42 @@ +## @file +# Component description file for the PeiDxeSmmPchPciExpressHelpersLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchPciExpressHelpersLib +FILE_GUID =3D 07E3F76D-6D26-419d-9053-58696A15B519 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchPciExpressHelpersLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLibCnl.inf b/Silicon/Intel/Coffeel= akeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsf= PrivateLibCnl.inf new file mode 100644 index 0000000000..0ed9f30dcc --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPs= fPrivateLib/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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPchPsfPrivateLibCnl +FILE_GUID =3D 7A6C18CA-0353-433E-885D-DD68BFAD38BE +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D PchPsfPrivateLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSil= iconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibCn= l.inf new file mode 100644 index 0000000000..adb154dd14 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPmcPrivateLibCnl +FILE_GUID =3D A1CB52AD-4FAB-4214-94A0-323E3BE4E934 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D 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/PeiDxeS= mmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf b/Silicon/Intel/Coffeelake= SiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLi= bWithS3.inf new file mode 100644 index 0000000000..cd1380dc43 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiDxeSmmPmcPrivateLibWithS3 +FILE_GUID =3D 5890CA5A-1955-4A02-A09C-01E4150606CC +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D 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/PeiDxeS= mmPmcPrivateLib/PeiPmcPrivateLibCnl.inf b/Silicon/Intel/CoffeelakeSiliconPk= g/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLibCnl.inf new file mode 100644 index 0000000000..ab3645c61d --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/PeiPmcPrivateLibCnl.inf @@ -0,0 +1,40 @@ +## @file +# PEI PCH PMC Private Lib for Cannon Lake PCH. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiPmcPrivateLibCnl +FILE_GUID =3D 1DD4EA23-12F2-4F05-93AF-535476106D8C +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D 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/PeiGpio= HelpersLib/PeiGpioHelpersLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/L= ibrary/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.inf new file mode 100644 index 0000000000..b6f786d80b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpers= Lib/PeiGpioHelpersLib.inf @@ -0,0 +1,42 @@ +## @file +# Component description file for the PeiGpioHelpersLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiGpioHelpersLib +FILE_GUID =3D 1838E1E7-3CC4-4A74-90D9-B421EF2A579F +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D GpioHelpersLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiGpio= NameBufferLib/PeiGpioNameBufferLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg= /Pch/Library/Private/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf new file mode 100644 index 0000000000..3619a2e6a7 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBuf= ferLib/PeiGpioNameBufferLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for the PeiGpioMemLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PeiGpioNameBufferLib +FILE_GUID =3D 16EC5CA8-8195-4847-B6CB-662CDAB863F2 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D PEIM +LIBRARY_CLASS =3D GpioNameBufferLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/PeiDxeS= mmGpioPrivateLib/GpioNativePrivateLibInternal.h b/Silicon/Intel/CoffeelakeS= iliconPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibI= nternal.h new file mode 100644 index 0000000000..e081027c40 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/GpioNativePrivateLibInternal.h @@ -0,0 +1,477 @@ +/** @file + Header file for GPIO Private Lib Internal functions. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_ +#define _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_ + +#include + +#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 ce= rtain values + according to below formula: + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period)= . + RTC clock with f =3D 32 KHz is used for glitch filter. + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us). + Supported DebounceTime values are following: + DebounceTime =3D 0 -> Debounce feature disabled + DebounceTime > 0 && < 250us -> Not supported + DebounceTime =3D 250us - 1024000us -> Supported range (DebounceTime =3D= 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 =3D 0, Debouncer featur= e 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 DebounceD= uration 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/PeiDxeS= mmPchDmiLib/PchDmi14.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pri= vate/PeiDxeSmmPchDmiLib/PchDmi14.h new file mode 100644 index 0000000000..1d50c04b0f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmi14.h @@ -0,0 +1,70 @@ +/** @file + Internal header file for PCH DMI library for SIP14 + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __PCH_DMI_14_H__ +#define __PCH_DMI_14_H__ + +#include +#include + +/** + 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 L= ock 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 programi= ng + @param[out] DmiVcCtlAddress DMI Virtual Channel Control register ad= dress + @param[out] DmiVcStsAddress DMI Virtual Channel Status register add= ress +**/ +VOID +PchDmi14VcRegs ( + IN PCH_DMI_VC_TYPE Vc, + OUT UINT16 *DmiVcCtlAddress, + OUT UINT16 *DmiVcStsAddress + ); + + +#endif diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchDmiLib/PchDmi15.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pri= vate/PeiDxeSmmPchDmiLib/PchDmi15.h new file mode 100644 index 0000000000..744a96fe14 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmi15.h @@ -0,0 +1,113 @@ +/** @file + Internal header file for PCH DMI library for SIP15 + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __PCH_DMI_15_H__ +#define __PCH_DMI_15_H__ + +#include +#include + +/** + 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 L= ock 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 programi= ng + @param[out] DmiVcCtlAddress DMI Virtual Channel Control register ad= dress + @param[out] DmiVcStsAddress DMI Virtual Channel Status register add= ress +**/ +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/PeiDxeS= mmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/Silicon/Intel/Cof= feelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchP= ciExpressHelpersLibrary.h new file mode 100644 index 0000000000..b14f24b18f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPc= iExpressHelpersLib/PchPciExpressHelpersLibrary.h @@ -0,0 +1,42 @@ +/** @file + Header file for PCH Pci Express helps library implementation. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_ +#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + B= IT7 + 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/PeiDxeS= mmPchPsfPrivateLib/PchPsfPrivateLibInternal.h b/Silicon/Intel/CoffeelakeSil= iconPkg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibInter= nal.h new file mode 100644 index 0000000000..f633df0411 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPs= fPrivateLib/PchPsfPrivateLibInternal.h @@ -0,0 +1,490 @@ +/** @file + This file contains internal header for PSF lib usage + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PCH_PSF_PRIVATE_LIB_INTERNAL_H_ +#define _PCH_PSF_PRIVATE_LIB_INTERNAL_H_ + +#include +#include + +#define PSF_PORT_NULL ((PSF_PORT){0,0}) +#define PSF_IS_PORT_NULL(PsfPort) ((PsfPort.PsfPid =3D=3D 0) && (PsfPort.R= egBase =3D=3D 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 conn= ected + + @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 =3D=3D 0)= && ((PsfTopoPort).PortId =3D=3D 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 Gra= ntCount 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 Po= rts + + @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 d= ata +**/ +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 giv= en 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 P= ort + + @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/PeiDxeS= mmPmcPrivateLib/PmcPrivateLibInternal.h b/Silicon/Intel/CoffeelakeSiliconPk= g/Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibInternal.h new file mode 100644 index 0000000000..c08d1cf10d --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/PmcPrivateLibInternal.h @@ -0,0 +1,47 @@ +/** @file + Internal header file for PMC Private library + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + 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 signal= s 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/PeiDxeS= mmGpioPrivateLib/GpioNamesCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Li= brary/Private/PeiDxeSmmGpioPrivateLib/GpioNamesCnl.c new file mode 100644 index 0000000000..5a4876bfeb --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/GpioNamesCnl.c @@ -0,0 +1,166 @@ +/** @file + This file contains GPIO name library implementation + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC CONST CHAR8* mGpioGppaNames[] =3D { + "ESPI_CLK_LOOPBK" +}; + +STATIC CONST CHAR8* mGpioGppbNames[] =3D { + "GSPI0_CLK_LOOPBK", + "GSPI1_CLK_LOOPBK" +}; + +STATIC CONST CHAR8* mGpioGpdNames[] =3D { + "SLP_LANB", + "SLP_SUSB", + "SLP_WAKEB", + "SLP_DRAM_RESETB" +}; + +STATIC CONST CHAR8* mGpioGppiNames[] =3D { + "SYS_PWROK", + "SYS_RESETB", + "MLK_RSTB" +}; + +STATIC CONST CHAR8* mGpioSpiNames[] =3D { + "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[] =3D { + "HDA_BCLK", + "HDA_RSTB", + "HDA_SYNC", + "HDA_SDO", + "HDA_SDI_0", + "HDA_SDI_1", + "SSP1_SFRM", + "SSP1_TXD" +}; + +STATIC CONST CHAR8* mGpioJtagNames[] =3D { + "JTAG_TDO", + "JTAGX", + "PRDYB", + "PREQB", + "CPU_TRSTB", + "JTAG_TDI", + "JTAG_TMS", + "JTAG_TCK", + "ITP_PMODE" +}; + +STATIC CONST CHAR8* mGpioHvmosNames[] =3D { + "HVMOS_L_BKLTEN", + "HVMOS_L_BKLCTL", + "HVMOS_L_VDDEN", + "HVMOS_SYS_PWROK", + "HVMOS_SYS_RESETB", + "HVMOS_MLK_RSTB" +}; + +STATIC CONST CHAR8* mGpioCpuNames[] =3D { + "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[] =3D { + 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[] =3D { + 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/PeiDxeS= mmGpioPrivateLib/GpioNativePrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPk= g/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c new file mode 100644 index 0000000000..affecf9ec0 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GpioNativePrivateLibInternal.h" +#include +#include +#include + +/** + 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + ZeroMem(&GpioConfig, sizeof(GPIO_CONFIG)); + GpioConfig.ElectricalConfig =3D GpioTermination; + + for (Index =3D 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++= ) { + GpioConfig.PadMode =3D I2cGpio[Index].Mode; + + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PinsUsed; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < NumOfSpiPins; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < NumOfSpiPins; Index++) { + Status =3D 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 =3D 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 =3D=3D 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 =3D SdCardGpio[0].Mode; + PwrEnConfig.Direction =3D GpioDirOut; + PwrEnConfig.HostSoftPadOwn =3D GpioHostOwnAcpi; + PwrEnConfig.InterruptConfig =3D GpioIntDis; + PwrEnConfig.PowerConfig =3D GpioHostDeepReset; + PwrEnConfig.LockConfig =3D GpioPadUnlock; + GpioSetPadConfig (SdCardGpio[0].Pad, &PwrEnConfig); + + for (Index =3D 1; Index < NumOfSdCardPins; Index++) { + Status =3D GpioSetPadMode (SdCardGpio[Index].Pad, SdCardGpio[Index].Mo= de); + 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]ScsSdCardGpi= o internal organization): + // GPP_G0 =3D 1 + // GPP_G4 =3D 5 + // + if (Index >=3D 1 && Index <=3D 5) { + Status =3D GpioSetPadElectricalConfig (SdCardGpio[Index].Pad, GpioTe= rmNative); + 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 =3D GpioGetScsSdCardDetectPin (); + PadConfig.PadMode =3D GpioPadModeGpio; + PadConfig.Direction =3D GpioDirIn; + PadConfig.HostSoftPadOwn =3D GpioHostOwnGpio; + PadConfig.InterruptConfig =3D GpioIntBothEdge; + PadConfig.PowerConfig =3D GpioHostDeepReset; + + // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mod= e. + 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < NumOfEmmcPins; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < NumOfHdaLinkPins; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_HDA_DMIC_NUMBER_OF_PINS; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_HDA_SSP_NUMBER_OF_PINS; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_HDA_SNDW_NUMBER_OF_PINS; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_SMBUS_NUMBER_OF_PINS; Index++) { + Status =3D 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 =3D GpioGetPadMode (DevSlpNativePad.Pad, &GpioMode); + + if (EFI_ERROR (Status) || (GpioMode !=3D DevSlpNativePad.Mode)) { + if (DevSlpPad !=3D NULL) { + *DevSlpPad =3D GPIO_PAD_NONE; + } + return FALSE; + } else { + if (DevSlpPad !=3D NULL) { + *DevSlpPad =3D 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 =3D=3D GpioPadModeNative1) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Cannot enable SATAGP%d, %a already u= sed 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 =3D ClkReqGpio.Mode; + PadConfig.Direction =3D GpioDirNone; + PadConfig.PowerConfig =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + // + // Configure HPD, VDD and BKLT Pins for eDP panel + // + for (Index =3D 0; Index < EdpPinsNumber; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_DDP_NUMBER_OF_PINS; Index++) { + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + // + // Configure CNVi BRI and RGI buses for high speed communication with CR= F + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS; Index++)= { + Status =3D GpioSetPadMode (CnviBriRgiExternalPad[Index].Pad, CnviBriRg= iExternalPad[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 =3D=3D NULL) || + (VUartForCnviBtPad =3D=3D NULL)) { + return EFI_UNSUPPORTED; + } + + // + // Configure CNVi Bluetooth UART for certain connection + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VCnviBtUartPad[Index], VCnviBtUartPadMode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable virtual connection for UART for Bluetooth + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VUartForCnviBtPad[Index], VUartForCnviBtPad= Mode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable CNVi BT UART on external pads + // + if (ConnectionType =3D=3D GpioCnviBtUartToExternalPads) { + + GpioGetCnviBtUartExternalPins (&CnviBtUartExternalPad); + + if (CnviBtUartExternalPad =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) = { + Status =3D GpioSetPadMode (CnviBtUartExternalPad[Index].Pad, CnviBtU= artExternalPad[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 =3D=3D NULL) || + (VSspForCnviBtPad =3D=3D NULL)) { + return EFI_UNSUPPORTED; + } + + // + // Configure CNVi Bluetooth I2S for certain connection + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VCnviBtI2sPad[Index], VCnviBtI2sPadMode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable virtual connection for SSP for Bluetooth + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VSspForCnviBtPad[Index], VSspForCnviBtPadMo= de); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable CNV BT I2S on external pads + // + if (ConnectionType =3D=3D (VGPIO_CNVI_BT_I2S_CONNECTION_TYPE) GpioCnviBt= I2sToExternalPads) { + + GpioGetCnviBtI2sExternalPins (&CnviBtI2sExternalPad); + + if (CnviBtI2sExternalPad =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (CnviBtI2sExternalPad[Index].Pad, CnviBtI2= sExternalPad[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 =3D=3D NULL) || + (VUartForCnviMfUart1Pad =3D=3D NULL)) { + return EFI_UNSUPPORTED; + } + + // + // Configure CNVi MFUART1 for certain connection + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VCnviMfUart1Pad[Index], VCnviMfUart1PadMode= ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable virtual connection for MFUART1 + // + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) { + Status =3D GpioSetPadMode (VUartForCnviMfUart1Pad[Index], VUartForCnvi= MfUart1PadMode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_UNSUPPORTED; + } + } + + // + // Enable CNV MFUART1 on external pads + // + if (ConnectionType =3D=3D GpioCnviMfUart1ToExternalPads) { + + GpioGetCnviMfUart1ExternalPins (&CnviMfUart1ExternalPad); + + if (CnviMfUart1ExternalPad =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < PCH_GPIO_CNVI_UART_NUMBER_OF_PINS; Index++) = { + Status =3D GpioSetPadMode (CnviMfUart1ExternalPad[Index].Pad, CnviMf= Uart1ExternalPad[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 =3D GpioPadModeGpio; + PadConfig.HostSoftPadOwn =3D GpioHostOwnGpio; + PadConfig.Direction =3D GpioDirOut; + if (Value =3D=3D 1) { + PadConfig.OutputState =3D GpioOutHigh; + } else { + PadConfig.OutputState =3D GpioOutLow; + } + CnviBtEnPad =3D GpioGetCnviBtEnablePin (); + + // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mod= e and it is GPO + GpioUnlockPadCfg (CnviBtEnPad); + GpioUnlockPadCfgTx (CnviBtEnPad); + Status =3D 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 =3D GpioPadModeGpio; + PadConfig.Direction =3D GpioDirOut; + if (BtInterface =3D=3D GpioCnviBtIfUsb) { + PadConfig.OutputState =3D GpioOutHigh; + } else { + PadConfig.OutputState =3D GpioOutLow; + } + + Status =3D 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 Char= ging 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 =3D GpioPadModeGpio; + CnviBtChargingPadConfig.Direction =3D GpioDirOut; + + if (BtWirelessCharging =3D=3D 1) { + CnviBtChargingPadConfig.OutputState =3D GpioOutHigh; + + GpioGetCnviA4WpPin (&A4WpPad); + + Status =3D GpioSetPadMode (A4WpPad.Pad, A4WpPad.Mode); + ASSERT_EFI_ERROR (Status); + + } else { + CnviBtChargingPadConfig.OutputState =3D GpioOutLow; + } + + Status =3D GpioSetPadConfig (GpioGetCnviBtChargingPin (), &CnviBtChargin= gPadConfig); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + This function enables and configures CNVi Bluetooth Host wake-up interru= pt + + @param[in] None + + @retval Status +**/ +EFI_STATUS +GpioConfigureCnviBtHostWakeInt ( + VOID + ) +{ + EFI_STATUS Status; + GPIO_PAD CnviBtHostWakeIntPad; + GPIO_CONFIG PadConfig; + + ZeroMem (&PadConfig, sizeof (PadConfig)); + + PadConfig.PadMode =3D GpioPadModeGpio; + PadConfig.Direction =3D GpioDirIn; + PadConfig.HostSoftPadOwn =3D GpioHostOwnGpio; + PadConfig.InterruptConfig =3D GpioIntEdge; + PadConfig.PowerConfig =3D GpioHostDeepReset; + CnviBtHostWakeIntPad =3D GpioGetCnviBtHostWakeIntPin (); + + // Unlock GPIO pad due to Host Software Pad Ownership is GPIO Driver mod= e. + GpioUnlockPadCfg (CnviBtHostWakeIntPad); + Status =3D 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 =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + for (Index =3D 0; Index < NoOfNativePins; Index++) { + Status =3D GpioSetPadMode (ImguClkOutGpio[Index].Pad, ImguClkOutGpio[I= ndex].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 acco= rding + to below formula are supported: + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period)= . + RTC clock with f =3D 32 KHz is used for glitch filter. + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us). + Supported DebounceTime values are following: + DebounceTime =3D 0 -> Debounce feature disabled + DebounceTime > 0 && < 250us -> Not supported + DebounceTime =3D 250us - 1024000us -> Supported range (DebounceTime =3D= 250us * 2^n) + For values not supported by HW, they will be rounded down to closest sup= ported one + + @param[in] DebounceTime Debounce Time in microseconds + If Debounce Time =3D 0, Debouncer feature wil= l be disabled + Function will set DebounceTime argument to ro= unded supported value +**/ +VOID +GpioSetPwrBtnDebounceTimer ( + IN UINT32 DebounceTime + ) +{ + GpioSetDebounceTimer (GpioGetPwrBtnPin (), &DebounceTime); +} + +/** + Configure LPC GPIO +**/ +VOID +LpcConfigureGpio ( + VOID + ) +{ + GPIO_PAD GpioPad; + GpioPad =3D GpioGetLpcPin(); + + if (GpioPad =3D=3D 0) { + return; + } else { + GpioSetPadElectricalConfig (GpioPad, GpioTermWpu20K); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmGpioPrivateLib/GpioNativePrivateLibCnl.c b/Silicon/Intel/CoffeelakeSilico= nPkg/Pch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibCnl.c new file mode 100644 index 0000000000..4cff00c27b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/GpioNativePrivateLibCnl.c @@ -0,0 +1,2275 @@ +/** @file + This file contains specific GPIO information + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GpioNativePrivateLibInternal.h" + +// +// I2C controller pins +// I2C[controller number][pin: SDA/SCL] +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio [][PC= H_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=3D +{ + {{GPIO_CNL_LP_GPP_C16, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_C17, GpioPa= dModeNative1}}, + {{GPIO_CNL_LP_GPP_C18, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_C19, GpioPa= dModeNative1}}, + {{GPIO_CNL_LP_GPP_H4, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H5 , GpioPa= dModeNative1}}, + {{GPIO_CNL_LP_GPP_H6, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H7 , GpioPa= dModeNative1}}, + {{GPIO_CNL_LP_GPP_H8, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H9 , GpioPa= dModeNative1}}, + {{GPIO_CNL_LP_GPP_H10, GpioPadModeNative1}, {GPIO_CNL_LP_GPP_H11, GpioPa= dModeNative1}} +}; + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio [][PC= H_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=3D +{ + {{GPIO_CNL_H_GPP_C16, GpioPadModeNative1}, {GPIO_CNL_H_GPP_C17, GpioPadM= odeNative1}}, // I2C0 + {{GPIO_CNL_H_GPP_C18, GpioPadModeNative1}, {GPIO_CNL_H_GPP_C19, GpioPadM= odeNative1}}, // I2C1 + {{GPIO_CNL_H_GPP_D13, GpioPadModeNative3}, {GPIO_CNL_H_GPP_D14, GpioPadM= odeNative3}}, // I2C2 + {{GPIO_CNL_H_GPP_D4, GpioPadModeNative2}, {GPIO_CNL_H_GPP_D23, GpioPadM= odeNative2}} // 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 =3D mPchLpI2cGpio[SerialIoI2cControllerNumber]; + return; + } + } else { + if (SerialIoI2cControllerNumber < ARRAY_SIZE (mPchHI2cGpio)) { + *NativePinsTable =3D mPchHI2cGpio[SerialIoI2cControllerNumber]; + return; + } + } + *NativePinsTable =3D NULL; + ASSERT (FALSE); +} +// +// UART controller pins +// UART[controller number][pin: RXD/TXD/RTSB/CTSB] +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio [][P= CH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=3D +{ + { // 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 [][PC= H_SERIAL_IO_PINS_PER_UART_CONTROLLER]=3D +{ + { // 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 =3D SerialIoUartControllerNumber; + + if ((SerialIoUartControllerNumber =3D=3D 0) && (PinMuxing =3D=3D 1)) { + // Last record is for UART0 second pin set + if (IsPchLp ()) { + UartGpioIndex =3D ARRAY_SIZE (mPchLpUartGpio) - 1; + } else { + UartGpioIndex =3D ARRAY_SIZE (mPchHUartGpio) - 1; + } + } + + if (HardwareFlowControl) { + *NoOfNativePins =3D PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER; + } else { + *NoOfNativePins =3D PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTR= L; + } + + if (IsPchLp ()) { + if (UartGpioIndex < ARRAY_SIZE (mPchLpUartGpio)) { + *NativePinsTable =3D mPchLpUartGpio[UartGpioIndex]; + return; + } + } else { + if (UartGpioIndex < ARRAY_SIZE (mPchHUartGpio)) { + *NativePinsTable =3D mPchHUartGpio[UartGpioIndex]; + return; + } + } + + *NativePinsTable =3D NULL; + *NoOfNativePins =3D 0; + ASSERT (FALSE); +} + +// +// SPI controller pins +// SPI[controller number][pin: CSB/CLK/MISO/MOSI] +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio [][PC= H_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=3D +{ + { // 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]=3D +{ + { // 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 =3D mPchLpSpiGpio[SerialIoSpiControllerNumber]; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpSpiGpio[SerialIoSpiController= Number]); + return; + } + } else { + if (SerialIoSpiControllerNumber < ARRAY_SIZE (mPchHSpiGpio)) { + *NativePinsTable =3D mPchHSpiGpio[SerialIoSpiControllerNumber]; + *NoOfNativePins =3D ARRAY_SIZE (mPchHSpiGpio[SerialIoSpiControllerN= umber]); + return; + } + } + *NativePinsTable =3D NULL; + *NoOfNativePins =3D 0; + ASSERT (FALSE); +} + +// +// ISH GP pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[] = =3D +{ + {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[] = =3D +{ + {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 =3D mPchLpIshGPGpio[IshGpPinNumber]; + return; + } + } else { + if (IshGpPinNumber < ARRAY_SIZE (mPchHIshGPGpio)) { + *NativePin =3D mPchHIshGPGpio[IshGpPinNumber]; + return; + } + } + *NativePin =3D (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] =3D +{ + { // 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] =3D +{ + { // 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 =3D mPchLpIshUartGpio[IshUartControllerNumber]; + return; + } + } else { + if (IshUartControllerNumber < ARRAY_SIZE (mPchHIshUartGpio)) { + *NativePinsTable =3D mPchHIshUartGpio[IshUartControllerNumber]; + return; + } + } + *NativePinsTable =3D 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] =3D +{ + { // 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[][P= CH_ISH_PINS_PER_I2C_CONTROLLER] =3D +{ + { // 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 =3D mPchLpIshI2cGpio[IshI2cControllerNumber]; + return; + } + } else { + if (IshI2cControllerNumber < ARRAY_SIZE (mPchHIshI2cGpio)) { + *NativePinsTable =3D mPchHIshI2cGpio[IshI2cControllerNumber]; + return; + } + } + *NativePinsTable =3D NULL; + ASSERT (FALSE); +} + +// +// ISH SPI controller pins +// ISH SPI[pin: CSB/CLK/MISO/MOSI] +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PC= H_ISH_PINS_PER_SPI_CONTROLLER] =3D +{ + {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] =3D +{ + {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 =3D mPchLpIshSpiGpio; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpIshSpiGpio); + return; + } + } else { + if (IshSpiControllerNumber < ARRAY_SIZE (mPchHIshSpiGpio)) { + *NativePinsTable =3D mPchHIshSpiGpio; + *NoOfNativePins =3D ARRAY_SIZE (mPchHIshSpiGpio); + return; + } + } + + *NoOfNativePins =3D 0; + *NativePinsTable =3D NULL; + ASSERT (FALSE); +} + +// +// GPIO pins for SD controller +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpScsSdCardGpio= [9] =3D +{ + {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] =3D +{ + {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 =3D mPchLpScsSdCardGpio; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpScsSdCardGpio); + } else { + *NativePinsTable =3D mPchHScsSdCardGpio; + *NoOfNativePins =3D 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[1= 2] =3D +{ + {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 =3D mPchLpScsEmmcGpio; + *NoOfNativePins =3D 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[P= CH_GPIO_HDA_LINK_NUMBER_OF_PINS] =3D +{ + {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[PC= H_GPIO_HDA_LINK_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpHdaLinkGpio; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpHdaLinkGpio); + } else { + *NativePinsTable =3D mPchHHdaLinkGpio; + *NoOfNativePins =3D 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] =3D +{ + { // 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] =3D +{ + { // 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 =3D mPchLpHdaDmicGpio[DmicNumber]; + return; + } + } else { + if (DmicNumber < ARRAY_SIZE (mPchHHdaDmicGpio)) { + *NativePinsTable =3D mPchHHdaDmicGpio[DmicNumber]; + return; + } + } + *NativePinsTable =3D 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 mPchLpHdaSspInterfa= ceGpio[][PCH_GPIO_HDA_SSP_NUMBER_OF_PINS] =3D +{ + { // 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 mPchHHdaSspInterfac= eGpio[][PCH_GPIO_HDA_SSP_NUMBER_OF_PINS] =3D +{ + { // 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 =3D mPchLpHdaSspInterfaceGpio[SspInterfaceNumber]; + return; + } + } else { + if (SspInterfaceNumber < ARRAY_SIZE (mPchHHdaSspInterfaceGpio)) { + *NativePinsTable =3D mPchHHdaSspInterfaceGpio[SspInterfaceNumber]; + return; + } + } + *NativePinsTable =3D NULL; + ASSERT (FALSE); +} + +// +// GPIO Pin for HD Audio SSP_MCLK/I2S_MCLK +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpHdaSspMasterC= lockGpio =3D {GPIO_CNL_LP_GPP_D23, GpioPadModeNative1}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHHdaSspMasterCl= ockGpio =3D {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, mPchLpHdaSspMa= sterClockGpio.Mode); + } else { + return GpioSetPadMode (mPchHHdaSspMasterClockGpio.Pad, mPchHHdaSspMast= erClockGpio.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] =3D +{ + { // 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] =3D +{ + { // 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 =3D mPchLpHdaSndwGpio[SndwInterfaceNumber]; + return; + } + } else { + if (SndwInterfaceNumber < ARRAY_SIZE (mPchHHdaSndwGpio)) { + *NativePinsTable =3D mPchHHdaSndwGpio[SndwInterfaceNumber]; + return; + } + } + *NativePinsTable =3D NULL; + ASSERT (FALSE); +} + +// +// GPIO pins for SMBUS +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSmbusGpio[PCH= _GPIO_SMBUS_NUMBER_OF_PINS] =3D +{ + {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] =3D +{ + {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 =3D mPchLpSmbusGpio; + } else { + *NativePinsTable =3D mPchHSmbusGpio; + } +} + +// +// SMBUS Alert pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSmbusAlertGpi= o =3D {GPIO_CNL_LP_GPP_C2, GpioPadModeNative1}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSmbusAlertGpio= =3D {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 =3D mPchLpSmbusAlertGpio; + } else { + SmbusAlertGpio =3D 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 mPchLpSataDevSlpPin= ToGpioMap[] =3D +{ + {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 mPchHSataDevSlpPinT= oGpioMap[] =3D +{ + {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 mCdfPchSata1DevSlpP= inToGpioMap[] =3D +{ +/// @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 mCdfPchSata2DevSlpP= inToGpioMap[] =3D +{ +/// @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 mCdfPchSata3DevSlpP= inToGpioMap[] =3D +{ +/// @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 =3D=3D SATA_1_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata1DevSlpPinToGpioMap)) { + *NativePin =3D mCdfPchSata1DevSlpPinToGpioMap[SataPort]; + return; + } + } else if (SataCtrlIndex =3D=3D SATA_2_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata2DevSlpPinToGpioMap)) { + *NativePin =3D mCdfPchSata2DevSlpPinToGpioMap[SataPort]; + return; + } + } else if (SataCtrlIndex =3D=3D SATA_3_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata3DevSlpPinToGpioMap)) { + *NativePin =3D mCdfPchSata3DevSlpPinToGpioMap[SataPort]; + return; + } + } + } else { + if (IsPchLp ()) { + if (SataPort < ARRAY_SIZE (mPchLpSataDevSlpPinToGpioMap)) { + *NativePin =3D mPchLpSataDevSlpPinToGpioMap[SataPort]; + return; + } + } else { + if (SataPort < ARRAY_SIZE (mPchHSataDevSlpPinToGpioMap)) { + *NativePin =3D mPchHSataDevSlpPinToGpioMap[SataPort]; + return; + } + } + } + *NativePin =3D (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 mPchLpSataGpToGpioM= ap[] =3D +{ + {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 mPchHSataGpToGpioMa= p[] =3D +{ + {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 mCdfPchSata1GpToGpi= oMap[] =3D +{ +/// @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 mCdfPchSata2GpToGpi= oMap[] =3D +{ +/// @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 mCdfPchSata3GpToGpi= oMap[] =3D +{ +/// @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 =3D=3D SATA_1_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata1GpToGpioMap)) { + *NativePin =3D mCdfPchSata1GpToGpioMap[SataPort]; + return; + } + } else if (SataCtrlIndex =3D=3D SATA_2_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata2GpToGpioMap)) { + *NativePin =3D mCdfPchSata2GpToGpioMap[SataPort]; + return; + } + } else if (SataCtrlIndex =3D=3D SATA_3_CONTROLLER_INDEX) { + if (SataPort < ARRAY_SIZE (mCdfPchSata3GpToGpioMap)) { + *NativePin =3D mCdfPchSata3GpToGpioMap[SataPort]; + return; + } + } + } else { + if (IsPchLp ()) { + if (SataPort < ARRAY_SIZE (mPchLpSataGpToGpioMap)) { + *NativePin =3D mPchLpSataGpToGpioMap[SataPort]; + return; + } + } else { + if (SataPort < ARRAY_SIZE (mPchHSataGpToGpioMap)) { + *NativePin =3D mPchHSataGpToGpioMap[SataPort]; + return; + } + } + } + *NativePin =3D (GPIO_PAD_NATIVE_FUNCTION){0}; + ASSERT (FALSE); +} + +// +// SATA LED pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataLedGpio = =3D {GPIO_CNL_LP_GPP_E8, GpioPadModeNative1}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataLedGpio = =3D {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 =3D mPchLpSataLedGpio; + } else { + SataLedGpio =3D mPchHSataLedGpio; + } + + return GpioSetPadMode (SataLedGpio.Pad, SataLedGpio.Mode); +} + +// +// USB2 OC pins +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUsbOcGpioPins= [] =3D +{ + {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[= ] =3D +{ + {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 >=3D ARRAY_SIZE (mPchLpUsbOcGpioPins)) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + OcGpio =3D mPchLpUsbOcGpioPins[OcPinNumber]; + } else { + if (OcPinNumber >=3D ARRAY_SIZE (mPchHUsbOcGpioPins)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + OcGpio =3D 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 mPchLpPcieSrcClkReq= bPinToGpioMap[] =3D +{ + {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 mPchHPcieSrcClkReqb= PinToGpioMap[] =3D +{ + {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 =3D mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex]; + return; + } + } else { + if (ClkreqIndex < ARRAY_SIZE (mPchHPcieSrcClkReqbPinToGpioMap)) { + *NativePin =3D mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex]; + return; + } + } + *NativePin =3D (GPIO_PAD_NATIVE_FUNCTION){0}; + ASSERT (FALSE); +} + +// +// PCHHOTB pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin = =3D {GPIO_CNL_LP_GPP_B23, GpioPadModeNative2}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin =3D= {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 =3D mPchLpPchHotbPin; + } else { + PchHotbPin =3D mPchHPchHotbPin; + } + + return GpioSetPadMode (PchHotbPin.Pad, PchHotbPin.Mode); +} + +// +// VRALERTB pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpVrAlertbPin = =3D {GPIO_CNL_LP_GPP_B2, GpioPadModeNative1}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHVrAlertbPin = =3D {GPIO_CNL_H_GPP_B2, GpioPadModeNative1}; + +// +// CPU_C10_GATE pin +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuC10GatePin= =3D {GPIO_CNL_LP_GPP_H18, GpioPadModeNative1}; +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuC10GatePin = =3D {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 =3D mPchLpVrAlertbPin; + } else { + VrAlertGpio =3D 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 =3D mPchLpCpuC10GatePin; + } else { + CpuC10GateGpio =3D mPchHCpuC10GatePin; + } + + return GpioSetPadMode (CpuC10GateGpio.Pad, CpuC10GateGpio.Mode); +} + +// +// CPU GP pins +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[P= CH_GPIO_CPU_GP_NUMBER_OF_PINS] =3D +{ + {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[PC= H_GPIO_CPU_GP_NUMBER_OF_PINS] =3D +{ + {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 >=3D ARRAY_SIZE (mPchLpCpuGpPinMap)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + CpuGpPin =3D mPchLpCpuGpPinMap[CpuGpPinNum]; + } else { + if (CpuGpPinNum >=3D ARRAY_SIZE (mPchHCpuGpPinMap)) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + CpuGpPin =3D mPchHCpuGpPinMap[CpuGpPinNum]; + } + + return GpioSetPadMode (CpuGpPin.Pad, CpuGpPin.Mode); +} + +// +// DDSP_HPD pins +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpDdspHpdPins[]= =3D +{ + {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[] = =3D +{ + {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 =3D DdspHpdPin - GpioDdspHpd0; + + if (IsPchLp ()) { + if (DdspHpdPinIndex >=3D ARRAY_SIZE (mPchLpDdspHpdPins)) { + goto Error; + } + DdspHpdGpio =3D mPchLpDdspHpdPins[DdspHpdPinIndex]; + } else { + if (DdspHpdPinIndex >=3D ARRAY_SIZE (mPchHDdspHpdPins)) { + goto Error; + } + DdspHpdGpio =3D 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_G= PIO_EDP_NUMBER_OF_PINS] =3D +{ + {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_GP= IO_EDP_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpEdpPins; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpEdpPins); + } else { + *NativePinsTable =3D mPchHEdpPins; + *NoOfNativePins =3D ARRAY_SIZE (mPchHEdpPins); + } +} + +// +// DDPB/C/D/F CTRLCLK and CTRLDATA pins +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpDdpInterfaceP= ins[PCH_GPIO_DDP_NUMBER_OF_INTERFACES][PCH_GPIO_DDP_NUMBER_OF_PINS] =3D +{ + {// 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 mPchHDdpInterfacePi= ns[PCH_GPIO_DDP_NUMBER_OF_INTERFACES][PCH_GPIO_DDP_NUMBER_OF_PINS] =3D +{ + {// 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 =3D DdpInterface - GpioDdpB; + break; + case GpioDdpF: + DdpInterfaceIndex =3D 3; + break; + default: + goto Error; + } + + if (IsPchLp ()) { + if (DdpInterfaceIndex < ARRAY_SIZE (mPchLpDdpInterfacePins)) { + *NativePinsTable =3D mPchLpDdpInterfacePins[DdpInterfaceIndex]; + return; + } + } else { + if (DdpInterfaceIndex < ARRAY_SIZE (mPchHDdpInterfacePins)) { + *NativePinsTable =3D mPchHDdpInterfacePins[DdpInterfaceIndex]; + return; + } + } +Error: + *NativePinsTable =3D 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 =3D GPIO_CNL_LP_GPP_H1; + PadMode =3D GpioPadModeNative3; + } else { + GpioPad =3D GPIO_CNL_H_GPP_D5; + PadMode =3D GpioPadModeNative3; + } + + Status =3D 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 =3D GPIO_CNL_LP_GPP_H2; + PadMode =3D GpioPadModeNative3; + } else { + GpioPad =3D GPIO_CNL_H_GPP_D6; + PadMode =3D GpioPadModeNative3; + } + + Status =3D 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 =3D GpioPadModeNative1; + if (IsPchLp ()) { + GpioNativePad->Pad =3D GPIO_CNL_LP_GPP_F23; + } else { + GpioNativePad->Pad =3D 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_C= NVI_UART_NUMBER_OF_PINS] =3D +{ + 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_CN= VI_UART_NUMBER_OF_PINS] =3D +{ + 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_GPI= O_CNVI_UART_NUMBER_OF_PINS] =3D +{ + 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] =3D +{ + 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 =3D mPchLpVCnviBtUartGpioPad; + *VUartForCnviBtPad =3D mPchLpVUartForCnviBtGpioPad; + } else { + *VCnviBtUartPad =3D mPchHVCnviBtUartGpioPad; + *VUartForCnviBtPad =3D mPchHVUartForCnviBtGpioPad; + } + + switch (ConnectionType) { + case GpioCnviBtUartToSerialIoUart0: + *VCnviBtUartPadMode =3D GpioPadModeNative1; + *VUartForCnviBtPadMode =3D GpioPadModeNative1; + break; + case GpioCnviBtUartToIshUart0: + *VCnviBtUartPadMode =3D GpioPadModeNative2; + *VUartForCnviBtPadMode =3D GpioPadModeNative1; + break; + case GpioCnviBtUartNotConnected: + case GpioCnviBtUartToExternalPads: + *VCnviBtUartPadMode =3D GpioPadModeGpio; + *VUartForCnviBtPadMode =3D GpioPadModeGpio; + break; + default: + ASSERT (FALSE); + return; + } +} + +// +// CNVi Bluetooth UART external pads +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviBtUartExt= ernalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =3D +{ + {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 mPchHCnviBtUartExte= rnalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpCnviBtUartExternalPads; + } else { + *NativePinsTable =3D mPchHCnviBtUartExternalPads; + } +} + +// +// CNVi Bluetooth I2S pads +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVCnviBtI2sGpioPad[PCH_GPIO_CN= VI_SSP_NUMBER_OF_PINS] =3D +{ + 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_CNV= I_SSP_NUMBER_OF_PINS] =3D +{ + 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] =3D +{ + 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] =3D +{ + 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 =3D mPchLpVCnviBtI2sGpioPad; + *VSspForCnviBtPad =3D mPchLpVSspForCnviBtGpioPad; + } else { + *VCnviBtI2sPad =3D mPchHVCnviBtI2sGpioPad; + *VSspForCnviBtPad =3D mPchHVSspForCnviBtGpioPad; + } + + switch (ConnectionType) { + case GpioCnviBtI2sToSsp0: + *VCnviBtI2sPadMode =3D GpioPadModeNative1; + *VSspForCnviBtPadMode =3D GpioPadModeNative1; + break; + case GpioCnviBtI2sToSsp1: + *VCnviBtI2sPadMode =3D GpioPadModeNative2; + *VSspForCnviBtPadMode =3D GpioPadModeNative1; + break; + case GpioCnviBtI2sToSsp2: + *VCnviBtI2sPadMode =3D GpioPadModeNative3; + *VSspForCnviBtPadMode =3D GpioPadModeNative1; + break; + case GpioCnviBtI2sNotConnected: + case GpioCnviBtI2sToExternalPads: + *VCnviBtI2sPadMode =3D GpioPadModeGpio; + *VSspForCnviBtPadMode =3D GpioPadModeGpio; + break; + default: + ASSERT (FALSE); + return; + } +} + +// +// CNVi Bluetooth I2S external pads +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviBtI2sExte= rnalPads[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =3D +{ + {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 mPchHCnviBtI2sExter= nalPads[PCH_GPIO_CNVI_SSP_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpCnviBtI2sExternalPads; + } else { + *NativePinsTable =3D mPchHCnviBtI2sExternalPads; + } +} + +// +// CNVi MFUART1 pads +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD mPchLpVCnviMfUart1GpioPad[PCH_GPIO_= CNVI_UART_NUMBER_OF_PINS] =3D +{ + 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_C= NVI_UART_NUMBER_OF_PINS] =3D +{ + 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[PC= H_GPIO_CNVI_UART_NUMBER_OF_PINS] =3D +{ + 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] =3D +{ + 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 =3D mPchLpVCnviMfUart1GpioPad; + *VUartForCnviMfUart1Pad =3D mPchLpVUartForCnviMfUart1GpioPad; + } else { + *VCnviMfUart1Pad =3D mPchHVCnviMfUart1GpioPad; + *VUartForCnviMfUart1Pad =3D mPchHVUartForCnviMfUart1GpioPad; + } + + switch (ConnectionType) { + case GpioCnviMfUart1ToSerialIoUart2: + *VCnviMfUart1PadMode =3D GpioPadModeNative2; + *VUartForCnviMfUart1PadMode =3D GpioPadModeNative1; + break; + case GpioCnviMfUart1ToIshUart0: + *VCnviMfUart1PadMode =3D GpioPadModeNative1; + *VUartForCnviMfUart1PadMode =3D GpioPadModeNative1; + break; + case GpioCnviMfUart1NotConnected: + case GpioCnviMfUart1ToExternalPads: + *VCnviMfUart1PadMode =3D GpioPadModeGpio; + *VUartForCnviMfUart1PadMode =3D GpioPadModeGpio; + break; + default: + ASSERT (FALSE); + return; + } +} + +// +// CNVi MFUART1 external pads +// +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCnviMfUart1Ex= ternalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =3D +{ + {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 mPchHCnviMfUart1Ext= ernalPads[PCH_GPIO_CNVI_UART_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpCnviMfUart1ExternalPads; + } else { + *NativePinsTable =3D 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 mPchLpCnviBriRgiGpi= oPad[PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS] =3D +{ + {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 mPchHCnviBriRgiGpio= Pad[PCH_GPIO_CNVI_BRI_RGI_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpCnviBriRgiGpioPad; + } else { + *NativePinsTable =3D 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 reg= ardless 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 =3D GpioPadModeGpio; + PadConfig.Direction =3D GpioDirOut; + if (WiFiMode =3D=3D GpioCnviWiFiEnabled) { + PadConfig.OutputState =3D GpioOutHigh; + } else { + PadConfig.OutputState =3D GpioOutLow; + } + + if (IsPchLp ()) { + CnviWifiModePad =3D GPIO_CNL_LP_VGPIO2; + } else { + CnviWifiModePad =3D GPIO_CNL_H_VGPIO2; + } + + Status =3D GpioSetPadConfig (CnviWifiModePad, &PadConfig); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpImguClkOutGpi= oPad[SA_GPIO_IMGUCLK_NUMBER_OF_PINS] =3D +{ + {GPIO_CNL_LP_GPP_D4, GpioPadModeNative1}, // IMGCLKOUT_0 + {GPIO_CNL_LP_GPP_H20, GpioPadModeNative1}, // IMGCLKOUT_1 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHImguClkOutGpio= Pad[SA_GPIO_IMGUCLK_NUMBER_OF_PINS] =3D +{ + {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 =3D mPchLpImguClkOutGpioPad; + *NoOfNativePins =3D ARRAY_SIZE (mPchLpImguClkOutGpioPad); + } else { + *NativePinsTable =3D mPchHImguClkOutGpioPad; + *NoOfNativePins =3D 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 () =3D=3D 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/PeiDxeS= mmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/= Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c new file mode 100644 index 0000000000..2cf11c6da2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/GpioPrivateLib.c @@ -0,0 +1,752 @@ +/** @file + This file contains GPIO routines for RC usage + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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) =3D=3D 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 =3D GpioGetGroupIndexFromGroup (Group); + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + // + // Check if group argument exceeds GPIO GROUP INFO array + // + if ((UINTN) GroupIndex >=3D GpioGroupInfoLength) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + *RegVal =3D MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Commu= nity, 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 =3D GpioGetGroupIndexFromGroup (Group); + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + // + // Check if group argument exceeds GPIO GROUP INFO array + // + if ((UINTN) GroupIndex >=3D GpioGroupInfoLength) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + MmioWrite32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offse= t), 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 R= egisters + @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 =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + PadNumber =3D 0; + GroupIndex =3D 0; + for (GroupIndex =3D 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) { + PadNumber =3D Index; + if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) { + // + // Found group and pad number + // + break; + } + Index =3D Index - GpioGroupInfo[GroupIndex].PadPerGroup; + } + + // + // Check if legal pad number + // + if (PadNumber >=3D GpioGroupInfo[GroupIndex].PadPerGroup){ + return EFI_INVALID_PARAMETER; + } + + // + // Check if selected group has GPI SMI Enable and Status registers + // + if (GpioGroupInfo[GroupIndex].SmiEnOffset =3D=3D NO_REGISTER_FOR_PROPERT= Y) { + return EFI_INVALID_PARAMETER; + } + + GpioGroup =3D GpioGetGroupFromGroupIndex (GroupIndex); + *GpioPin =3D GpioGetGpioPadFromGroupAndPadNumber (GpioGroup, PadNumber); + + DEBUG_CODE_BEGIN (); + // + // Check if selected GPIO Pad is not owned by CSME/ISH/IE + // + GpioGetPadOwnership (*GpioPin, &PadOwnVal); + if (PadOwnVal !=3D GpioPadOwnHost) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a not owned by host!\n", GpioName (= *GpioPin))); + return EFI_INVALID_PARAMETER; + } + DEBUG_CODE_END (); + + *GpiSmiBitOffset =3D (UINT8)(PadNumber % 32); + + HostSwOwnRegOffset =3D GpioGroupInfo[GroupIndex].HostOwnOffset + (PadNum= ber / 32) * 0x4; + *GpiHostSwOwnRegAddress =3D PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].C= ommunity, HostSwOwnRegOffset); + + SmiStsRegOffset =3D GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber = / 32) * 0x4; + *GpiSmiStsRegAddress =3D PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Comm= unity, 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 =3D (UINT32)~(B_GPIO_PCR_MISCCFG_IRQ_ROUTE); + Data32Or =3D (UINT32)Irq << N_GPIO_PCR_MISCCFG_IRQ_ROUTE; + + NoOfGpioComs =3D GpioGetComSbiPortIds (&GpioComSbiIds); + + // + // Program MISCCFG register for each community + // + for (GpioComIndex =3D 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 =3D GpioGetGroupIndexFromGpioPad (GpioPad); + + GpioGroupInfo =3D 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 =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Create Pad Configuration register offset + // + PadCfgRegAddress =3D 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 !=3D GpioPadOwnHost) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a is not owned by host!\n", GpioNam= e (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 GPI= O 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 t= his chipset!\n", GpioPad)); + goto Error; + } + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Check if legal pin number + // + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + if (PadNumber >=3D GpioGroupInfo[GpioGetGroupIndexFromGpioPad (GpioPad)]= .PadPerGroup) { + DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible ran= ge 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 =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Create Pad Configuration register offset + // + PadCfgReg =3D 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 =3D 0; + PadCfgLockTx =3D 0; + + // + // Check if Pad Configuration (except output state) is to be changed. + // If AND and OR masks will indicate that configuration fields (other th= an 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 =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + + GpioGroupInfo =3D GpioGetGroupInfoTable (&GpioGroupInfoLength); + + // + // Create Pad Configuration register offset + // + PadCfgReg =3D 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 !=3D (GPIO_PAD_MODE)GpioHardwareDefault) { + + PadCfgOrMask =3D (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PA= D_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 =3D GpioReadPadCfgReg (GpioPad, 0); + + *PadModeValue =3D (GPIO_PAD_MODE)(((PadCfgRegValue & B_GPIO_PCR_PAD_MODE= ) >> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPI= O_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 =3D (UINT32)~0, + // + // Enable MISCCFG.GPSIDEDPCGEn, MISCCFG.GPRCOMPCDLCGEn, MISCCFG.GPRTCDLC= GEn, + // MISCCFG.GPDLCGEn and MISCCFG.GPDPCGEn for GPIO communities + // + Data32Or =3D (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 =3D GpioGetComSbiPortIds (&GpioComSbiIds); + + // + // Configure Clock Gating in each community + // + for (GpioComIndex =3D 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_S= AI. +**/ +VOID +GpioUnlockAllPads ( + VOID + ) +{ + UINT32 DwNum; + UINT32 GroupIndex; + UINT32 NumberOfGroups; + GPIO_GROUP Group; + UINT32 LockValue; + EFI_STATUS Status; + + NumberOfGroups =3D GpioGetNumberOfGroups (); + + for (GroupIndex =3D 0; GroupIndex < NumberOfGroups; GroupIndex++) { + Group =3D GpioGetGroupFromGroupIndex (GroupIndex); + for (DwNum =3D 0; DwNum <=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (Grou= p)); DwNum++) { + + GpioGetPadCfgLockForGroupDw (Group, DwNum, &LockValue); + + if (LockValue) { + Status =3D GpioUnlockPadCfgForGroupDw (Group, DwNum, ~0u); + ASSERT_EFI_ERROR (Status); + } + + GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &LockValue); + + if (LockValue) { + Status =3D 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_LE= NGTH_MAX); +} + + +// +// For GPIO debounce feature glitch filter clock is used +// which is driven by RTC clock with f =3D 32kHz (T =3D 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 ce= rtain values + according to below formula: + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period)= . + RTC clock with f =3D 32 KHz is used for glitch filter. + DebounceTime =3D (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us). + Supported DebounceTime values are following: + DebounceTime =3D 0 -> Debounce feature disabled + DebounceTime > 0 && < 250us -> Not supported + DebounceTime =3D 250us - 1024000us -> Supported range (DebounceTime =3D= 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 =3D 0, Debouncer featur= e 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 DebounceD= uration 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 =3D 1024000; + SupportedValue =3D FALSE; + } else if ((*DebounceTime < 250) && (*DebounceTime > 0)) { + InRangeDebounceTime =3D 0; + SupportedValue =3D FALSE; + } else { + InRangeDebounceTime =3D *DebounceTime; + SupportedValue =3D TRUE; + } + + // + // DebounceValue =3D log2 (InRangeDebounceTime * f_deb_clk) + // + DebounceValue =3D 0; + Temp =3D InRangeDebounceTime * 1000 / GPIO_DEB_CLK_PERIOD_IN_NS; + + // + // Check if any rounding occurred + // + if (InRangeDebounceTime !=3D (Temp * GPIO_DEB_CLK_PERIOD_IN_NS / 1000)) = { + SupportedValue =3D FALSE; + } + + // + // Check if value is power of 2 + // + if ((Temp !=3D 0) && ((Temp & (Temp - 1)) !=3D 0)) { + SupportedValue =3D FALSE; + } + + // + // DebounceValue =3D log2 (Temp) + // + while (Temp > 1) { + Temp >>=3D 1; + DebounceValue++; + } + + if (DebounceValue > 0) { + DebounceEnable =3D B_GPIO_PCR_DEBEN; + SupportedDebounceTime =3D (1 << DebounceValue) * GPIO_DEB_CLK_PERIOD_I= N_NS / 1000; + } else { + DebounceEnable =3D 0; + SupportedDebounceTime =3D 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 =3D SupportedDebounceTime; + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmGpioPrivateLib/GpioPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/P= ch/Library/Private/PeiDxeSmmGpioPrivateLib/GpioPrivateLibCnl.c new file mode 100644 index 0000000000..a6d260f4ad --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmGpioP= rivateLib/GpioPrivateLibCnl.c @@ -0,0 +1,225 @@ +/** @file + This file contains specific GPIO information + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] =3D { + {PID_GPIOCOM0, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PAD_OWN, R_CNL_PCH_LP_GPIO_PC= R_GPP_A_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_A_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_GPP_A_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_A_PADCFG_OFFSET, CN= L_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_PC= R_GPP_B_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_B_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_GP= IO_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_G= PIO_PCR_GPP_B_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_B_PADCFG_OFFSET, CN= L_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_PC= R_GPP_C_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_C_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_GP= IO_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_G= PIO_PCR_GPP_C_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_C_PADCFG_OFFSET, CN= L_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_PC= R_GPP_D_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_D_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_GP= IO_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_G= PIO_PCR_GPP_D_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_D_PADCFG_OFFSET, CN= L_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_PC= R_GPP_E_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_E_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_GP= IO_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_G= PIO_PCR_GPP_E_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_E_PADCFG_OFFSET, CN= L_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_PC= R_GPP_F_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_F_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_GPP_F_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_F_PADCFG_OFFSET, CN= L_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_PC= R_GPP_G_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_G_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_GPP_G_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_G_PADCFG_OFFSET, CN= L_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_PC= R_GPP_H_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPP_H_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_GPP_H_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPP_H_PADCFG_OFFSET, CN= L_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_PC= R_GPD_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_GPD_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_GPD_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_GPD_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_GPD_PADCFG_OFFSET, CN= L_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_PC= R_VGPIO_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_VGPIO_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_VGPIO_0_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_VGPIO_0_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_VGPIO_PADCFG_OFFSET, CN= L_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_PC= R_SPI_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_SPI_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_SPI_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_SPI_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_SPI_PADCFG_OFFSET, CN= L_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_PC= R_AZA_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_AZA_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_AZA_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_AZA_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_AZA_PADCFG_OFFSET, CN= L_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_PC= R_CPU_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PRO= PERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_P= ROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR= _PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_CPU_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_CPU_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_CPU_PADCFG_OFFSET, CN= L_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_PC= R_JTAG_HOSTSW_OWN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PRO= PERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_P= ROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR= _PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_JTAG_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_JTAG_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_JTAG_PADCFG_OFFSET, CN= L_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_PC= R_HVMOS_HOSTSW_OWN, R_CNL_PCH_LP_GPIO_PCR_HVMOS_GPI_IS, R_CNL_PCH_LP_GPIO_P= CR_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_P= ROPERTY, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PADCFGLOCK, R_CNL_PCH_LP_G= PIO_PCR_HVMOS_PADCFGLOCKTX, R_CNL_PCH_LP_GPIO_PCR_HVMOS_PADCFG_OFFSET, CN= L_PCH_LP_GPIO_HVMOS_PAD_MAX} //CNL PCH-LP HVMOS +}; + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchHGpioGroupInfo[] =3D { + {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_G= PP_A_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_A_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_G= PP_B_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_B_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_B_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_B_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_C_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_C_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_C_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_C_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_D_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_D_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_D_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_D_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_E_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_E_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_E_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_E_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_F_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_F_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_G= PP_G_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_G_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_G_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_G_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_H_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_H_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_G= PP_I_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_I_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_I_GPI_GPE_EN, R_CNL_PCH_H_GPIO_PCR_GPP_I_SMI_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_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_G= PP_J_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_J_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_J_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_G= PP_K_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPP_K_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PP_K_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_G= PD_GPI_IE, R_CNL_PCH_H_GPIO_PCR_GPD_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_G= PD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_V= GPIO_GPI_IE, R_CNL_PCH_H_GPIO_PCR_VGPIO_GPI_GPE_STS, R_CNL_PCH_H_GPIO_PCR_V= GPIO_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, = R_CNL_PCH_H_GPIO_PCR_VGPIO_0_PADCFGLOCK, R_CNL_PCH_H_GPIO_PCR_VGPI= O_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_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPER= TY, 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 =3D ARRAY_SIZE (mPchLpGpioGroupInfo); + return mPchLpGpioGroupInfo; + } else { + *GpioGroupInfoTableLength =3D 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 =3D=3D GPIO_CNL_LP_GROUP_GPD) || (Group =3D=3D GPIO_CNL_H_GRO= UP_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 =3D GPIO_CNL_LP_GPP_A12; + } else { + GpioPad =3D 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 =3D=3D GpioPadOwnHost) { + // + // Set PadCfgLock for GPP_A_12 + // + GpioLockPadCfg (GpioPad); + } +} + +GLOBAL_REMOVE_IF_UNREFERENCED PCH_SBI_PID mGpioComSbiIds[] =3D +{ + PID_GPIOCOM0, PID_GPIOCOM1, PID_GPIOCOM2, PID_GPIOCOM3, PID_GPIOCOM4 +}; + +/** + This function provides GPIO Community PortIDs + + @param[out] NativePinsTable Table with GPIO COMMx SBI Por= tIDs + + @retval Number of communities +**/ +UINT32 +GpioGetComSbiPortIds ( + OUT PCH_SBI_PID **GpioComSbiIds + ) +{ + *GpioComSbiIds =3D mGpioComSbiIds; + return ARRAY_SIZE (mGpioComSbiIds); +} + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchLpGpioGroupToG= peMapping[] =3D { + {GPIO_CNL_LP_GROUP_GPP_A, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_A, V_CN= L_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_CN= L_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_CN= L_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_CN= L_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_CN= L_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_CN= L_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_CN= L_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_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPP_H}, + {GPIO_CNL_LP_GROUP_GPD, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_GPD, V_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_GPD}, + {GPIO_CNL_LP_GROUP_VGPIO , 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_VGPIO, V_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_VGPIO}, + {GPIO_CNL_LP_GROUP_SPI, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_SPI, V_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_SPI}, + {GPIO_CNL_LP_GROUP_AZA, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_AZA, V_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_AZA}, + {GPIO_CNL_LP_GROUP_JTAG, 0, V_CNL_PCH_LP_PMC_PWRM_GPIO_CFG_JTAG, V_CN= L_PCH_LP_GPIO_PCR_MISCCFG_GPE0_JTAG} +}; + +GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchHGpioGroupToGp= eMapping[] =3D { + {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 desi= red 1-Tier GPE mapping + + @param[out] GpioGroupToGpeMapping Table with GPIO Group to GPE ma= pping + @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 =3D mPchLpGpioGroupToGpeMapping; + *GpioGroupToGpeMappingLength =3D ARRAY_SIZE (mPchLpGpioGroupToGpeMappi= ng); + } else { + *GpioGroupToGpeMapping =3D mPchHGpioGroupToGpeMapping; + *GpioGroupToGpeMappingLength =3D ARRAY_SIZE (mPchHGpioGroupToGpeMappin= g); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchDmiLib/PchDmi14.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pri= vate/PeiDxeSmmPchDmiLib/PchDmi14.c new file mode 100644 index 0000000000..2f9b6a7e6f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmi14.c @@ -0,0 +1,67 @@ +/** @file + This file contains functions for PCH DMI SIP14 + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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) !=3D 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 L= ock setting + @param[out] SrlRegMask Mask for Secure Register Lock setting +**/ +VOID +PchDmi14SrlRegData ( + OUT UINT16 *SrlRegOffset, + OUT UINT32 *SrlRegMask + ) +{ + *SrlRegMask =3D B_PCH_DMI14_PCR_DMIC_SRL; + *SrlRegOffset =3D R_PCH_DMI14_PCR_DMIC; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchDmiLib/PchDmi15.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pri= vate/PeiDxeSmmPchDmiLib/PchDmi15.c new file mode 100644 index 0000000000..c711b3de39 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmi15.c @@ -0,0 +1,113 @@ +/** @file + This file contains functions for PCH DMI SIP15 + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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_M= PC_SRL) !=3D 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 =3D (UINT32)~(B_PCH_DMI15_PCR_UPHWAWC_TS3TW | B_PCH_DMI15_PCR_= UPHWAWC_TS2TW | + B_PCH_DMI15_PCR_UPHWAWC_TS1TW | B_PCH_DMI15_PCR_UP= HWAWC_TS0TW); + Data32Or =3D (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 =3D (UINT32)~(B_PCH_DMI15_PCR_UPHWAWC_TS3TW | B_PCH_DMI15_PCR_= UPHWAWC_TS2TW | + B_PCH_DMI15_PCR_UPHWAWC_TS1TW | B_PCH_DMI15_PCR_UP= HWAWC_TS0TW); + Data32Or =3D (DmiThermalThrottling.ThermalSensor3TargetWidth << N_PCH_D= MI15_PCR_UPHWAWC_TS3TW) | + (DmiThermalThrottling.ThermalSensor2TargetWidth << N_PCH_DMI= 15_PCR_UPHWAWC_TS2TW) | + (DmiThermalThrottling.ThermalSensor1TargetWidth << N_PCH_DMI= 15_PCR_UPHWAWC_TS1TW) | + (DmiThermalThrottling.ThermalSensor0TargetWidth << N_PCH_DMI= 15_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 L= ock setting + @param[out] SrlRegMask Mask for Secure Register Lock setting +**/ +VOID +PchDmi15SrlRegData ( + OUT UINT16 *SrlRegOffset, + OUT UINT32 *SrlRegMask + ) +{ + *SrlRegMask =3D B_PCH_DMI15_PCR_MPC_SRL; + *SrlRegOffset =3D R_PCH_DMI15_PCR_MPC; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchDmiLib/PchDmiLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Pr= ivate/PeiDxeSmmPchDmiLib/PchDmiLib.c new file mode 100644 index 0000000000..f1b2867659 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmiLib.c @@ -0,0 +1,569 @@ +/** @file + PCH DMI library. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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 of= fset 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_TC= OBASE_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 =3D (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA); + Data32 |=3D (UINT32) Address; + Data32 |=3D 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 =3D (UINT32) (((Length - 1) << 16) & B_LPC_CFG_GENX_DEC_IODRA); + Data32 |=3D (UINT32) Address; + Data32 |=3D B_LPC_CFG_GENX_DEC_EN; + // + // Program eSPI Generic IO Range #, PCR[DMI] + 27BCh to the same value p= rogrammed 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 pr= ogrammed 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 programm= ed 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 programm= ed 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) = !=3D 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 pr= ogrammed 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 sett= ings. + + @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 val= ue 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 se= ttings. + + @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 val= ue 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 purp= oses. + /// By default PCH will forward IO port 80h cycles to LPC bus. The Reser= ved 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 examp= le, 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 acc= ordingly to point + /// to the root port that decode this range. Reading from Port 80h may n= ot return valid values + /// if the POST-card itself do not shadow the writes. Unlike LPC, PCIe d= oes not shadow the Port 80 writes. + /// + PsfRpDestinationId =3D PsfPcieDestinationId ((UINT32)RpNumber); + + DmiRpDestinationId =3D (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_R= PR >> 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 cycl= es 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 uC= ode 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/PeiDxeS= mmPchDmiLib/PchDmiWithS3Lib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Libr= ary/Private/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c new file mode 100644 index 0000000000..9778c9a252 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchDm= iLib/PchDmiWithS3Lib.c @@ -0,0 +1,79 @@ +/** @file + PCH DMI library with S3 boot script support. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PchDmi14.h" +#include "PchDmi15.h" + +/** + Configure PCH DMI Lock +**/ +VOID +PchDmiSetLockWithS3BootScript ( + VOID + ) +{ + UINT32 Data32Or; + UINT32 Data32And; + UINT16 Address; + + Data32And =3D 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 =3D 0xFFFFFFFF; + Data32Or =3D 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/PeiDxeS= mmPchInitCommonLib/PchInitCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch= /Library/Private/PeiDxeSmmPchInitCommonLib/PchInitCommon.c new file mode 100644 index 0000000000..14bd51ec43 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchIn= itCommonLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[]; +extern CONST UINT32 mPchPcieControllerInfoSize; + +#define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us =3D 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_CONTROLL= ER_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 =3D 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 =3D PchGetPcieRpDevice (RpIndex); + Fid =3D (UINT16) ((RpDevice << 3) | (RpIndex % 4 )); + Status =3D PchSbiExecutionEx ( + GetRpSbiPid (RpIndex), + Offset, + PciConfigRead, + FALSE, + 0xF, + 0, + Fid, + Data32, + &Response + ); + if (Status !=3D EFI_SUCCESS) { + DEBUG((DEBUG_ERROR,"Sideband Read Failed of RpIndex %d Offset 0x%x. De= vice =3D %d Fid =3D 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 =3D PchGetPcieRpDevice (RpIndex); + Status =3D PchSbiRpPciRead32 (RpIndex, Offset, &Data32); + if (Status =3D=3D EFI_SUCCESS) { + Data32 &=3D Data32And; + Data32 |=3D Data32Or; + Fid =3D (UINT16) ((RpDevice << 3) | (RpIndex % 4 )); + Status =3D PchSbiExecutionEx ( + GetRpSbiPid (RpIndex), + Offset, + PciConfigWrite, + FALSE, + 0xF, + 0, + Fid, + &Data32, + &Response + ); + if (Status !=3D EFI_SUCCESS) { + DEBUG((DEBUG_ERROR,"Sideband Write Failed of RpIndex %d Offset 0x%x.= Device =3D %d Fid =3D 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 =3D 0; Offset < PrintSize; Offset++) { + if ((Offset % 16) =3D=3D 0) { + DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFF= F0)); + } + 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 =3D 0; Offset < PrintSize; Offset++) { + if ((Offset % 16) =3D=3D 0) { + DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFF= F0)); + } + DEBUG ((DEBUG_VERBOSE, "%02X ", PciSegmentRead8 (PrintPciSegmentBase += Offset))); + } + DEBUG ((DEBUG_VERBOSE, "\n")); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/Silicon/Intel/Cof= feelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPciExpressHelpersLib/PchP= ciExpressHelpersLibrary.c new file mode 100644 index 0000000000..dcb43285b7 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPc= iExpressHelpersLib/PchPciExpressHelpersLibrary.c @@ -0,0 +1,2407 @@ +/** @file + This file contains routines that support PCI Express initialization + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PchPciExpressHelpersLibrary.h" +#include + +#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 coordinat= es of a PCIe device +// in a single variable. PcieCap is offset to PCI Express capabilities. Ha= ving 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 accom= odate 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 addres= s + + @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 =3D (RpIndex / 4); + ControllerLane =3D (RpIndex % 4) + RpLane; + if (IsPcieLaneReversalEnabled (RpIndex)) { + ControllerLane =3D 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_PC= IEDBG, &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 =3D 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 valu= e +*/ +T_POWER_ON +GetTpoCapability ( + UINT64 DeviceBase, + UINT32 L1ssCapOffset + ) +{ + T_POWER_ON Tpo; + UINT32 L1ssCapabilities; + + L1ssCapabilities =3D PciSegmentRead32 (DeviceBase + L1ssCapOffset + R_PC= IE_EX_L1SCAP_OFFSET); + Tpo.Scale =3D (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L= 1SCAP_PTPOS; + Tpo.Value =3D (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1S= CAP_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[] =3D {2, 10, 100}; + + ASSERT (TpoScale < TpoScaleMax); + if (TpoScale >=3D 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 re= turns 0 + CAPID list: + 0x01 =3D PCI Power Management Interface + 0x04 =3D Slot Identification + 0x05 =3D MSI Capability + 0x10 =3D 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 un= necessary PCI access + // If the device doesn't exist, check for CapHeaderId !=3D 0xFF will fai= l and function will return offset 0 + // + if ((PciSegmentRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_= STATUS_CAPABILITY) =3D=3D 0x00) { + /// + /// Function has no capability pointer + /// + return 0; + } else { + /// + /// Check the header layout to determine the Offset of Capabilities Po= inter Register + /// + if ((PciSegmentRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LA= YOUT_CODE) =3D=3D (HEADER_TYPE_CARDBUS_BRIDGE)) { + /// + /// If CardBus bridge, start at Offset 0x14 + /// + CapHeaderOffset =3D EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR; + } else { + /// + /// Otherwise, start at Offset 0x34 + /// + CapHeaderOffset =3D PCI_CAPBILITY_POINTER_OFFSET; + } + /// + /// Get Capability Header, A pointer value of 00h is used to indicate = the last capability in the list. + /// + CapHeaderId =3D 0; + CapHeaderOffset =3D PciSegmentRead8 (DeviceBase + CapHeaderOffset) & (= (UINT8) ~(BIT0 | BIT1)); + while (CapHeaderOffset !=3D 0 && CapHeaderId !=3D 0xFF) { + Data16 =3D PciSegmentRead16 (DeviceBase + CapHeaderOffset); + CapHeaderId =3D (UINT8)(Data16 & 0xFF); + if (CapHeaderId =3D=3D CapId) { + if (CapHeaderOffset > PCI_MAXLAT_OFFSET) { + /// + /// Return valid capability offset + /// + DEBUG ((DEBUG_INFO,"CapId %x,%x->%02x\n", ((UINT32)(DeviceBase&0= xFFFFF000)>>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 point= er at 34h) are reserved + /// and must be implemented as 00b although software must mask them = to allow for future uses of these bits. + /// + CapHeaderOffset =3D (UINT8)(Data16 >> 8); + } + return 0; + } +} + +/** + Find the Offset to a given Capabilities ID + CAPID list: + 0x01 =3D PCI Power Management Interface + 0x04 =3D Slot Identification + 0x05 =3D MSI Capability + 0x10 =3D 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 =3D = %0x \n", Segment, Bus, Device, Function, CapId)); + DeviceBase =3D 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 =3D Advanced Error Reporting Capability + 0x0002 =3D Virtual Channel Capability + 0x0003 =3D Device Serial Number Capability + 0x0004 =3D 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 th= e last capability in the list. + /// + CapHeaderId =3D 0; + CapHeaderOffset =3D R_PCH_PCIE_CFG_EXCAP_OFFSET; + while (CapHeaderOffset !=3D 0 && CapHeaderId !=3D MAX_UINT16) { + CapHeaderId =3D PciSegmentRead16 (DeviceBase + CapHeaderOffset); + if (CapHeaderId =3D=3D CapId) { + return CapHeaderOffset; + } + /// + /// Each capability must be DWORD aligned. + /// The bottom two bits of all pointers are reserved and must be imple= mented as 00b + /// although software must mask them to allow for future uses of these= bits. + /// + CapHeaderOffset =3D (PciSegmentRead16 (DeviceBase + CapHeaderOffset + = 2) >> 4) & ((UINT16) ~(BIT0 | BIT1)); + } + + return 0; +} + +/** + Search and return the offset of desired Pci Express Capability ID + CAPID list: + 0x0001 =3D Advanced Error Reporting Capability + 0x0002 =3D Virtual Channel Capability + 0x0003 =3D Device Serial Number Capability + 0x0004 =3D 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 =3D 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 por= t. + + @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 =3D PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL); + return (Data32 & B_PCH_PCIE_CFG_PCIEPMECTL_DLSULPPGE) !=3D 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= =3D128b, 1=3D256b, 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 regist= er (0=3D128b, 1=3D256b, etc) +**/ +STATIC +VOID +SetMps ( + SBDF Sbdf, + UINT8 Mps + ) +{ + PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCTL_OF= FSET, (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 coordina= tes + + @retval TRUE if yes +**/ +STATIC +BOOLEAN +IsLtrCapable ( + SBDF Sbdf + ) +{ + if (Sbdf.PcieCap =3D=3D 0) { + return FALSE; + } + return !!(PciSegmentRead32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DC= AP2_OFFSET) & B_PCIE_DCAP2_LTRMS); +} + +/** + Enables LTR feature in given device + + @param[in] Sbdf device's segment:bus:device:function coordina= tes +**/ +STATIC +VOID +EnableLtr ( + SBDF Sbdf + ) +{ + if (Sbdf.PcieCap =3D=3D 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) =3D=3D 0xFFFF) { + return FALSE; + } + return TRUE; +} + +/** + Returns information about type of device. + + @param[out] Sbdf device's segment:bus:device:function coordin= ates + @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 =3D=3D 0) { + return DevTypePci; + } + DeviceType =3D (UINT8) ((PciSegmentRead16 (SbdfToBase (Sbdf) + Sbdf.Pcie= Cap + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT); + if (DeviceType =3D=3D PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) { + return DevTypePcieUpstream; + } else if (DeviceType =3D=3D PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT || De= viceType =3D=3D PCIE_DEVICE_PORT_TYPE_ROOT_PORT) { + return DevTypePcieDownstream; + } else { + return DevTypePcieEndpoint; + } +} + +/** + Initializes Dev:Func numbers for use in FindNextPcieChild or FindNextLeg= alSbdf functions. + + @param[out] Sbdf device's segment:bus:device:function coordin= ates +**/ +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 =3D PCI_MAX_DEVICE; + Sbdf->Func =3D PCI_MAX_FUNC; +} + +/** + Checks the device is a bridge and has non-zero secondary bus number assi= gned. + 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 compl= ex + + @param[in] Sbdf device's segment:bus:device:function coordinates + @param[out] ChildSbdf SBDF initialized in such way that calling FindNex= tPcieChild( ) on it will find all children devices + + @retval TRUE if device is a bridge and has a bus behind it; FALSE otherw= ise +**/ +STATIC +BOOLEAN +HasChildBus ( + SBDF Sbdf, + SBDF *ChildSbdf + ) +{ + UINT32 Data32; + UINT64 Base; + UINT8 SecondaryBus; + + ChildSbdf->Seg =3D Sbdf.Seg; + InitChildFinder (ChildSbdf); + + Base =3D SbdfToBase (Sbdf); + + if (PciSegmentRead8 (Base + R_PCI_BCC_OFFSET) !=3D PCI_CLASS_BRIDGE) { + DEBUG ((DEBUG_INFO, "HasChildBus%02:%02:%02: no\n", Sbdf.Bus, Sbdf.Dev= , Sbdf.Func)); + return FALSE; + } + Data32 =3D PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFS= ET); + SecondaryBus =3D (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8); + ChildSbdf->Bus =3D SecondaryBus; + if (SecondaryBus =3D=3D 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 HEAD= ER_TYPE register + make sense (header !=3D 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 =3D PciSegmentRead8(Base + PCI_HEADER_TYPE_OFFSET); + if ((HeaderType =3D=3D 0xFF) || ((HeaderType & HEADER_TYPE_MULTI_FUNCTIO= N) =3D=3D 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] =3D {1, 32, 1024, 32768, 1048576, 335544= 32, 0, 0}; + + DecodedLatencyA =3D ScaleEncoding[LtrA.MaxSnoopLatencyScale] * LtrA.MaxS= noopLatencyValue; + DecodedLatencyB =3D ScaleEncoding[LtrB.MaxSnoopLatencyScale] * LtrB.MaxS= noopLatencyValue; + if ((!LtrB.MaxSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedLat= encyB) && LtrA.MaxSnoopLatencyRequirement)) { + Result.MaxSnoopLatencyValue =3D LtrA.MaxSnoopLatencyValue; + Result.MaxSnoopLatencyScale =3D LtrA.MaxSnoopLatencyScale; + Result.MaxSnoopLatencyRequirement =3D LtrA.MaxSnoopLatencyRequirement; + } else { + Result.MaxSnoopLatencyValue =3D LtrB.MaxSnoopLatencyValue; + Result.MaxSnoopLatencyScale =3D LtrB.MaxSnoopLatencyScale; + Result.MaxSnoopLatencyRequirement =3D LtrB.MaxSnoopLatencyRequirement; + } + DecodedLatencyA =3D ScaleEncoding[LtrA.MaxNoSnoopLatencyScale] * LtrA.Ma= xNoSnoopLatencyValue; + DecodedLatencyB =3D ScaleEncoding[LtrB.MaxNoSnoopLatencyScale] * LtrB.Ma= xNoSnoopLatencyValue; + if ((!LtrB.MaxNoSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedL= atencyB) && LtrA.MaxNoSnoopLatencyRequirement)) { + Result.MaxNoSnoopLatencyValue =3D LtrA.MaxNoSnoopLatencyValue; + Result.MaxNoSnoopLatencyScale =3D LtrA.MaxNoSnoopLatencyScale; + Result.MaxNoSnoopLatencyRequirement =3D LtrA.MaxNoSnoopLatencyRequirem= ent; + } else { + Result.MaxNoSnoopLatencyValue =3D LtrB.MaxNoSnoopLatencyValue; + Result.MaxNoSnoopLatencyScale =3D LtrB.MaxNoSnoopLatencyScale; + Result.MaxNoSnoopLatencyRequirement =3D LtrB.MaxNoSnoopLatencyRequirem= ent; + } + Result.ForceOverride =3D FALSE; + if (LtrA.ForceOverride || LtrB.ForceOverride) { + Result.ForceOverride =3D 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.MaxSnoopLat= encyRequirement, + LtrA.MaxNoSnoopLatencyValue, LtrA.MaxNoSnoopLatencyScale, LtrA.MaxNoSn= oopLatencyRequirement, + 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.MaxSnoopLat= encyRequirement, + LtrB.MaxNoSnoopLatencyValue, LtrB.MaxNoSnoopLatencyScale, LtrB.MaxNoSn= oopLatencyRequirement, + 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.MaxSn= oopLatencyRequirement, + Result.MaxNoSnoopLatencyValue, Result.MaxNoSnoopLatencyScale, Result.M= axNoSnoopLatencyRequirement, + 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 =3D {0}; + + VenId =3D PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET); + DevId =3D PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET); + RevId =3D PciSegmentRead16 (Base + PCI_REVISION_ID_OFFSET); + + for (Index =3D 0; Index < Override->Size; Index++) { + if (((Override->Table[Index].OverrideConfig & PchPcieLtrOverride) =3D= =3D PchPcieLtrOverride) && + (Override->Table[Index].VendorId =3D=3D VenId) && + ((Override->Table[Index].DeviceId =3D=3D DevId) || (Override->Tabl= e[Index].DeviceId =3D=3D 0xFFFF)) && + ((Override->Table[Index].RevId =3D=3D RevId) || (Override->Table[I= ndex].RevId =3D=3D 0xFF))) { + if (Override->Table[Index].SnoopLatency & 0x8000) { + ReturnValue.MaxSnoopLatencyRequirement =3D 1; + ReturnValue.MaxSnoopLatencyValue =3D Override->Table[Index].SnoopL= atency & 0x3FF; + ReturnValue.MaxSnoopLatencyScale =3D (Override->Table[Index].Snoop= Latency & 0x1C00) >> 10; + } + if (Override->Table[Index].NonSnoopLatency & 0x8000) { + ReturnValue.MaxNoSnoopLatencyRequirement =3D 1; + ReturnValue.MaxNoSnoopLatencyValue =3D Override->Table[Index].NonS= noopLatency & 0x3FF; + ReturnValue.MaxNoSnoopLatencyScale =3D (Override->Table[Index].Non= SnoopLatency & 0x1C00) >> 10; + } + ReturnValue.ForceOverride =3D Override->Table[Index].ForceLtrOverrid= e; + 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 =3D PcieBaseFindExtendedCapId (Base, R_PCH_PCIE_LTRECH_CID)= ; + if (LtrCapOffset =3D=3D 0) { + return; + } + Data16 =3D (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, D= ata16); + + Data16 =3D (UINT16)((Ltr.MaxNoSnoopLatencyValue << N_PCH_PCIE_LTRECH_MNS= LR_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 0= x10 + If the device is PCI express then its SDBF structure gets updated with p= ointer to + the PCIe Capability. This is an optimization feature. It greatly decreas= es the number + of bus accesses, since most features configured by this library depend o= n 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 PC= Ie or there's no device at all +**/ +STATIC +BOOLEAN +IsPcieDevice ( + SBDF *Sbdf + ) +{ + UINT8 PcieCapOffset; + UINT64 Base; + + Base =3D SbdfToBase (*Sbdf); + + if (PciSegmentRead16 (Base) =3D=3D 0xFFFF) { + return FALSE; + } + + + PcieCapOffset =3D PcieBaseFindCapId (Base, EFI_PCI_CAPABILITY_ID_PCIEXP)= ; + if (PcieCapOffset =3D=3D 0) { + DEBUG ((DEBUG_INFO, "IsPcieDevice %02x:%02x:%02x - legacy\n", Sbdf->Bu= s, Sbdf->Dev, Sbdf->Func)); + return FALSE; + } else { + Sbdf->PcieCap =3D 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 l= ocated, or FALSE if there + no such coordinates left. + + Segment and Bus fields of SBDF structure are input only and determine wh= ich bus will be scanned. + This function should be called in a while() loop. It replaces the less e= fficient 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 Mul= tifunction bit set, + then higher function numbers are skipped. If parent of this bus is a dow= nstream port, then + Device numbers 1-31 get skipped too (there can be only Dev0 behind downs= tream ports) + If device/function number =3D=3D 0x1F/0x7, this function returns first p= ossible address, that is 0:0 + Any other device number means Dev:Func contain address of last found chi= ld 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 fro= m this function + Dev:Func value of 1F:07 means se= arch should start from the beginning + On exit: if legal Dev:Func combination wa= s found, that Dev:Func is returned + otherwise, Dev:Func are initiali= zed 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 =3D=3D DevTypePcieEndpoint) { + return FALSE; + } + if (ParentDevType =3D=3D DevTypePcieUpstream) { + MaxDev =3D PCI_MAX_DEVICE; + } else { + MaxDev =3D 0; + } + Func0Base =3D PCI_SEGMENT_LIB_ADDRESS (Sbdf->Seg, Sbdf->Bus, Sbdf->Dev, = 0, 0); + if ((Sbdf->Dev =3D=3D PCI_MAX_DEVICE) && Sbdf->Func =3D=3D PCI_MAX_FUNC)= { + Sbdf->Dev =3D 0; + Sbdf->Func =3D 0; + return TRUE; + } else if ((Sbdf->Func =3D=3D PCI_MAX_FUNC) || (Sbdf->Func =3D=3D 0 && != IsMultifunctionDevice (Func0Base))) { + // + // if it's the last function of a device, then return Func0 of new devic= e or FALSE in case there are no more devices + // + if (Sbdf->Dev =3D=3D MaxDev) { + InitChildFinder (Sbdf); + return FALSE; + } + (Sbdf->Dev)++; + Sbdf->Func =3D 0; + return TRUE; + } else { + (Sbdf->Func)++; + return TRUE; + } +} + +/** + Finds next PCIe (not legacy PCI) device behind given device + If device/function number =3D=3D 0x1F/0x7, this function searches for ch= ildren from scratch + Any other device number means Dev:Func contain address of last found chi= ld 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 fro= m this function + Dev:Func value of 0x1F:0x07 mean= s search should start from the beginning + On exit: if PCIe device was found, its SB= DF coordinates are returned + otherwise, Dev:Func are initiali= zed 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_CC= C); +} + +/** + Retrains link behind given device. + It only makes sense to call it for downstream ports. If called for upstr= eam port nothing will happen. + If WaitUntilDone is TRUE function will wait until link retrain had finis= hed, otherwise it will return immediately. + Link must finish retrain before software can access the device on the ot= her 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 coordinat= es + @param[in] WaitUntilDone when TRUE, function waits until link has retra= ined +**/ +VOID +RetrainLink ( + UINT64 Base, + UINT8 PcieCapOffset, + BOOLEAN WaitUntilDone + ) +{ + UINT16 LinkTraining; + UINT32 TimeoutUs; + + TimeoutUs =3D 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 =3D (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS= _OFFSET) & B_PCIE_LSTS_LT); + TimeoutUs--; + } while (LinkTraining && (TimeoutUs !=3D 0)); + + PciSegmentOr8 (Base + PcieCapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL= ); + + TimeoutUs =3D LINK_RETRAIN_WAIT_TIME; + if (WaitUntilDone) { + do { + LinkTraining =3D (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LS= TS_OFFSET) & B_PCIE_LSTS_LT); + TimeoutUs--; + } while (LinkTraining && (TimeoutUs !=3D 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_LC= AP_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 =3D PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 2); + SubClassCode =3D PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 1); + ProgInterface =3D PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET); + if ((BaseClassCode =3D=3D PCI_CLASS_SYSTEM_PERIPHERAL) && + (SubClassCode =3D=3D PCI_SUBCLASS_PIC) && + ((ProgInterface =3D=3D PCI_IF_APIC_CONTROLLER) || + (ProgInterface =3D=3D PCI_IF_APIC_CONTROLLER2))) { + return TRUE; + } + return FALSE; +} + +/** + There are some devices which support L1 substates, but due to silicon bu= gs 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 =3D PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET); + DeviceId =3D PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET); + Revision =3D PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET); + + for (Index =3D 0; Index < Override->Size; Index++) { + if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverri= de) =3D=3D PchPcieL1SubstatesOverride) && + (Override->Table[Index].VendorId =3D=3D VendorId) && + (Override->Table[Index].DeviceId =3D=3D DeviceId) && + (Override->Table[Index].RevId =3D=3D Revision || Override->Table[I= ndex].RevId =3D=3D 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 c= apabilities + + @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 =3D PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET); + DeviceId =3D PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET); + Revision =3D PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET); + + for (Index =3D 0; Index < Override->Size; Index++) { + if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverri= de) =3D=3D PchPcieL1SubstatesOverride) && + (Override->Table[Index].VendorId =3D=3D VendorId) && + (Override->Table[Index].DeviceId =3D=3D DeviceId) && + (Override->Table[Index].RevId =3D=3D Revision || Override->Table[I= ndex].RevId =3D=3D 0xFF)) { + L1ss->PmL12 &=3D !!(Override->Table[Index].L1SubstatesCapMask & B_= PCIE_EX_L1SCAP_PPL12S); + L1ss->PmL11 &=3D !!(Override->Table[Index].L1SubstatesCapMask & B_= PCIE_EX_L1SCAP_PPL11S); + L1ss->AspmL12 &=3D !!(Override->Table[Index].L1SubstatesCapMask & B_= PCIE_EX_L1SCAP_AL12S); + L1ss->AspmL11 &=3D !!(Override->Table[Index].L1SubstatesCapMask & B_= PCIE_EX_L1SCAP_AL1SS); + if (Override->Table[Index].L1sTpowerOnValue !=3D 0) { + L1ss->Cmrt =3D Override->Table[Index].L1sCommonModeRestoreTime; + L1ss->TpoScale =3D Override->Table[Index].L1sTpowerOnScale; + L1ss->TpoValue =3D 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 =3D {0}; + UINT16 PcieCapOffset; + UINT32 CapsRegister; + + PcieCapOffset =3D GetOverrideL1ssCapsOffset (Base, Override); + if (PcieCapOffset =3D=3D 0) { + PcieCapOffset =3D PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID); + } + if (PcieCapOffset =3D=3D 0) { + return Capabilities; + } + CapsRegister =3D PciSegmentRead32 (Base + PcieCapOffset + R_PCIE_EX_L1SC= AP_OFFSET); + if (CapsRegister & B_PCIE_EX_L1SCAP_L1PSS) { + Capabilities.PmL11 =3D !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL11S); + Capabilities.PmL12 =3D !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL12S); + Capabilities.AspmL12 =3D !!(CapsRegister & B_PCIE_EX_L1SCAP_AL12S); + Capabilities.AspmL11 =3D !!(CapsRegister & B_PCIE_EX_L1SCAP_AL1SS); + Capabilities.Cmrt =3D (CapsRegister & B_PCIE_EX_L1SCAP_CMRT) >> N_PCIE= _EX_L1SCAP_CMRT; + Capabilities.TpoValue =3D (CapsRegister & B_PCIE_EX_L1SCAP_PTV) >> N_P= CIE_EX_L1SCAP_PTV; + Capabilities.TpoScale =3D (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 betwe= en 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 =3D L1ssA.PmL12 && L1ssB.PmL12; + Combined.PmL11 =3D L1ssA.PmL11 && L1ssB.PmL11; + Combined.AspmL12 =3D L1ssA.AspmL12 && L1ssB.AspmL12; + Combined.AspmL11 =3D L1ssA.AspmL11 && L1ssB.AspmL11; + Combined.Cmrt =3D MAX (L1ssA.Cmrt, L1ssB.Cmrt); + if (TpoToUs (L1ssA.TpoScale, L1ssA.TpoValue) > TpoToUs (L1ssB.TpoScale, = L1ssB.TpoValue)) { + Combined.TpoScale =3D L1ssA.TpoScale; + Combined.TpoValue =3D L1ssA.TpoValue; + } else { + Combined.TpoScale =3D L1ssB.TpoScale; + Combined.TpoValue =3D 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 =3D SbdfToBase(Sbdf); + Ctrl1Register =3D 0; + Ctrl2Register =3D 0; + + PcieCapOffset =3D GetOverrideL1ssCapsOffset (Base, Override); + if (PcieCapOffset =3D=3D 0) { + PcieCapOffset =3D PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID); + } + if (PcieCapOffset =3D=3D 0) { + return; + } + Ctrl1Register |=3D (L1ss.PmL12 ? B_PCIE_EX_L1SCAP_PPL12S : 0); + Ctrl1Register |=3D (L1ss.PmL11 ? B_PCIE_EX_L1SCAP_PPL11S : 0); + Ctrl1Register |=3D (L1ss.AspmL12 ? B_PCIE_EX_L1SCAP_AL12S : 0); + Ctrl1Register |=3D (L1ss.AspmL11 ? B_PCIE_EX_L1SCAP_AL1SS : 0); + if (GetDeviceType (Sbdf) =3D=3D DevTypePcieDownstream) { + Ctrl1Register |=3D (L1ss.Cmrt << N_PCIE_EX_L1SCAP_CMRT); + } + /// + /// Set L1.2 LTR threshold to 80us (value =3D 0x50, scale =3D 0x2 =3D 1= 024ns), 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 l= ess than Tpo + /// + Ctrl1Register |=3D (0x50 << N_PCIE_EX_L1SCTL1_L12LTRTLV); + Ctrl1Register |=3D (2 << N_PCIE_EX_L1SCTL1_L12LTRTLSV); + + Ctrl2Register |=3D (L1ss.TpoScale); + Ctrl2Register |=3D (L1ss.TpoValue << N_PCIE_EX_L1SCTL2_POWT); + + PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, 0); + PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, Ctrl= 2Register); + PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, Ctrl= 1Register); +} + +/** + 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 !=3D ASPM_L1_NO_LIMIT) { + if (Value > 0) { + Aspm.L1AcceptableLatencyUs +=3D Value; + } else { + if (Aspm.L1AcceptableLatencyUs > (UINT32)(-1*Value)) { + Aspm.L1AcceptableLatencyUs =3D Aspm.L1AcceptableLatencyUs + Value; + } else { + Aspm.L1AcceptableLatencyUs =3D 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 =3D {0}; + + Base =3D SbdfToBase (Sbdf); + + LinkCapRegister =3D PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_LCAP_= OFFSET); + DevCapRegister =3D PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_DCAP_O= FFSET); + + /// + /// Check endpoint for pre-1.1 devices based on the Role based Error Rep= orting Capability bit. Don't report L0s support for old devices + /// + if (DevCapRegister & B_PCIE_DCAP_RBER) { + Aspm.L0sSupported =3D !!(LinkCapRegister & B_PCIE_LCAP_APMS_L0S); + } + Aspm.L1Supported =3D !!(LinkCapRegister & B_PCIE_LCAP_APMS_L1); + + Aspm.LinkL0sExitLatency =3D (LinkCapRegister & B_PCIE_LCAP_EL0) >> N_PCI= E_LCAP_EL0; + Aspm.LinkL1ExitLatencyUs =3D L1LatencyToUs( (LinkCapRegister & B_PCIE_LC= AP_EL1) >> N_PCIE_LCAP_EL1); + + if (GetDeviceType (Sbdf) =3D=3D DevTypePcieEndpoint) { + Aspm.L0sAcceptableLatency =3D (DevCapRegister & B_PCIE_DCAP_E0AL) >> N= _PCIE_DCAP_E0AL; + Aspm.L1AcceptableLatencyUs =3D 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.L0sAcceptableLate= ncy, + = Aspm.L1Supported?'+':'-', Aspm.LinkL1ExitLatencyUs, Aspm.L1AcceptableLaten= cyUs)); + } else { + Aspm.L0sAcceptableLatency =3D ASPM_L0s_NO_LIMIT; + Aspm.L1AcceptableLatencyUs =3D 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 cu= rrently visited PCIe device + @param[in,out] MyAspm Current device's ASPM capabilities struct= ure + @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 =3D SbdfToBase (Sbdf); + + VendorId =3D PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET); + DeviceId =3D PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET); + Revision =3D PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET); + + for (Index =3D 0; Index < Override->Size; Index++) { + if (((Override->Table[Index].OverrideConfig & PchPcieL1L2Override) =3D= =3D PchPcieL1L2Override) && + (Override->Table[Index].VendorId =3D=3D VendorId) && + (Override->Table[Index].DeviceId =3D=3D DeviceId) && + (Override->Table[Index].RevId =3D=3D Revision || Override->Table[I= ndex].RevId =3D=3D 0xFF)) { + DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, original L0sSup= ported =3D 0x%x, L1Supported =3D 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 =3D Override->Table[Index].EndPointAspm & BIT= 0; + } + if (MyAspm->L1Supported) { + // + // If L1 is supported in capability, apply platform override. + // + MyAspm->L1Supported =3D (Override->Table[Index].EndPointAspm & BIT= 1) >> 1; + } + DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, override L0sSup= ported =3D 0x%x, L1Supported =3D 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 dete= rmine 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 s= tate of link just below + // and consider all acceptable latencies of all endpoints anywhere dow= n below that port + // + Combined.L0sSupported =3D AspmA.L0sSupported & AspmB.L0sSupported; + Combined.L1Supported =3D AspmA.L1Supported & AspmB.L1Supported; + Combined.LinkL0sExitLatency =3D MAX (AspmA.LinkL0sExitLatency, AspmB.L= inkL0sExitLatency); + Combined.LinkL1ExitLatencyUs =3D MAX (AspmA.LinkL1ExitLatencyUs, AspmB= .LinkL1ExitLatencyUs); + Combined.L0sAcceptableLatency =3D MIN (AspmA.L0sAcceptableLatency, Asp= mB.L0sAcceptableLatency); + Combined.L1AcceptableLatencyUs =3D MIN (AspmA.L1AcceptableLatencyUs, A= spmB.L1AcceptableLatencyUs); + } else { + // + // When combining ASPM in switch upstream ports, + // Supported and ExitLatency must only reflect capabilities of upstrea= m port itself + // But acceptable latencies must consider all endpoints anywhere below + // + Combined.L0sSupported =3D AspmA.L0sSupported; + Combined.L1Supported =3D AspmA.L1Supported; + Combined.LinkL0sExitLatency =3D AspmA.LinkL0sExitLatency; + Combined.LinkL1ExitLatencyUs =3D AspmA.LinkL1ExitLatencyUs; + Combined.L0sAcceptableLatency =3D MIN (AspmA.L0sAcceptableLatency, Asp= mB.L0sAcceptableLatency); + Combined.L1AcceptableLatencyUs =3D MIN (AspmA.L1AcceptableLatencyUs, A= spmB.L1AcceptableLatencyUs); + } + DEBUG ((DEBUG_INFO, "CombineAspm %x:%x -> %x\n", AspmA.L1AcceptableLaten= cyUs, 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 en= dpoint devices below it + @retval TRUE if L1 can be enabled +**/ +STATIC +BOOLEAN +IsL1Allowed ( + ASPM_CAPS Aspm + ) +{ + return (Aspm.L1Supported && (Aspm.L1AcceptableLatencyUs >=3D Aspm.LinkL1= ExitLatencyUs)); +} + +/** + 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 en= dpoint devices below it + @retval TRUE if L0s can be enabled +**/ +STATIC +BOOLEAN +IsL0sAllowed ( + ASPM_CAPS Aspm + ) +{ + return (Aspm.L0sSupported && (Aspm.L0sAcceptableLatency >=3D Aspm.LinkL0= sExitLatency)); +} + +/** + 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 l= ink'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 en= dpoint devices below it +**/ +STATIC +VOID +SetAspm ( + SBDF Sbdf, + ASPM_CAPS Aspm + ) +{ + UINT16 DataOr; + + DataOr =3D 0; + if (IsL0sAllowed (Aspm)) { + DataOr |=3D V_PCIE_LCTL_ASPM_L0S; + } + if (IsL1Allowed (Aspm)) { + DataOr |=3D V_PCIE_LCTL_ASPM_L1; + } + DEBUG ((DEBUG_INFO, "SetAspm on %02x:%02x:%02x to %d\n", Sbdf.Bus,Sbdf.D= ev,Sbdf.Func, DataOr)); + PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCTL_OF= FSET, (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 devic= e to be added to table +**/ +STATIC +VOID +AddToDeviceTable ( + SBDF_TABLE *Table, + SBDF Sbdf + ) +{ + if (Table->Count < MAX_SBDF_TABLE_SIZE) { + Table->Entry[Table->Count++] =3D 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_B= RIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0); + Table->Count--; + } +} + +/** + Attempts to assign secondary and subordinate bus numbers to uninitialize= d 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 num= bers 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 cle= ared afterwards. + + @param[in] Sbdf segment:bus:device:function coordinates o= f device to be added to table + @param[in] MinBus minimum Bus number that can be assigned b= elow this port + @param[in] MaxBus maximum Bus number that can be assigned b= elow this port + @param[in] BridgeCleanupList list of bridges where bus numbers were mo= dified + + @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 =3D Sbdf.Seg; + InitChildFinder (&ChildSbdf); + Base =3D 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 any= where below; return that number + // + DevType =3D GetDeviceType (Sbdf); + if ((Sbdf.Bus >=3D MaxBus) || (DevType =3D=3D DevTypePcieEndpoint) || (D= evType =3D=3D DevTypePci)) { + return (UINT8) Sbdf.Bus; + } else { + Data32 =3D PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OF= FSET); + SecondaryBus =3D (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8); + SubordinateBus =3D (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SBBN) >> 16); + if (SecondaryBus !=3D 0) { + ChildSbdf.Bus =3D SecondaryBus; + MinBus =3D 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 =3D RecursiveBusAssignment (ChildSbdf, MinBus, Subordinat= eBus, BridgeCleanupList); + MinBus =3D BelowBus + 1; + } + return SubordinateBus; + } else { + Data32 =3D Sbdf.Bus + (MinBus << 8) + (MaxBus << 16); + PciSegmentWrite32(Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Dat= a32); + 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 =3D MinBus; + ChildSbdf.Bus =3D MinBus; + MinBus++; + while (FindNextPcieChild (DevType, &ChildSbdf)) { + BelowBus =3D RecursiveBusAssignment (ChildSbdf, MinBus, MaxBus, Br= idgeCleanupList); + MinBus =3D BelowBus + 1; + } + Data32 &=3D ~B_PCI_BRIDGE_BNUM_SBBN; + Data32 |=3D (BelowBus << 16); + PciSegmentWrite32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Da= ta32); + 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 late= ncy is smaller than acceptable latency + ASPM of a given link is independend from any other link (except 1ms L1 a= djustment, 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 P= CIe device + @param[in] Depth How many links there are betwe= en this port and root complex + @param[in] Override Pch Pcie devices OverrideTable + + @retval structure that describes acceptable latencies of all endpoints b= elow 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, S= bdf.Dev, Sbdf.Func)); + + // + // On way down: + // pass number of links traversed; increase it per upstream port visit= ed (not endpoint) + // On way up: + // EndPoint: read Acceptable Latencies; subtract Depth From L1Acceptab= leLat 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 e= arlier Depth subtraction + // UpstreamPort: calculate minimum of below Acceptable Latencies; retu= rn that, with upper link's Latency and L0s/L1 support + // + DevType =3D GetDeviceType(Sbdf); + if (DevType =3D=3D DevTypePcieUpstream) { + Depth++; + } + MyAspm =3D GetAspmCaps (Sbdf); + // + // Get ASPM L0s and L1 override + // + GetOverrideAspm (Sbdf, &MyAspm, Override); + if (DevType =3D=3D DevTypePcieEndpoint) { + // + // Every switch between endpoint and CPU introduces 1us additional lat= ency 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' add= ed delay may be shadowed by + // other links' exit latency. But it guarantees that acceptable latenc= y 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 =3D RecursiveAspmConfiguration (ChildSbdf, Depth, Override= ); + MyAspm =3D CombineAspm (MyAspm, ChildAspm, (DevType =3D=3D DevTypePc= ieDownstream)); + } + if (DevType =3D=3D 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 =3D 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 P= CIe 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, S= bdf.Dev, Sbdf.Func)); + + Base =3D SbdfToBase (Sbdf); + // + // On way down: + // do nothing + // On way up: + // In downstream ports, combine L1ss capabilities of that port and dev= ice behind it, then enable L1.1 and/or L1.2 if possible + // Return L1ss capabilities + // + if (HasChildBus (Sbdf, &ChildSbdf)) { + DevType =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + ChildCaps =3D RecursiveL1ssConfiguration (ChildSbdf, Override); + if (DevType =3D=3D DevTypePcieDownstream && ChildSbdf.Func =3D=3D 0)= { + CombinedCaps =3D CombineL1ss (GetL1ssCaps (Base, Override), ChildC= aps); + 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 P= CIe 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.De= v, Sbdf.Func)); + + IoApicPresent =3D 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 =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + IoApicPresent =3D RecursiveIoApicCheck (ChildSbdf); + if (IoApicPresent) { + break; + } + } + } + DEBUG ((DEBUG_INFO, "IoApic status %d @%x:%x:%x:%x\n", IoApicPresent, Sb= df.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 be= low it. + There are many valid strategies for setting MPS. This implementation cho= oses + 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 P= CIe device + + @retval MPS supported by PCIe hierarchy, calculated as MIN(MPS of all d= evices 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 =3D GetMps (Sbdf); + if (MyMps =3D=3D 0) { + return MyMps; + } + if (HasChildBus (Sbdf, &ChildSbdf)) { + DevType =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + SubtreeMps =3D RecursiveMpsCheck (ChildSbdf); + MyMps =3D 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 dev= ices below it. + There are many valid strategies for setting MPS. This implementation cho= oses + 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 P= CIe device + @param[in] Mps Maximum Payload Size to be pro= grammed +**/ +STATIC +VOID +RecursiveMpsConfiguration ( + SBDF Sbdf, + UINT8 Mps + ) +{ + SBDF ChildSbdf; + PCI_DEV_TYPE DevType; + + DEBUG ((DEBUG_INFO, "RecursiveMpsConfiguration %x:%x:%x\n", Sbdf.Bus, Sb= df.Dev, Sbdf.Func)); + + if (HasChildBus (Sbdf, &ChildSbdf)) { + DevType =3D 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 sup= port. + 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 & s= et ECPM of downstream component + When this function executes on downstream component, all devices below i= t are guaranteed to + return CPM=3D0 so it will do nothing + + @param[in] Segment,Bus,Device,Function address of currently visited P= CIe device + + @retval TRUE =3D this device supports CPM, FALSE =3D 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, Sb= df.Dev, Sbdf.Func)); + + ChildCpm =3D FALSE; + + if (HasChildBus (Sbdf, &ChildSbdf)) { + ChildCpm =3D TRUE; + DevType =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + ChildCpm &=3D 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 b= it =3D 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 functio= ns 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 P= CIe device + @param[in] WaitForRetrain decides if this function shoul= d busy-wait for link retrain + + @retval TRUE =3D this device supports SCC, FALSE =3D 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, Sb= df.Dev, Sbdf.Func)); + + ChildScc =3D 0; + Base =3D SbdfToBase(Sbdf); + MyScc =3D GetScc (SbdfToBase(Sbdf), (UINT8)Sbdf.PcieCap); + if (HasChildBus (Sbdf, &ChildSbdf)) { + DevType =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + ChildScc |=3D RecursiveCccConfiguration (ChildSbdf, WaitForRetrain); + } + if (DevType =3D=3D DevTypePcieDownstream) { + LinkScc =3D 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 visit= s 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 suppo= rts LTR. This function does not + iterate down behind devices with no LTR support. In effect, LTR will b= e 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 P= CIe 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, Sb= df.Dev, Sbdf.Func)); + + Base =3D 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 =3D 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 upstre= am link would be allowed to enter L1.2 + and cause large latency downstream. To work around such issues and to fi= x some devices with broken + LTR reporting, Device Override table was introduced. + This function scans PCIe tree for devices mentioned in override table an= d calculates the strictest + LTR requirement between them. That value will be programmed into rootpor= t'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 P= CIe device + @param[in] AspmOverride Device specific ASPM policy ov= erride 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, Sb= df.Dev, Sbdf.Func)); + + Base =3D SbdfToBase(Sbdf); + + MyLtrOverride =3D GetOverrideLtr (Base, AspmOverride); + if (HasChildBus (Sbdf, &ChildSbdf)) { + DevType =3D GetDeviceType (Sbdf); + while (FindNextPcieChild (DevType, &ChildSbdf)) { + ChildLtr =3D RecursiveLtrOverrideCheck (ChildSbdf, AspmOverride); + MyLtrOverride =3D CombineLtr (MyLtrOverride, ChildLtr); + } + } + return MyLtrOverride; +} + +/** + Configures rootport packet split. + + @param[in] Segment,Bus,Device,Function address of currently visited P= CIe device + @param[in] Mps maximum packet size +**/ +STATIC +VOID +ConfigureRpPacketSplit ( + SBDF RpSbdf, + UINT8 Mps + ) +{ + UINT64 RpBase; + + RpBase =3D SbdfToBase (RpSbdf); + PciSegmentAndThenOr32 (RpBase + R_PCH_PCIE_CFG_CCFG, (UINT32) ~(B_PCH_PC= IE_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 P= CIe device + @param[in] RpConfig rootport configuration + @param[in] TreeLtr combination of LTR override va= lues 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 =3D 0; + OvrVal =3D 0; + RpBase =3D SbdfToBase (RpSbdf); + // + // LTR settings from LTROVR register only get acknowledged on rising edg= e of LTROVR2[1:0] + // If those bits were already set (that can happen on a plug-hotUnplug-h= otPlug scenario), + // they need to be toggled + // + if (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LTROVR2) !=3D 0) { + PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR2, 0); + } + // + // (*)LatencyOverrideMode =3D 0 -> no override + // 1 -> override with RP policy values + // 2 -> override with endpoint's override value= s + // + + TreeLtr =3D RecursiveLtrOverrideCheck (RpSbdf, AspmOverride); + + if (RpConfig->ForceLtrOverride || TreeLtr.ForceOverride) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_FORCE_OVERRIDE; + } + if (RpConfig->LtrConfigLock =3D=3D TRUE) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_LOCK; + } + + if (RpConfig->SnoopLatencyOverrideMode =3D=3D 1) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN; + OvrVal |=3D RpConfig->SnoopLatencyOverrideValue; + OvrVal |=3D RpConfig->SnoopLatencyOverrideMultiplier << 10; + OvrVal |=3D B_PCH_PCIE_CFG_LTROVR_LTRSROVR; + } else if (RpConfig->SnoopLatencyOverrideMode =3D=3D 2) { + if (TreeLtr.MaxSnoopLatencyRequirement) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN; + OvrVal |=3D TreeLtr.MaxSnoopLatencyValue; + OvrVal |=3D TreeLtr.MaxSnoopLatencyScale << 10; + OvrVal |=3D B_PCH_PCIE_CFG_LTROVR_LTRSROVR; + } + } + if (RpConfig->NonSnoopLatencyOverrideMode =3D=3D 1) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN; + OvrVal |=3D RpConfig->NonSnoopLatencyOverrideValue << 16; + OvrVal |=3D RpConfig->NonSnoopLatencyOverrideMultiplier << 26; + OvrVal |=3D B_PCH_PCIE_CFG_LTROVR_LTRNSROVR; + } else if (RpConfig->NonSnoopLatencyOverrideMode =3D=3D 2) { + if (TreeLtr.MaxNoSnoopLatencyRequirement) { + OvrEn |=3D B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN; + OvrVal |=3D TreeLtr.MaxNoSnoopLatencyValue << 16; + OvrVal |=3D TreeLtr.MaxNoSnoopLatencyScale << 26; + OvrVal |=3D 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", RpSbd= f.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 =3D PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFuncti= on, 0); + RpIndex =3D PciePortIndex (RpBase); + + if (IoApicPresent =3D=3D 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 Mult= icast 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 =3D SbdfToBase (RpSbdf); + ClkreqSupported =3D PcieIsPhyLanePgEnabled (RpBase); + + PcieCapOffset =3D PcieBaseFindExtendedCapId (RpBase, V_PCIE_EX_L1S_CID); + if (PcieCapOffset =3D=3D 0) { + L1ssEnabled =3D FALSE; + } else { + Data32 =3D PciSegmentRead32 (RpBase + PcieCapOffset + R_PCIE_EX_L1SCTL= 1_OFFSET); + L1ssEnabled =3D Data32 & (B_PCIE_EX_L1SCAP_AL1SS | B_PCIE_EX_L1SCAP_AL= 12S | B_PCIE_EX_L1SCAP_PPL11S |B_PCIE_EX_L1SCAP_PPL12S); + } + L1LowSupported =3D ClkreqSupported && IsLtrCapable (RpSbdf) && !L1ssEnab= led; + + /// + /// If L1.SNOOZ and L1.OFF (L1 Sub-States) are not supported and per-por= t CLKREQ# is supported, and LTR is supported: + /// Enable L1.LOW by setting Dxx:Fn:420[17] =3D 1b + /// + if (L1LowSupported) { + PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) B_PCH_PCI= E_CFG_PCIEPMECTL_L1LE); + } else { + PciSegmentAnd32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) ~B_PCH_P= CIE_CFG_PCIEPMECTL_L1LE); + } + + if (L1LowSupported || L1ssEnabled) { + /// + /// f. Set Dxx:Fn:420h[0] to 1b prior to L1 enabling if any L1substat= e is enabled (including L1LOW) + /// + PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, B_PCH_PCIE_CFG_PCI= EPMECTL_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 c= an 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 trus= ts 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 L= 0s/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 =3D PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFuncti= on, 0); + if (!(IsDevicePresent (RpBase))) { + return; + } + RpSbdf.Seg =3D RpSegment; + RpSbdf.Bus =3D RpBus; + RpSbdf.Dev =3D RpDevice; + RpSbdf.Func =3D RpFunction; + RpSbdf.PcieCap =3D PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIE= XP); + + DEBUG ((DEBUG_INFO, "RootportDownstreamConfiguration %x:%x\n", RpDevice,= RpFunction)); + BridgeCleanupList.Count =3D 0; + RecursiveBusAssignment (RpSbdf, BusMin, BusMax, &BridgeCleanupList); + + Mps =3D RecursiveMpsCheck (RpSbdf); + RecursiveMpsConfiguration (RpSbdf, Mps); + ConfigureRpPacketSplit (RpSbdf, Mps); + IoApicPresent =3D RecursiveIoApicCheck (RpSbdf); + ConfigureEoiForwarding (RpSegment, RpBus, RpDevice, RpFunction, IoApicPr= esent); + RecursiveCccConfiguration (RpSbdf, TRUE); + + ClearBusFromTable (&BridgeCleanupList); +} + +/** + Configures the following power-management related features in rootport a= nd 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 c= an 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 trus= ts 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 assig= ned 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 =3D PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFuncti= on, 0); + if (!(IsDevicePresent (RpBase))) { + return; + } + PmOverrideTable.Size =3D AspmOverrideTableSize; + PmOverrideTable.Table =3D AspmOverrideTable; + + DEBUG ((DEBUG_INFO, "RootportDownstreamPmConfiguration %x:%x\n", RpDevic= e, RpFunction)); + PolicyLtr.MaxNoSnoopLatencyScale =3D (RpConfig->LtrMaxNoSnoopLatency & 0= x1c00) >> 10; + PolicyLtr.MaxNoSnoopLatencyValue =3D RpConfig->LtrMaxNoSnoopLatency & 0x= 3FF; + PolicyLtr.MaxSnoopLatencyScale =3D (RpConfig->LtrMaxSnoopLatency & 0x1= c00) >> 10; + PolicyLtr.MaxSnoopLatencyValue =3D RpConfig->LtrMaxSnoopLatency & 0x3F= F; + + RpSbdf.Seg =3D RpSegment; + RpSbdf.Bus =3D RpBus; + RpSbdf.Dev =3D RpDevice; + RpSbdf.Func =3D RpFunction; + RpSbdf.PcieCap =3D PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIE= XP); + // + // 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 numbe= rs to uninitialized bridges, if there are any + // List of such bridges will be kept in CleanupList, so that after PM pr= ogramming is done, bus numbers can brought to original state + // + BridgeCleanupList.Count =3D 0; + RecursiveBusAssignment(RpSbdf, BusMin, BusMax, &BridgeCleanupList); + // + // The 'Recursive...' functions below expect bus numbers to be already a= ssigned + // + RecursiveLtrConfiguration (RpSbdf, PolicyLtr); + ConfigureRpLtrOverride (RpSbdf, RpConfig, &PmOverrideTable); + if (RpConfig->EnableCpm) { + RecursiveCpmConfiguration (RpSbdf); + } + // + // L1 substates can be modified only when L1 is disabled, so this functi= on 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/PeiDxeS= mmPchPsfPrivateLib/PchPsfPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/= Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c new file mode 100644 index 0000000000..f2d20c625a --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPs= fPrivateLib/PchPsfPrivateLib.c @@ -0,0 +1,542 @@ +/** @file + This file contains PSF routines for RC usage + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "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 mi= ght + // still be accessible since the PSF cycle is not completed yet, and cau= ses + // 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 =3D PsfPmcPort (); + + ASSERT (PchPcrRead32 (PsfPort.PsfPid, PsfPort.RegBase + R_PCH_PSFX_PCR_T= 0_SHDW_BAR4) !=3D 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 =3D PsfPmcPort (); + // + // Read ABASE from PSF PMC space BAR4 + // + Address =3D PchPcrRead16 ( + PsfPort.PsfPid, + PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR4 + ); + + ASSERT (Address !=3D 0xFFFF); + + return Address; +} + +/** + Get PMC PWRMBASE value from PSF + + @retval Address Address for PWRM base. +**/ +UINT32 +PsfGetPmcPwrmBase ( + VOID + ) +{ + UINT32 Address; + PSF_PORT PsfPort; + + PsfPort =3D PsfPmcPort (); + // + // Read PWRMBASE from PSF PMC space BAR0 + // + Address =3D PchPcrRead32 ( + PsfPort.PsfPid, + PsfPort.RegBase + R_PCH_PSFX_PCR_T0_SHDW_BAR0 + ); + + ASSERT (Address !=3D 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 =3D 0; PsfTableIndex < PsfTableSize; PsfTableIndex++)= { + if (PsfTable[PsfTableIndex].Id =3D=3D PsfId) { + return PsfTable[PsfTableIndex].SbPid; + } + } + + ASSERT (FALSE); + return 0; +} + + +/** + Get PCH Root PSF ID. This is the PSF segment to which OPDMI/DMI is conne= cted. + + @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 =3D PsfEoiRegData (PsfId, &EoiTargetBase, &EoiCon= trolBase); + PsfSbiPortId =3D PsfSbPortId (PsfId); + + // + // Get number of enabled agents from PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI= register + // + Data32 =3D PchPcrRead32 (PsfSbiPortId, EoiControlBase); + NumOfEnabledTargets =3D (UINT8) (Data32 >> N_PCH_PSFX_PCR_MC_CONTROL_MCA= STX_NUMMC); + + // + // Check if target was not already enabled + // Targets from a different PSF segment are aggregated into single desti= nation on + // current PSF segment. + // + for (TargetIndex =3D 0; TargetIndex < NumOfEnabledTargets; TargetIndex++= ) { + Data32 =3D PchPcrRead32 (PsfSbiPortId, EoiTargetBase + TargetIndex * 4= ); + // + // If target already added don't add it again + // + if (Data32 =3D=3D TargetId.RegVal) { + ASSERT (FALSE); + return; + } + // + // If target is from different PSF segment than currently being analyz= ed + // it is enough that its PsfID is matching + // + if ((Data32 & B_PCH_PSFX_PCR_TARGET_PSFID) >> N_PCH_PSFX_PCR_TARGET_PS= FID =3D=3D TargetId.Fields.PsfId) { + return; + } + } + + // + // Check if next one can be added + // + if (NumOfEnabledTargets >=3D 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_EOI register + // so that other targets are not overridden. is known from the numb= er 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, Ta= rgetId.RegVal); + + // + // Enable new target + // Configure PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI, increase NumMc and set= MultCEn + // + NumOfEnabledTargets++; + Data32 =3D (NumOfEnabledTargets << N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMM= C) | 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 =3D 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 !=3D 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 Multica= st registers + // accordingly to PCH BWG PSF EOI Multicast Configuration + // Since there is a device behind RootPort to which EOI needs to be forw= arded + // enable multicast (MULTCEN) and increase the number of multicast agent= s (NUMMC) + // in Multicast Control Register. + // + PsfEnableEoiTarget (PsfPcieDestinationId (RpIndex)); + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPchPsfPrivateLib/PchPsfPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconP= kg/Pch/Library/Private/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLibCnl.c new file mode 100644 index 0000000000..d1c87a9e84 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPchPs= fPrivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PchPsfPrivateLibInternal.h" + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoI2cPsfRegs[] =3D +{ + 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[] =3D +{ + 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 =3D PID_PSF3; + + if (IsPchLp ()) { + if (I2cNum < ARRAY_SIZE(mPchLpSerialIoI2cPsfRegs)) { + PsfPort.RegBase =3D mPchLpSerialIoI2cPsfRegs[I2cNum]; + return PsfPort; + } + } else { + if (I2cNum < ARRAY_SIZE(mPchHSerialIoI2cPsfRegs)) { + PsfPort.RegBase =3D mPchHSerialIoI2cPsfRegs[I2cNum]; + return PsfPort; + } + } + + ASSERT(FALSE); + return PSF_PORT_NULL; +} + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoSpiPsfRegs[] =3D +{ + 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[] =3D +{ + 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 =3D PID_PSF3; + + if (IsPchLp ()) { + if (SpiNum < ARRAY_SIZE(mPchLpSerialIoSpiPsfRegs)) { + PsfPort.RegBase =3D mPchLpSerialIoSpiPsfRegs[SpiNum]; + return PsfPort; + } + } else { + if (SpiNum < ARRAY_SIZE(mPchHSerialIoSpiPsfRegs)) { + PsfPort.RegBase =3D mPchHSerialIoSpiPsfRegs[SpiNum]; + return PsfPort; + } + } + + ASSERT(FALSE); + return PSF_PORT_NULL; +} + +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoUartPsfRegs[] =3D +{ + 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[] =3D +{ + 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 =3D PID_PSF3; + + if (IsPchLp ()) { + if (UartNum < ARRAY_SIZE(mPchLpSerialIoUartPsfRegs)) { + PsfPort.RegBase =3D mPchLpSerialIoUartPsfRegs[UartNum]; + return PsfPort; + } + } else { + if (UartNum < ARRAY_SIZE(mPchHSerialIoUartPsfRegs)) { + PsfPort.RegBase =3D 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 =3D 0; + *EoiTargetBase =3D 0; + *EoiControlBase =3D 0; + + switch (PsfId) { + case 1: + if (IsPchLp ()) { + *EoiTargetBase =3D R_CNL_PCH_LP_PSF1_PCR_PSF_MC_AGENT_MCAST0_TGT0_= EOI; + *EoiControlBase =3D R_CNL_PCH_LP_PSF1_PCR_PSF_MC_CONTROL_MCAST0_EO= I; + MaxTargets =3D 17; + } else { + *EoiTargetBase =3D R_CNL_PCH_H_PSF1_PCR_PSF_MC_AGENT_MCAST0_TGT0_E= OI; + *EoiControlBase =3D R_CNL_PCH_H_PSF1_PCR_PSF_MC_CONTROL_MCAST0_EOI= ; + MaxTargets =3D 7; + } + break; + + case 3: + *EoiTargetBase =3D R_CNL_PCH_PSF3_PCR_PSF_MC_AGENT_MCAST0_TGT0_EOI; + *EoiControlBase =3D R_CNL_PCH_PSF3_PCR_PSF_MC_CONTROL_MCAST0_EOI; + MaxTargets =3D 1; + break; + + case 6: + if (IsPchH ()) { + *EoiTargetBase =3D R_CNL_PCH_H_PSF6_PCR_PSF_MC_AGENT_MCAST0_TGT0_E= OI; + *EoiControlBase =3D R_CNL_PCH_H_PSF6_PCR_PSF_MC_CONTROL_MCAST0_EOI= ; + MaxTargets =3D 8; + } + break; + + case 7: + if (IsPchH ()) { + *EoiTargetBase =3D R_CNL_PCH_H_PSF7_PCR_PSF_MC_AGENT_MCAST0_TGT0_E= OI; + *EoiControlBase =3D R_CNL_PCH_H_PSF7_PCR_PSF_MC_CONTROL_MCAST0_EOI= ; + MaxTargets =3D 8; + } + break; + + case 8: + if (IsPchH ()) { + *EoiTargetBase =3D R_CNL_PCH_H_PSF8_PCR_PSF_MC_AGENT_MCAST0_TGT0_E= OI; + *EoiControlBase =3D R_CNL_PCH_H_PSF8_PCR_PSF_MC_CONTROL_MCAST0_EOI= ; + MaxTargets =3D 8; + } + break; + } + return MaxTargets; +} + +GLOBAL_REMOVE_IF_UNREFERENCED PSF_PORT_DEST_ID PchLpRpDestId[] =3D +{ + {0x18000}, {0x18001}, {0x18002}, {0x18003}, // SPA: PSF1, PortID =3D 0 + {0x18200}, {0x18201}, {0x18202}, {0x18203}, // SPB: PSF1, PortID =3D 2 + {0x18400}, {0x18401}, {0x18402}, {0x18403}, // SPC: PSF1, PortID =3D 4 + {0x18600}, {0x18601}, {0x18602}, {0x18603} // SPD: PSF1, PortID =3D 6 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED PSF_PORT_DEST_ID PchHRpDestId[] =3D +{ + {0x68000}, {0x68001}, {0x68002}, {0x68003}, // SPA: PSF6, PortID =3D 0 + {0x88000}, {0x88001}, {0x88002}, {0x88003}, // SPB: PSF8, PortID =3D 0 + {0x68100}, {0x68101}, {0x68102}, {0x68103}, // SPC: PSF6, PortID =3D 1 + {0x78000}, {0x78001}, {0x78002}, {0x78003}, // SPD: PSF7, PortID =3D 0 + {0x78100}, {0x78101}, {0x78102}, {0x78103}, // SPE: PSF7, PortID =3D 1 + {0x88100}, {0x88101}, {0x88102}, {0x88103} // SPF: PSF8, PortID =3D 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 =3D PID_PSF3; + + if (IsPchLp ()) { + PsfPort.RegBase =3D R_CNL_PCH_LP_PSF3_PCR_T0_SHDW_PMC_REG_BASE; + } else { + PsfPort.RegBase =3D R_CNL_PCH_H_PSF3_PCR_T0_SHDW_PMC_REG_BASE; + } + return PsfPort; +} + +GLOBAL_REMOVE_IF_UNREFERENCED PSF_SEGMENT mPchLpPsfTable[] =3D +{ + {1, PID_PSF1}, + {2, PID_PSF2}, + {3, PID_PSF3}, + {4, PID_PSF4}, + {5, PID_CSME_PSF} +}; + +GLOBAL_REMOVE_IF_UNREFERENCED PSF_SEGMENT mPchHPsfTable[] =3D +{ + {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 =3D mPchLpPsfTable; + *PsfTableLength =3D ARRAY_SIZE(mPchLpPsfTable); + } else { + *PsfTable =3D mPchHPsfTable; + *PsfTableLength =3D ARRAY_SIZE(mPchHPsfTable); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPmcPrivateLib/PeiPmcPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch= /Library/Private/PeiDxeSmmPmcPrivateLib/PeiPmcPrivateLib.c new file mode 100644 index 0000000000..f88febfa48 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/PeiPmcPrivateLib.c @@ -0,0 +1,92 @@ +/** @file + PCH private PEI PMC Library for all PCH generations. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 =3D PeiServicesLocatePpi ( + &gSiPolicyPpiGuid, + 0, + NULL, + (VOID **)&SiPolicy + ); + ASSERT_EFI_ERROR (Status); + + Status =3D GetConfigBlock ((VOID *) SiPolicy, &gPmConfigGuid, (VOID *) &= PmConfig); + ASSERT_EFI_ERROR (Status); + + PchPmTimerEnabled =3D TRUE; + if (!PmConfig->EnableTcoTimer) { + PchPmTimerEnabled =3D FALSE; + } + + DEBUG ((DEBUG_INFO, "PmcIsPchPmTimerEnabled () =3D %x\n", PchPmTimerEnab= led)); + + return PchPmTimerEnabled; +} + +/** + Lock down PMC settings + + @param[in] SiPolicy The SI Policy PPI instance +**/ +VOID +PmcLockSettings ( + IN SI_POLICY_PPI *SiPolicy + ) +{ + + UINT32 PchPwrmBase; + PchPwrmBase =3D 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/PeiDxeS= mmPmcPrivateLib/PmcPrivateLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Li= brary/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c new file mode 100644 index 0000000000..a6ccf4b96b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PmcPrivateLibInternal.h" + +/** + Send PMC IPC1 Normal Read/Write command + + @param[in] Command Command to be issued to PMC IPC 1 interfac= e + @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 iss= ued to PMC IPC 1 interface + @param[out] ReadBufPtr Pointer to Structure of 4 DWORDs to be fil= led 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=3D0x%02X, IPC_SUB_CMD= =3D 0x%02X, IPC_SIZE=3D0x%02X \n", Command, SubCmdId, CmdSize)); + DEBUG ((DEBUG_INFO, "WBUF0=3D0x%08X, WBUF1=3D0x%08X, WBUF2=3D0x%08X, WBU= F3=3D0x%08X \n", WriteBufPtr->Buf0, WriteBufPtr->Buf1, WriteBufPtr->Buf2, W= riteBufPtr->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 =3D 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 =3D 0; + Status =3D EFI_SUCCESS; + while (TRUE) { + IpcSts =3D MmioRead32 (PchPwrmBase + R_PMC_PWRM_IPC_STS); + if ((IpcSts & B_PMC_PWRM_IPC_STS_BUSY) =3D=3D 0) { + break; + } + + if (Timeout > (1000 * 100)) { + Status =3D EFI_TIMEOUT; + break; + } + MicroSecondDelay (10); + Timeout++; + } + + if ((IpcSts & B_PMC_PWRM_IPC_STS_ERROR) !=3D 0) { + Status =3D EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "PmcSendCommand() Error: IPC_STS=3D0x%08X\n", Ipc= Sts)); + return Status; + } + + if (ReadBufPtr !=3D NULL) { + // + // Fill the ReadBuffer contents with the Data that needs to be read f= rom PMC + // + ReadBufPtr->Buf0 =3D MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF0); + ReadBufPtr->Buf1 =3D MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF1); + ReadBufPtr->Buf2 =3D MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF2); + ReadBufPtr->Buf3 =3D MmioRead32(PchPwrmBase + R_PMC_PWRM_IPC_RBUF3); + + DEBUG ((DEBUG_INFO, "RBUF0=3D0x%08X, RBUF1=3D0x%08X, RBUF2=3D0x%08X, R= BUF3=3D0x%08X \n", ReadBufPtr->Buf0, ReadBufPtr->Buf1, ReadBufPtr->Buf2, Re= adBufPtr->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) !=3D 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 sp= ace, so must not exceed 0xFFFF. + Only address matching PcdAcpiBaseAddress is the acceptable value for ACP= I 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 !=3D PcdGet16 (PcdAcpiBaseAddress)) { + DEBUG ((DEBUG_ERROR, "PmcSetAcpiBase Error. Invalid Address: %x.\n", A= ddress)); + 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 PWRM= BASE + + @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 !=3D PCH_PWRM_BASE_ADDRESS) { + DEBUG ((DEBUG_ERROR, "PmcSetPwrmBase Error. Invalid Address: %x.\n", A= ddress)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + PmcBase =3D 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) =3D=3D 0xFFFF) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + // + // Disable PWRMBASE in PMC Device first before changing PWRM base addres= s. + // + 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 ga= ting) + 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) !=3D 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) !=3D 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) =3D=3D 0); +} + +/** + This function disables ISH device by static power gating. + For static power gating to take place Global Reset, G3 or DeepSx transit= ion must happen. +**/ +VOID +PmcStaticDisableIsh ( + VOID + ) +{ + // + // Set PWRMBASE + ST_PG_FDIS_PMC_1[5] =3D 1b to statically disable ISH C= ontroller + // + 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 Deep= Sx transition. +**/ +VOID +PmcEnableIsh ( + VOID + ) +{ + // + // Set PWRMBASE + ST_PG_FDIS_PMC_1[5] =3D 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) !=3D 0); +} + +/** + This function disables GbE device by static power gating and enables Mod= PHY SPD gating (PCH-LP only). + For static power gating to take place Global Reset, G3 or DeepSx transit= ion must happen. +**/ +VOID +PmcStaticDisableGbe ( + VOID + ) +{ + UINT32 PchPwrmBase; + PchPwrmBase =3D PmcGetPwrmBase (); + // + // Set PWRMBASE + ST_PG_FDIS_PMC_1[0] =3D 1b to statically disable GbE C= ontroller + // + MmioOr32 (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1, B_PMC_PWRM_ST_PG_FD= IS_PMC_1_GBE_FDIS_PMC); + + if (PmcIsModPhySusPgSupported ()) { + // + // Set MSPDRTREQ: + // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[13] =3D 1 to enable ASL code trigg= er 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 Deep= Sx transition. +**/ +VOID +PmcEnableGbe ( + VOID + ) +{ + // + // Set PWRMBASE + ST_PG_FDIS_PMC_1[0] =3D 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_P= MC_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS) =3D=3D 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_P= G_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_P= MC_PWRM_FUSE_DIS_RD_2_CNVI_FUSE_SS_DIS) =3D=3D 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) !=3D 0); +} + +/** + This function enables CNVi device by disabling static power gating. + Static power gating disabling takes place after Global Reset, G3 or Deep= Sx 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 transit= ion 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 enab= les 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 =3D PmcGetPwrmBase (); + // + // Set PchPwrmBase + NST_PG_FDIS_1 to function disable PCIE port in PMC + // + if (IsPchH () && RpIndex >=3D 20) { + NstPgFdis1Mask =3D B_PCH_H_PMC_PWRM_NST_PG_FDIS_1_PCIE_F0_FDIS_PMC << = (RpIndex % 20); + } else { + NstPgFdis1Mask =3D B_PMC_PWRM_NST_PG_FDIS_1_PCIE_A0_FDIS_PMC << RpInde= x; + } + MmioOr32 (PchPwrmBase + R_PMC_PWRM_NST_PG_FDIS_1, NstPgFdis1Mask); + + if (PmcIsModPhySusPgSupported ()) { + // + // Set MSPDRTREQ: + // PWRMBASE + R_PWRM_MODPHY_PM_CFG5[26:0] =3D 1 to enable ASL code tri= gger request for ModPHY SPD gating. + // + if (RpIndex <=3D 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 =3D PmcGetPwrmBase (); + + // + // Set PWRMBASE + NST_PG_FDIS_1 [0] =3D 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] =3D 1 to enable ASL code tr= igger request for ModPHY SPD gating. + // + MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_P= M_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 =3D PmcGetPwrmBase (); + + // + // Set PWRMBASE + NST_PG_FDIS_1 [26] =3D 1b to disable XDCI Controller i= n 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] =3D 1 to enable ASL code trigg= er request for ModPHY SPD gating. + // + MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_P= M_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_P= MC_PWRM_FUSE_DIS_RD_2_OTG_FUSE_SS_DIS) =3D=3D 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_PW= RM_SW_PG_CTRL_LOCK) !=3D 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) !=3D 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_ETR= 3_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_ETR= 3_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_PMC= ON_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_HOS= T_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) !=3D 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] =3D { + 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 <=3D PmcSwSmiRate64ms); + + PchPwrmBase =3D 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 pos= sible values +**/ +VOID +PmcSetPeriodicSmiRate ( + IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate + ) +{ + UINT32 PchPwrmBase; + STATIC UINT8 PeriodicSmiRateRegVal[4] =3D { + 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 <=3D PmcPeriodicSmiRate64s); + + PchPwrmBase =3D 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 =3D MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GPIO_CFG)= ); + + *GpeDw0Value =3D ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW0) >> N_PMC_PWRM_= GPIO_CFG_GPE0_DW0); + *GpeDw1Value =3D ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW1) >> N_PMC_PWRM_= GPIO_CFG_GPE0_DW1); + *GpeDw2Value =3D ((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 =3D (UINT32) ~(B_PMC_PWRM_GPIO_CFG_GPE0_DW2 | B_PMC_PWRM_GPIO_= CFG_GPE0_DW1 | B_PMC_PWRM_GPIO_CFG_GPE0_DW0); + Data32Or =3D (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 =3D PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_SLP_CTRL, 0, 4, &W= buf, 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 =3D 1; + Status =3D PmcSendCommand (V_PMC_PWRM_IPC_CMD_COMMAND_SLP_CTRL, 0, 4, &W= buf, 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 =3D 2 for NMI delivery control and status register (entire regi= ster PCR[ITSS] 0x3330) + // + Wbuf.Buf0 =3D V_PMC_PWRM_IPC_CMD_WBUF0_PROXY_NMI; + Status =3D 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 =3D 2 for NMI delivery control and status register (entire regi= ster PCR[ITSS] 0x3330) + // + Wbuf.Buf0 =3D V_PMC_PWRM_IPC_CMD_WBUF0_PROXY_NMI; + Wbuf.Buf1 =3D NmiRegister; + Status =3D 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_MO= DPHY_PM_CFG5_MSPDRTREQ_GBE); + } +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPmcPrivateLib/PmcPrivateLibClient.c b/Silicon/Intel/CoffeelakeSiliconPkg/= Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibClient.c new file mode 100644 index 0000000000..2411a2be23 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D PmcGetPwrmBase (); + + ASSERT (SataCtrlIndex < GetPchMaxSataControllerNum ()); + + // + // Set PWRMBASE + NST_PG_FDIS_1 [22] =3D 1b to disable SATA Controller i= n 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] =3D 1 to enable ASL code trigg= er request for ModPHY SPD gating. + // + MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_P= M_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_P= MC_PWRM_FUSE_DIS_RD_2_SATA_FUSE_SS_DIS) =3D=3D 0); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPmcPrivateLib/PmcPrivateLibCnl.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch= /Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibCnl.c new file mode 100644 index 0000000000..847be42937 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D BIT0; + Status =3D 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 =3D BIT1; + Status =3D 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 signal= s 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 =3D PmcGetPwrmBase (); + if (IsPchLp () && (PchStepping () < PCH_B0)) { + /// + /// PWRMBASE + 0x1880 =3D 0x0 + /// + MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING, 0x0); + } else { + /// + /// PWRMBASE + 0x1880 =3D 0x2F8FBB01 + /// + MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING, 0x2F8FBB01); + } + + if (IsPchLp ()) { + if (PchStepping () < PCH_B0) { + /// + /// PWRMBASE + 0x1884 =3D 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 =3D 0x0 + /// + MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA, 0x0); + /// + /// PWRMBASE + 0x188C =3D 0x0 + /// + MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SA2, 0x0); + } else { + /// + /// PWRMBASE + 0x1888 =3D 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 =3D 0x0 + /// + MmioWrite32 (PchPwrmBase + R_PMC_PWRM_EN_CW_SLOW_RING_CF, 0x0); + } else { + /// + /// PWRMBASE + 0x1898 =3D 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] =3D 1,1 + /// PWRMBASE + 0x1E00[29] =3D 0 + /// PWRMBASE + 0x1E00[10:6] =3D 0 + /// PWRMBASE + 0x1E00[3:0] =3D 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 =3D 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 Deep= Sx transition. +**/ +VOID +PmcEnableSerialIo ( + VOID + ) +{ + // + // Set PWRMBASE + ST_PG_FDIS_PMC_2 + // + MmioAnd32 (PmcGetPwrmBase () + R_PMC_PWRM_ST_PG_FDIS_PMC_2, (UINT32)~B_P= MC_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 transit= ion 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 (st= atic 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) =3D=3D B_PMC_PWRM_ST_PG_FDIS_PMC_2_SE= RIALIO); +} + +/** + This function checks if SerialIo device is supported (not disabled by fu= se) + + @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_P= MC_PWRM_FUSE_DIS_RD_2_SERIALIO_FUSE_SS_DIS) =3D=3D 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_PWR= M_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 =3D B_PCH_LP_PMC_PWRM_NST_PG_FDIS_1_SDCARD_FDIS_PMC; + } else { + ScsDevicePgMask =3D 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 =3D=3D 0) && IsPchLp ()); + + PchPwrmBase =3D 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] =3D 1 to enable ASL code tr= igger request for ModPHY SPD gating. + // + MmioOr32 (PchPwrmBase + R_PMC_PWRM_MODPHY_PM_CFG5, B_PMC_PWRM_MODPHY_P= M_CFG5_MSPDRTREQ_UFS2); + } +} + +/** + This function checks if SCS eMMC device is supported (not disabled by fu= se) + + @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_P= MC_PWRM_FUSE_DIS_RD_2_EMMC_FUSE_SS_DIS) =3D=3D 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_P= MC_PWRM_FUSE_DIS_RD_2_SDX_FUSE_SS_DIS) =3D=3D 0); +} + +/** + This function checks if SCS UFS device is supported (not disabled by fus= e) + + @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_P= MC_PWRM_FUSE_DIS_RD_2_UFSX2_FUSE_SS_DIS) =3D=3D 0); +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeS= mmPmcPrivateLib/PmcPrivateLibWithS3.c b/Silicon/Intel/CoffeelakeSiliconPkg/= Pch/Library/Private/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c new file mode 100644 index 0000000000..bbe944da5c --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiDxeSmmPmcPr= ivateLib/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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + This function locks down PMC (DebugModeLock) +**/ +VOID +PmcLockWithS3BootScript ( + VOID + ) +{ + + UINT32 PchPwrmBase; + + PchPwrmBase =3D 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 bot= h + the Host and the ME partitions after CF9h write of 6h or Eh. +**/ +VOID +PmcDisableCf9GlobalResetInS3BootScript ( + VOID + ) +{ + UINT32 Data; + + UINT32 PchPwrmBase; + PchPwrmBase =3D PmcGetPwrmBase (); + + Data =3D MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3); + + Data &=3D (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 bot= h + 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 =3D PmcGetPwrmBase (); + + Data =3D MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3); + + Data &=3D (UINT32) ~B_PMC_PWRM_ETR3_CF9GR; + Data |=3D (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 =3D 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 =3D 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 Scrip= t programming +**/ +VOID +PmcLockFunctionDisableConfigWithS3BootScript ( + VOID + ) +{ + UINT32 PchPwrmBase; + + PchPwrmBase =3D PmcGetPwrmBase (); + + MmioOr32 (PchPwrmBase + R_PMC_PWRM_ST_PG_FDIS_PMC_1, (UINT32) (B_PMC_PWR= M_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 =3D 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/PeiGpio= HelpersLib/PeiGpioHelpersLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Lib= rary/Private/PeiGpioHelpersLib/PeiGpioHelpersLib.c new file mode 100644 index 0000000000..9c722bce07 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioHelpers= Lib/PeiGpioHelpersLib.c @@ -0,0 +1,356 @@ +/** @file + This file contains routines for PEI GPIO Helpers Lib + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 pe= r group DwNum must be 0. + + @retval GpioUnlockHobIndex +**/ +STATIC +UINT32 +GpioUnlockDataIndex ( + IN UINT32 GroupIndex, + IN UINT32 DwNum + ) +{ + UINT32 GpioUnlockDataIndex; + UINT32 Index; + + GpioUnlockDataIndex =3D 0; + + for (Index =3D 0; Index < GroupIndex; Index++) { + GpioUnlockDataIndex +=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (GpioGetG= roupFromGroupIndex (Index))) + 1; + } + + GpioUnlockDataIndex +=3D 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 =3D GpioGetLowestGroup (); + GroupMax =3D GpioGetHighestGroup (); + GpioUnlockDataRecords =3D 0; + + for (Group =3D GroupMin; Group <=3D GroupMax; Group++) { + GpioUnlockDataRecords +=3D GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)= ) + 1; + } + + HobData =3D BuildGuidHob (&gGpioLibUnlockHobGuid, GpioUnlockDataRecords = * sizeof (GPIO_UNLOCK_HOB_DATA)); + if (HobData =3D=3D 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 da= ta. + If HOB doesn't exist it will be created. + + @param[out] GpioUnlockData pointer to GPIO Unlock data structur= e + + @retval Length number of GPIO unlock data records +**/ +STATIC +UINT32 +GpioGetUnlockData ( + GPIO_UNLOCK_HOB_DATA **GpioUnlockData + ) +{ + VOID *Hob; + + Hob =3D GetFirstGuidHob (&gGpioLibUnlockHobGuid); + if (Hob =3D=3D NULL) { + // + // It is the first time this function is used so create the HOB + // + *GpioUnlockData =3D GpioCreateUnlockData (); + if (*GpioUnlockData =3D=3D NULL) { + return 0; + } + Hob =3D GetFirstGuidHob (&gGpioLibUnlockHobGuid); + } else { + *GpioUnlockData =3D (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 structur= e + + @retval Length number of GPIO unlock data records +**/ +STATIC +UINT32 +GpioLocateUnlockData ( + GPIO_UNLOCK_HOB_DATA **GpioUnlockData + ) +{ + VOID *Hob; + + Hob =3D GetFirstGuidHob (&gGpioLibUnlockHobGuid); + if (Hob =3D=3D NULL) { + *GpioUnlockData =3D NULL; + return 0; + } + + *GpioUnlockData =3D (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 =3D=3D GpioLockDefault) { + return EFI_SUCCESS; + } + + Length =3D GpioGetUnlockData (&GpioUnlockData); + if (Length =3D=3D 0) { + return EFI_NOT_FOUND; + } + + GroupIndex =3D GpioGetGroupIndexFromGpioPad (GpioPad); + PadNumber =3D GpioGetPadNumberFromGpioPad (GpioPad); + Index =3D GpioUnlockDataIndex (GroupIndex, GPIO_GET_DW_NUM (PadNumber)); + + if (Index >=3D Length) { + return EFI_INVALID_PARAMETER; + } + + if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) =3D=3D Gpio= PadConfigUnlock) { + GpioUnlockData[Index].PadConfig |=3D 1 << (GpioGetPadNumberFromGpioPad= (GpioPad) % 32); + } + + if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) =3D=3D GpioOu= tputStateUnlock) { + GpioUnlockData[Index].OutputState |=3D 1 << (GpioGetPadNumberFromGpioP= ad (GpioPad) % 32); + } + + return EFI_SUCCESS; +} + +/** + This procedure stores GPIO group data about pads which PadConfig needs t= o be unlocked. + + @param[in] GroupIndex GPIO group index + @param[in] DwNum DWORD index for a group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] UnlockedPads DWORD bitmask for pads which are going t= o 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 =3D=3D 0) { + // + // No pads to be left unlocked + // + return EFI_SUCCESS; + } + + Length =3D GpioGetUnlockData (&GpioUnlockData); + if (Length =3D=3D 0) { + return EFI_NOT_FOUND; + } + + Index =3D GpioUnlockDataIndex (GroupIndex, DwNum); + if (Index >=3D Length) { + return EFI_INVALID_PARAMETER; + } + + GpioUnlockData[Index].PadConfig |=3D UnlockedPads; + return EFI_SUCCESS; +} + +/** + This procedure stores GPIO group data about pads which Output state need= s 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 pe= r group DwNum must be 0. + @param[in] UnlockedPads DWORD bitmask for pads which are going t= o 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 =3D=3D 0) { + // + // No pads to be left unlocked + // + return EFI_SUCCESS; + } + + Length =3D GpioGetUnlockData (&GpioUnlockData); + if (Length =3D=3D 0) { + return EFI_NOT_FOUND; + } + + Index =3D GpioUnlockDataIndex (GroupIndex, DwNum); + if (Index >=3D Length) { + return EFI_INVALID_PARAMETER; + } + + GpioUnlockData[Index].OutputState |=3D UnlockedPads; + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO group data with pads, which PadConfig is su= pposed 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 pe= r group DwNum must be 0. + @retval UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: to be locked, 1: Leave un= locked +**/ +UINT32 +GpioGetGroupDwUnlockPadConfigMask ( + IN UINT32 GroupIndex, + IN UINT32 DwNum + ) +{ + GPIO_UNLOCK_HOB_DATA *GpioUnlockData; + UINT32 Length; + UINT32 Index; + + Length =3D GpioLocateUnlockData (&GpioUnlockData); + if (Length =3D=3D 0) { + return 0; + } + + Index =3D GpioUnlockDataIndex (GroupIndex, DwNum); + if (Index >=3D Length) { + return 0; + } + + return GpioUnlockData[Index].PadConfig; +} + +/** + This procedure will get GPIO group data with pads, which Output is suppo= sed 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 pe= r group DwNum must be 0. + @retval UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: to be locked, 1: Leave un= locked +**/ +UINT32 +GpioGetGroupDwUnlockOutputMask ( + IN UINT32 GroupIndex, + IN UINT32 DwNum + ) +{ + GPIO_UNLOCK_HOB_DATA *GpioUnlockData; + UINT32 Length; + UINT32 Index; + + Length =3D GpioLocateUnlockData (&GpioUnlockData); + if (Length =3D=3D 0) { + return 0; + } + + Index =3D GpioUnlockDataIndex (GroupIndex, DwNum); + if (Index >=3D Length) { + return 0; + } + + return GpioUnlockData[Index].OutputState; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpio= NameBufferLib/GpioNameBufferPei.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/= Library/Private/PeiGpioNameBufferLib/GpioNameBufferPei.c new file mode 100644 index 0000000000..1b05378799 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/PeiGpioNameBuf= ferLib/GpioNameBufferPei.c @@ -0,0 +1,68 @@ +/** @file + This file contains GpioMemLib implementation for PEI phase + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +STATIC CONST EFI_GUID mGpioNamesPrivateHobGuid =3D {0x9AE3138D, 0x4EBF, 0x= 4E90, {0x87, 0x96, 0x11, 0xD3, 0x10, 0x04, 0x60, 0x0A}}; + +STATIC volatile BOOLEAN mGlobalMemoryWorking =3D 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 =3D NULL; + GpioNameBuffer =3D NULL; + + Hob =3D GetFirstGuidHob (&mGpioNamesPrivateHobGuid); + if (Hob !=3D NULL){ + GpioNameBuffer =3D (CHAR8*) GET_GUID_HOB_DATA (Hob); + } else { + GpioNameBuffer =3D (CHAR8*) BuildGuidHob (&mGpioNamesPrivateHobGuid, G= PIO_NAME_LENGTH_MAX); + if (GpioNameBuffer =3D=3D 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 =3D TRUE; + + if (mGlobalMemoryWorking) { + return mGpioNameBuffer; + } else { + return GetBufferFromHob (); + } +} + --=20 2.16.2.windows.1