From: "Chuang, Rosen" <rosen.chuang@intel.com>
To: "Chaganty, Rangasai V" <rangasai.v.chaganty@intel.com>,
"Kasbekar, Saloni" <saloni.kasbekar@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>
Subject: Re: [edk2-devel] [PATCH 04/10] AlderlakeSiliconPkg/IpBlock: Add Pmc, Spi components
Date: Fri, 15 Sep 2023 03:04:02 +0000 [thread overview]
Message-ID: <DM8PR11MB562470F531B68BC127AC6FEE92F6A@DM8PR11MB5624.namprd11.prod.outlook.com> (raw)
In-Reply-To: <MW4PR11MB577622B0CDBB240388352B83B6F7A@MW4PR11MB5776.namprd11.prod.outlook.com>
Reviewed-by: Rosen Chuang <rosen.chuang@intel.com>
-----Original Message-----
From: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
Sent: Friday, September 15, 2023 5:40 AM
To: Kasbekar, Saloni <saloni.kasbekar@intel.com>; devel@edk2.groups.io
Cc: Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: RE: [PATCH 04/10] AlderlakeSiliconPkg/IpBlock: Add Pmc, Spi components
Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>
-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com>
Sent: Wednesday, September 13, 2023 3:14 PM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 04/10] AlderlakeSiliconPkg/IpBlock: Add Pmc, Spi components
Adds the following modules:
- IpBlock/Pmc/IncludePrivate
- IpBlock/Pmc/Library
- IpBlock/Pmc/LibraryPrivate
- IpBlock/Spi/IncludePrivate
- IpBlock/Spi/Library
- IpBlock/Spi/LibraryPrivate
- IpBlock/Spi/Smm
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
.../IncludePrivate/Library/PmcPrivateLib.h | 47 +
.../IpBlock/Pmc/IncludePrivate/PmcSocConfig.h | 67 +
.../PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf | 38 +
.../Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c | 50 +
.../PeiDxeSmmPmcPrivateLib.inf | 43 +
.../PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c | 86 ++
.../Spi/IncludePrivate/Library/SpiCommonLib.h | 376 ++++++
.../Spi/IncludePrivate/Register/SpiRegs.h | 116 ++
.../IpBlock/Spi/Library/PeiSpiLib/PchSpi.c | 209 +++
.../Spi/Library/PeiSpiLib/PeiSpiLib.inf | 41 +
.../BaseSpiCommonLib/BaseSpiCommonLib.inf | 29 +
.../BaseSpiCommonLib/SpiCommon.c | 1127 +++++++++++++++++
.../AlderlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c | 387 ++++++
.../IpBlock/Spi/Smm/SpiSmm.inf | 46 +
14 files changed, 2662 insertions(+)
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/PmcSocConfig.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PchSpi.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PeiSpiLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h
new file mode 100644
index 0000000000..6ec244b127
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h
@@ -0,0 +1,47 @@
+/** @file
+ Header file for private PmcLib.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PMC_PRIVATE_LIB_H_
+#define _PMC_PRIVATE_LIB_H_
+
+#include <Library/PmcLib.h>
+#include "Register/PmcRegs.h"
+
+typedef enum {
+ PmcSwSmiRate1p5ms = 0,
+ PmcSwSmiRate16ms,
+ PmcSwSmiRate32ms,
+ PmcSwSmiRate64ms
+} PMC_SWSMI_RATE;
+
+/**
+ This function sets SW SMI Rate.
+
+ @param[in] SwSmiRate Refer to PMC_SWSMI_RATE for possible values
+**/
+VOID
+PmcSetSwSmiRate (
+ IN PMC_SWSMI_RATE SwSmiRate
+ );
+
+typedef enum {
+ PmcPeriodicSmiRate8s = 0,
+ PmcPeriodicSmiRate16s,
+ PmcPeriodicSmiRate32s,
+ PmcPeriodicSmiRate64s
+} PMC_PERIODIC_SMI_RATE;
+
+/**
+ This function sets Periodic SMI Rate.
+
+ @param[in] PeriodicSmiRate Refer to PMC_PERIODIC_SMI_RATE for possible values
+**/
+VOID
+PmcSetPeriodicSmiRate (
+ IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate
+ );
+
+#endif // _PMC_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/PmcSocConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/PmcSocConfig.h
new file mode 100644
index 0000000000..523a84a180
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/PmcSocConfig.h
@@ -0,0 +1,67 @@
+/** @file
+ PMC SoC configuration
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PMC_SOC_CONFIGURATION_H_
+#define _PMC_SOC_CONFIGURATION_H_
+
+typedef enum {
+ AdrSinglePhase = 0,
+ AdrDualPhase
+} ADR_PHASE_TYPE;
+
+typedef enum {
+ AdrGpioB = 0,
+ AdrGpioC
+} ADR_GPIO;
+
+typedef enum {
+ AdrOverPmSync = 0,
+ AdrOverDmi
+} ADR_MSG_INTERFACE;
+
+typedef struct {
+ BOOLEAN Supported;
+ ADR_PHASE_TYPE AdrPhaseType;
+ ADR_GPIO AdrGpio;
+ ADR_MSG_INTERFACE AdrMsgInterface;
+ //
+ // On some designs ADR_GEN_CFG has been moved in the HW.
+ // Set this to if ADR_GEN_CFG is located at 0x1908
+ //
+ BOOLEAN AdrGenCfgMoved;
+} PMC_ADR_SOC_CONFIG;
+
+typedef struct {
+ BOOLEAN CppmCgInterfaceVersion;
+ BOOLEAN LpmSupported;
+ UINT8 LpmInterfaceVersion;
+ BOOLEAN OsIdleSupported;
+ BOOLEAN TimedGpioSupported;
+ UINT32 CpuIovrRampTime;
+ BOOLEAN PsOnSupported;
+ BOOLEAN ModPhySusPgSupported;
+ UINT8 SciIrq;
+ BOOLEAN FabricPowerGatingCppmQualificationEnable;
+ BOOLEAN EspiBoot;
+ BOOLEAN UsbDbcConnected;
+ UINT32 Usb3LanesConnectedBitmask;
+ BOOLEAN DisableIosfSbClockGating;
+ BOOLEAN SkipModPhyGatingPolicy;
+ PMC_ADR_SOC_CONFIG AdrSocConfig;
+ BOOLEAN AllSbrIdleQualifierEnable;
+ UINT32 LpmPriVal; ///< Low Power Mode Priority
+
+} PMC_SOC_CONFIG;
+
+typedef struct {
+ BOOLEAN OverrideFetRampTime;
+ UINT8 FetRampTime;
+ UINT8 IsFetRampTime;
+ UINT16 FuseDownloadDelayUs;
+} PMC_FIVR_SOC_CONFIG;
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
new file mode 100644
index 0000000000..e9784ceb9c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
@@ -0,0 +1,38 @@
+## @file
+# PEI/DXE/SMM PCH PMC Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPmcLib
+ FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PmcLib
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PciSegmentLib
+ PchCycleDecodingLib
+ PchPcrLib
+ PchInfoLib
+ PmcPrivateLib
+ BaseMemoryLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ AlderlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+
+[Sources]
+ PmcLib.c
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c
new file mode 100644
index 0000000000..91e741a294
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c
@@ -0,0 +1,50 @@
+/** @file
+ PCH PMC Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <PchReservedResources.h>
+#include <Register/PmcRegs.h>
+#include <Register/PchRegs.h>
+
+/**
+ Get PCH ACPI base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT16
+PmcGetAcpiBase (
+ VOID
+ )
+{
+ return PcdGet16 (PcdAcpiBaseAddress);
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT32
+PmcGetPwrmBase (
+ VOID
+ )
+{
+ return PCH_PWRM_BASE_ADDRESS;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLib.inf
new file mode 100644
index 0000000000..e6693f767d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PEI/DXE/SMM PCH PMC Private Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPmcPrivateLib
+FILE_GUID = EB69B12B-6D4C-4B12-BB31-66CBCC4C1DC7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+TimerLib
+PciSegmentLib
+PmcLib
+BaseMemoryLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+
+[FixedPcd]
+
+[Sources]
+PmcPrivateLib.c
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
new file mode 100644
index 0000000000..b720305d15
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
@@ -0,0 +1,86 @@
+/** @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) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <PchReservedResources.h>
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchPciBdfLib.h>
+
+
+/**
+ This function sets SW SMI Rate.
+
+ @param[in] SwSmiRate Refer to PMC_SWSMI_RATE for possible values
+**/
+VOID
+PmcSetSwSmiRate (
+ IN PMC_SWSMI_RATE SwSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 SwSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_1_5MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_16MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_32MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_64MS
+ };
+
+ ASSERT (SwSmiRate <= PmcSwSmiRate64ms);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // SWSMI_RATE_SEL BIT (PWRMBASE offset 1020h[7:6]) bits are in RTC well
+ //
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL,
+ SwSmiRateRegVal[SwSmiRate]
+ );
+}
+
+/**
+ This function sets Periodic SMI Rate.
+
+ @param[in] PeriodicSmiRate Refer to PMC_PERIODIC_SMI_RATE for possible values
+**/
+VOID
+PmcSetPeriodicSmiRate (
+ IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 PeriodicSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_8S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_16S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_32S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_64S
+ };
+
+ ASSERT (PeriodicSmiRate <= PmcPeriodicSmiRate64s);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_PER_SMI_SEL,
+ PeriodicSmiRateRegVal[PeriodicSmiRate]
+ );
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
new file mode 100644
index 0000000000..e13718c9e9
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
@@ -0,0 +1,376 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SPI_COMMON_LIB_H_
+#define _SPI_COMMON_LIB_H_
+
+#include <Protocol/Spi.h>
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define SPI_WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
+
+#define SPI_WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
+
+///
+/// Flash cycle Type
+///
+typedef enum {
+ FlashCycleRead,
+ FlashCycleWrite,
+ FlashCycleErase,
+ FlashCycleReadSfdp,
+ FlashCycleReadJedecId,
+ FlashCycleWriteStatus,
+ FlashCycleReadStatus,
+ FlashCycleMax
+} FLASH_CYCLE_TYPE;
+
+///
+/// Flash Component Number
+///
+typedef enum {
+ FlashComponent0,
+ FlashComponent1,
+ FlashComponentMax
+} FLASH_COMPONENT_NUM;
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ PCH_SPI_PROTOCOL SpiProtocol;
+ UINT16 PchAcpiBase;
+ UINT64 PchSpiBase;
+ UINT8 ReadPermission;
+ UINT8 WritePermission;
+ UINT32 SfdpVscc0Value;
+ UINT32 SfdpVscc1Value;
+ UINT16 PchStrapBaseAddr;
+ UINT16 PchStrapSize;
+ UINT16 CpuStrapBaseAddr;
+ UINT16 CpuStrapSize;
+ UINT8 NumberOfComponents;
+ UINT32 Component1StartAddr;
+ UINT32 TotalFlashSize;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ Acquire pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Release pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Check if it's granted to do flash write.
+
+ @retval TRUE It's secure to do flash write.
+ @retval FALSE It's not secure to do flash write.
+**/
+BOOLEAN
+IsSpiFlashWriteGranted (
+ VOID
+ );
+
+/**
+ Check if a save and restore of the SPI controller state is necessary
+
+ @retval TRUE It's necessary to save and restore SPI controller state
+ @retval FALSE It's not necessary to save and restore SPI controller state
+**/
+BOOLEAN
+IsSpiControllerSaveRestoreEnabled (
+ VOID
+ );
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
new file mode 100644
index 0000000000..5cb4791142
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
@@ -0,0 +1,116 @@
+/** @file
+ Register names for PCH SPI device.
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -H denoted by "_PCH_H_" in component name.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SPI_REGS_H_
+#define _SPI_REGS_H_
+
+//
+// SPI Registers
+//
+#define R_SPI_CFG_BAR0 0x10
+#define B_SPI_CFG_BAR0_MASK 0x0FFF
+
+
+#define R_SPI_CFG_BC 0xDC
+#define S_SPI_CFG_BC 4
+#define N_SPI_CFG_BC_ASE_BWP 11
+#define B_SPI_CFG_BC_ASE_BWP BIT11
+#define N_SPI_CFG_BC_ASYNC_SS 10
+#define B_SPI_CFG_BC_ASYNC_SS BIT10
+#define N_SPI_CFG_BC_SYNC_SS 8
+#define B_SPI_CFG_BC_SYNC_SS BIT8
+#define B_SPI_CFG_BC_BILD BIT7
+#define B_SPI_CFG_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_SPI_CFG_BC_SRC (BIT3 | BIT2)
+#define N_SPI_CFG_BC_SRC 2
+#define V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No prefetching and no caching
+#define N_SPI_CFG_BC_BLE 1
+#define B_SPI_CFG_BC_WPD BIT0 ///< Write Protect Disable
+
+//
+// BIOS Flash Program Registers (based on SPI_BAR0)
+//
+#define R_SPI_MEM_HSFSC 0x04 ///< Hardware Sequencing Flash Status and Control Register(32bits)
+#define B_SPI_MEM_HSFSC_FDBC_MASK 0x3F000000 ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.
+#define N_SPI_MEM_HSFSC_FDBC 24
+#define B_SPI_MEM_HSFSC_CYCLE_MASK 0x001E0000 ///< Flash Cycle.
+#define N_SPI_MEM_HSFSC_CYCLE 17
+#define V_SPI_MEM_HSFSC_CYCLE_READ 0 ///< Flash Cycle Read
+#define V_SPI_MEM_HSFSC_CYCLE_WRITE 2 ///< Flash Cycle Write
+#define V_SPI_MEM_HSFSC_CYCLE_4K_ERASE 3 ///< Flash Cycle 4K Block Erase
+#define V_SPI_MEM_HSFSC_CYCLE_64K_ERASE 4 ///< Flash Cycle 64K Sector Erase
+#define V_SPI_MEM_HSFSC_CYCLE_READ_SFDP 5 ///< Flash Cycle Read SFDP
+#define V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID 6 ///< Flash Cycle Read JEDEC ID
+#define V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS 7 ///< Flash Cycle Write Status
+#define V_SPI_MEM_HSFSC_CYCLE_READ_STATUS 8 ///< Flash Cycle Read Status
+#define B_SPI_MEM_HSFSC_CYCLE_FGO BIT16 ///< Flash Cycle Go.
+#define B_SPI_MEM_HSFSC_FDV BIT14 ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_SPI_MEM_HSFSC_WRSDIS BIT11 ///< Write Status Disable
+#define B_SPI_MEM_HSFSC_SAF_CE BIT8 ///< SAF ctype error
+#define B_SPI_MEM_HSFSC_SAF_LE BIT6 ///< SAF link error
+#define B_SPI_MEM_HSFSC_SCIP BIT5 ///< SPI cycle in progress
+#define B_SPI_MEM_HSFSC_SAF_DLE BIT4 ///< SAF Data length error
+#define B_SPI_MEM_HSFSC_SAF_ERROR BIT3 ///< SAF Error
+#define B_SPI_MEM_HSFSC_AEL BIT2 ///< Access Error Log
+#define B_SPI_MEM_HSFSC_FCERR BIT1 ///< Flash Cycle Error
+#define B_SPI_MEM_HSFSC_FDONE BIT0 ///< Flash Cycle Done
+#define R_SPI_MEM_FADDR 0x08 ///< SPI Flash Address
+#define B_SPI_MEM_FADDR_MASK 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)
+#define R_SPI_MEM_FDATA00 0x10 ///< SPI Data 00 (32 bits)
+#define R_SPI_MEM_FRAP 0x50 ///< Flash Region Access Permissions Register
+#define B_SPI_MEM_FRAP_BRWA_MASK 0x0000FF00 ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define N_SPI_MEM_FRAP_BRWA 8 ///< BIOS Region Write Access bit position
+#define B_SPI_MEM_FRAP_BRRA_MASK 0x000000FF ///< BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define R_SPI_MEM_FREG0_FLASHD 0x54 ///< Flash Region 0(Flash Descriptor)(32bits)
+#define S_SPI_MEM_FREGX 4 ///< Size of Flash Region register
+#define B_SPI_MEM_FREGX_LIMIT_MASK 0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh
+#define N_SPI_MEM_FREGX_LIMIT 16 ///< Region limit bit position
+#define N_SPI_MEM_FREGX_LIMIT_REPR 12 ///< Region limit bit represents position
+#define B_SPI_MEM_FREGX_BASE_MASK 0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]
+#define N_SPI_MEM_FREGX_BASE 0 ///< Region base bit position
+#define N_SPI_MEM_FREGX_BASE_REPR 12 ///< Region base bit represents position
+#define R_SPI_MEM_FDOC 0xB4 ///< Flash Descriptor Observability Control Register(32 bits)
+#define B_SPI_MEM_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) ///< Flash Descritor Section Select
+#define V_SPI_MEM_FDOC_FDSS_FSDM 0x0000 ///< Flash Signature and Descriptor Map
+#define V_SPI_MEM_FDOC_FDSS_COMP 0x1000 ///< Component
+
+#define B_SPI_MEM_FDOC_FDSI_MASK 0x0FFC ///< Flash Descriptor Section Index
+#define R_SPI_MEM_FDOD 0xB8 ///< Flash Descriptor Observability Data Register(32 bits)
+#define R_SPI_MEM_SFDP0_VSCC0 0xC4 ///< Vendor Specific Component Capabilities Register(32 bits)
+
+#define B_SPI_MEM_SFDPX_VSCCX_EO_64K BIT29 ///< 64k Erase valid (EO_64k_valid)
+#define R_SPI_MEM_SFDP1_VSCC1 0xC8 ///< Vendor Specific Component Capabilities Register(32 bits)
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PchSpi.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PchSpi.c
new file mode 100644
index 0000000000..aaf4e1790f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PchSpi.c
@@ -0,0 +1,209 @@
+/** @file
+ PCH SPI PEI Library implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Ppi/Spi.h>
+#include <Library/SpiCommonLib.h>
+#include <PchReservedResources.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+typedef struct {
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ SPI_INSTANCE SpiInstance;
+} PEI_SPI_INSTANCE;
+
+/**
+ PCI Enumeratuion is not done till later in DXE
+ Initlialize SPI BAR0 to a default value till enumeration is done
+ also enable memory space decoding for SPI
+
+**/
+VOID
+InitSpiBar0 (
+ VOID
+ )
+{
+ UINT64 PchSpiBase;
+ PchSpiBase = SpiPciCfgBase ();
+ PciSegmentWrite32 (PchSpiBase + R_SPI_CFG_BAR0, PCH_SPI_BASE_ADDRESS);
+ PciSegmentOr32 (PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+}
+
+/**
+ This function Initial SPI services
+
+ @retval EFI_STATUS Results of the installation of the SPI services
+**/
+EFI_STATUS
+EFIAPI
+SpiServiceInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PEI_SPI_INSTANCE *PeiSpiInstance;
+ SPI_INSTANCE *SpiInstance;
+ PCH_SPI_PPI *SpiPpi;
+
+ Status = PeiServicesLocatePpi (
+ &gPchSpiPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SpiPpi
+ );
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "SpiServiceInit() Start\n"));
+
+ //
+ // PCI Enumeratuion is not done till later in DXE
+ // Initlialize SPI BAR0 to a default value till enumeration is done
+ // also enable memory space decoding for SPI
+ //
+ InitSpiBar0 ();
+
+ PeiSpiInstance = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_SPI_INSTANCE));
+ if (NULL == PeiSpiInstance) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SpiInstance = &(PeiSpiInstance->SpiInstance);
+ SpiProtocolConstructor (SpiInstance);
+
+ PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PeiSpiInstance->PpiDescriptor.Guid = &gPchSpiPpiGuid;
+ PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol);
+
+ ///
+ /// Install the SPI PPI
+ ///
+ DEBUG ((DEBUG_INFO, "SPI PPI Installed\n"));
+ Status = PeiServicesInstallPpi (&PeiSpiInstance->PpiDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "SpiServiceInit() End\n"));
+ }
+ else {
+ DEBUG ((DEBUG_INFO, "SPI PPI already installed\n"));
+ }
+ return Status;
+}
+
+/**
+ Acquire pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ return PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+}
+
+/**
+ Release pch spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ ///
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ PciSegmentOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ B_SPI_CFG_BC_WPD
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ ///
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ PciSegmentAnd8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) (~B_SPI_CFG_BC_WPD)
+ );
+}
+
+/**
+ Check if it's granted to do flash write.
+
+ @retval TRUE It's secure to do flash write.
+ @retval FALSE It's not secure to do flash write.
+**/
+BOOLEAN
+IsSpiFlashWriteGranted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Check if a save and restore of the SPI controller state is necessary
+
+ @retval TRUE It's necessary to save and restore SPI controller state
+ @retval FALSE It's not necessary to save and restore SPI controller state
+**/
+BOOLEAN
+IsSpiControllerSaveRestoreEnabled (
+ VOID
+ )
+{
+ return FALSE;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PeiSpiLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PeiSpiLib.inf
new file mode 100644
index 0000000000..c3bf6d02a1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Library/PeiSpiLib/PeiSpiLib.inf
@@ -0,0 +1,41 @@
+## @file
+# Component description file for PCH Reset Lib Pei Phase
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiSpiLib
+FILE_GUID = 4998447D-7948-448F-AB75-96E24E18FF23
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = SpiLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+DebugLib
+PeiServicesLib
+PeiServicesTablePointerLib
+MemoryAllocationLib
+PciSegmentLib
+SpiCommonLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchSpi.c
+
+
+[Ppis]
+gPchSpiPpiGuid ## PRODUCES
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
new file mode 100644
index 0000000000..25ab91940c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
@@ -0,0 +1,29 @@
+## @file
+# Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseSpiCommonLib
+ FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpiCommonLib
+
+[Sources]
+ SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ AlderlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PmcLib
+ PchPciBdfLib
+
+[Pcd]
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..ab51521f14
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1127 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PmcLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/Spi.h>
+#include <Library/SpiCommonLib.h>
+#include <Register/PchRegs.h>
+#include <Register/SpiRegs.h>
+#include <Register/FlashRegs.h>
+#include <Register/PmcRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+#define DEFAULT_CPU_STRAP_BASE_OFFSET 0x300 // Default CPU Straps base offset
+#define B_SPI_MEM_HSFSC_SAVE_MASK (B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK)
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 Data32;
+ UINT16 Mdtba;
+ EFI_STATUS Status;
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION;
+ SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead;
+ SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite;
+ SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase;
+ SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp;
+ SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+ SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+ SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus;
+ SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+ SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+ SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+ SpiInstance->PchSpiBase = SpiPciCfgBase ();
+
+ SpiInstance->PchAcpiBase = PmcGetAcpiBase ();
+ ASSERT (SpiInstance->PchAcpiBase != 0);
+
+ PchSpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+ if (PchSpiBar0 == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV) == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Get Region 0 - 7 read Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + R_SPI_MEM_FRAP) & B_SPI_MEM_FRAP_BRRA_MASK;
+ DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance->ReadPermission));
+ //
+ // Get Region 0 - 7 write Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FRAP) &
+ B_SPI_MEM_FRAP_BRWA_MASK) >> N_SPI_MEM_FRAP_BRWA);
+ DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance->WritePermission));
+
+ SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0);
+ DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc0Value));
+ SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP1_VSCC1);
+ DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc1Value));
+
+ //
+ // Select to Flash Map 0 Register to get the number of flash Component
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_FDOC,
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP0)
+ );
+
+ //
+ // Copy Zero based Number Of Components
+ //
+ SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FDOD) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);
+ DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfComponents + 1));
+
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_FDOC,
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_COMP | R_FLASH_FCBA_FLCOMP)
+ );
+
+ //
+ // Copy Component 0 Density
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ if (SpiInstance->NumberOfComponents > 0) {
+ SpiInstance->Component1StartAddr = V_FLASH_FLCOMP_COMP_512KB <<
+ (Data32 & B_FLASH_FLCOMP_COMP0_MASK);
+ DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+ SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+ (V_FLASH_FLCOMP_COMP_512KB <<
+ ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >>
+ N_FLASH_FLCOMP_COMP1));
+ } else {
+ SpiInstance->TotalFlashSize = V_FLASH_FLCOMP_COMP_512KB <<
+ (Data32 & B_FLASH_FLCOMP_COMP0_MASK);
+ }
+ DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+
+ //
+ // Select FLASH_MAP1 to get Flash PCH Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_SPI_MEM_FDOC),
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP1)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & B_FLASH_FDBAR_FPSBA)
+ >> N_FLASH_FDBAR_FPSBA)
+ << N_FLASH_FDBAR_FPSBA_REPR);
+ DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBaseAddr));
+ ASSERT (SpiInstance->PchStrapBaseAddr != 0);
+ //
+ // PCH Strap Length, [31:24] represents number of Dwords
+ //
+ SpiInstance->PchStrapSize = (UINT16) (((Data32 & B_FLASH_FDBAR_PCHSL)
+ >> N_FLASH_FDBAR_PCHSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));
+
+ //
+ // Select FLASH_MAP2 to get Flash CPU Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_SPI_MEM_FDOC),
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP2)
+ );
+ //
+ // Align FPSBA with address bits for the CPU Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ //
+ // CPU Strap Length, [23:16] represents number of Dwords
+ //
+ SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_FLASH_FDBAR_CPUSL)
+ >> N_FLASH_FDBAR_CPUSL)
+ * sizeof (UINT32));
+
+ //
+ // CPU Strap Address [11:2] represent offset from MDTBA
+ //
+ SpiInstance->CpuStrapBaseAddr = (UINT16) ((Data32 & B_FLASH_FDBAR_FCPUSBA) >> N_FLASH_FDBAR_FCPUSBA);
+ ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+
+ //
+ // If CPU Strap base address is different than 0x300 need to add MDTBA value for final location
+ //
+ if (SpiInstance->CpuStrapBaseAddr != DEFAULT_CPU_STRAP_BASE_OFFSET) {
+ Status = SpiProtocolFlashRead (&(SpiInstance->SpiProtocol), FlashRegionAll, R_FLASH_UMAP1, sizeof (Data32), (UINT8 *) (&Data32));
+ ASSERT_EFI_ERROR (Status);
+ Mdtba = (UINT16)(((Data32 & B_FLASH_UMAP1_MDTBA) >> N_FLASH_UMAP1_MDTBA) << N_FLASH_UMAP1_MDTBA_REPR);
+ DEBUG ((DEBUG_INFO, "Mdtba : %0x\n", Mdtba));
+ // Add MDTBA offset for final address of CPU Straps
+ SpiInstance->CpuStrapBaseAddr += Mdtba;
+ }
+
+ DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+ DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delay for at least the request number of microseconds for Runtime usage.
+
+ @param[in] ABase Acpi base address
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+ IN UINT16 ABase,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ OriginalTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACPI_IO_PM1_TMR_TMR_VAL;
+ CurrentTick = OriginalTick;
+
+ //
+ // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
+ //
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ //
+ // The loops needed by timer overflow
+ //
+ Counts = Ticks / V_ACPI_IO_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_ACPI_IO_PM1_TMR_MAX_VAL;
+
+ //
+ // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+ // one I/O operation, and maybe generate SMI
+ //
+ while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+ CurrentTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACPI_IO_PM1_TMR_TMR_VAL;
+ //
+ // Check if timer overflow
+ //
+ if ((CurrentTick < OriginalTick)) {
+ if (Counts != 0) {
+ Counts--;
+ } else {
+ //
+ // If timer overflow and Counts equ to 0, that means we already stalled more than
+ // RemainingTick, break the loop here
+ //
+ break;
+ }
+ }
+
+ OriginalTick = CurrentTick;
+ }
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+STATIC
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = SPI_WAIT_TIME / SPI_WAIT_PERIOD;
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ if ((Data32 & B_SPI_MEM_HSFSC_SCIP) == 0) {
+ MmioWrite8 (PchSpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FCERR | B_SPI_MEM_HSFSC_FDONE);
+ if (((Data32 & B_SPI_MEM_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD);
+ }
+ return FALSE;
+}
+
+/**
+ This function waits for a pending SPI transaction to complete without clearing
+ status fields
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] PchSpiBar0 SPI MMIO address
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+STATIC
+WaitForScipNoClear (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ SPI_INSTANCE *SpiInstance;
+ UINT32 Data32;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ WaitCount = SPI_WAIT_TIME / SPI_WAIT_PERIOD;
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ if ((Data32 & B_SPI_MEM_HSFSC_SCIP) == 0) {
+ return TRUE;
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD);
+ }
+ return FALSE;
+}
+
+/**
+ This function sets the FDONE and optionally FCERR bits in the HSFS_CTL register
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] PchSpiBar0 SPI MMIO address
+ @param[in] SetErrorBit Set to TRUE to set the FCERR bit
+
+**/
+VOID
+STATIC
+SetHsfscFdone (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN SetFcErrorBit
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 Index;
+ UINT8 DataCount;
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionBios, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Clear FDONE and FCERR
+ //
+ MmioWrite8 (PchSpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FCERR | B_SPI_MEM_HSFSC_FDONE);
+
+ //
+ // Fill data buffer
+ //
+ if (SetFcErrorBit) {
+ for (Index = 0; Index < 64; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, 0xFFFFFFFF);
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_SPI_MEM_FADDR),
+ (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK)
+ );
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ if (SetFcErrorBit) {
+ DataCount = 0x3F;
+ } else {
+ DataCount = 0;
+ }
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK)),
+ (UINT32) (((DataCount << N_SPI_MEM_HSFSC_FDBC) & B_SPI_MEM_HSFSC_FDBC_MASK) |
+ (V_SPI_MEM_HSFSC_CYCLE_READ << N_SPI_MEM_HSFSC_CYCLE) |
+ B_SPI_MEM_HSFSC_CYCLE_FGO)
+ );
+
+ if (SetFcErrorBit) {
+ //
+ // Intentionally write to FDATA while a cycle is in progress to generate an error
+ //
+ for (Index = 0; Index < 64; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, 0x0);
+ }
+ }
+
+ WaitForScipNoClear (This, PchSpiBar0);
+}
+
+/**
+ This function sends the programmed SPI command to the device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized or blocked command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+STATIC
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ )
+{
+ UINT32 FdataSave[16];
+ EFI_STATUS Status;
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINT64 SpiBaseAddress;
+ UINTN PchSpiBar0;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 SpiDataCount;
+ UINT32 FlashCycle;
+ UINT8 BiosCtlSave;
+ UINT32 SmiEnSave;
+ UINT16 ABase;
+ UINT32 HsfstsCtl;
+ UINT32 FaddrSave;
+ UINT32 HsfscSave;
+ BOOLEAN HsfscFdoneSave;
+ BOOLEAN HsfscFcerrSave;
+ BOOLEAN RestoreState;
+
+ //
+ // For flash write, there is a requirement that all CPU threads are in SMM
+ // before the flash protection is disabled.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {
+ if (!IsSpiFlashWriteGranted ()) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ Status = EFI_SUCCESS;
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ ABase = SpiInstance->PchAcpiBase;
+ RestoreState = FALSE;
+
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+ // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ // synchronization methods must be applied here or in the consumer of the
+ // SendSpiCmd. An example method is disabling the specific SMI sources
+ // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+ // sources after the flash cycle .
+ //
+ SmiEnSave = IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN));
+ IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave & (UINT32) (~B_ACPI_IO_SMI_EN_GBL_SMI));
+ BiosCtlSave = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_SRC;
+
+ //
+ // Acquire SPI BAR0
+ //
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+
+ //
+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ Status = DisableBiosWriteProtect ();
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ PciSegmentAndThenOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) (~B_SPI_CFG_BC_SRC),
+ (UINT8) (V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS << N_SPI_CFG_BC_SRC)
+ );
+ }
+
+ //
+ // Save current SPI controller state
+ //
+ if (IsSpiControllerSaveRestoreEnabled ()) {
+ if (!WaitForScipNoClear (This, PchSpiBar0)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ HsfscSave = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ HsfscFdoneSave = ((HsfscSave & B_SPI_MEM_HSFSC_FDONE) != 0) ? TRUE : FALSE;
+ HsfscFcerrSave = ((HsfscSave & B_SPI_MEM_HSFSC_FCERR) != 0) ? TRUE : FALSE;
+ HsfscSave &= B_SPI_MEM_HSFSC_SAVE_MASK;
+ FaddrSave = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FADDR);
+ for (Index = 0; Index < 64; Index += sizeof (UINT32)) {
+ FdataSave[Index >> 2] = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index);
+ }
+ RestoreState = TRUE;
+ }
+
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check if Write Status isn't disabled in HW Sequencing
+ //
+ if (FlashCycleType == FlashCycleWriteStatus) {
+ HsfstsCtl = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ if ((HsfstsCtl & B_SPI_MEM_HSFSC_WRSDIS) != 0) {
+ Status = EFI_ACCESS_DENIED;
+ goto SendSpiCmdEnd;
+ }
+ }
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ HardwareSpiAddr += Address;
+ if ((Address + ByteCount) > FlashRegionSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check for PCH SPI hardware sequencing required commands
+ //
+ FlashCycle = 0;
+ switch (FlashCycleType) {
+ case FlashCycleRead:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleWrite:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleErase:
+ if (((ByteCount % SIZE_4KB) != 0) ||
+ ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+ break;
+ case FlashCycleReadSfdp:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_SFDP << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadJedecId:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleWriteStatus:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadStatus:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_STATUS << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ default:
+ //
+ // Unrecognized Operation
+ //
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ break;
+ }
+
+ do {
+ SpiDataCount = ByteCount;
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleReadSfdp)) {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write at most 64 bytes
+ // per operation
+ //
+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes during each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ }
+ if (FlashCycleType == FlashCycleErase) {
+ if (((ByteCount / SIZE_64KB) != 0) &&
+ ((ByteCount % SIZE_64KB) == 0) &&
+ ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+ if ((SpiInstance->NumberOfComponents == 0) ||
+ (HardwareSpiAddr < SpiInstance->Component1StartAddr)) {
+ //
+ // Check whether Component0 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc0Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ } else {
+ //
+ // Check whether Component1 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc1Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ }
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ if (SpiDataCount == SIZE_4KB) {
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_4K_ERASE << N_SPI_MEM_HSFSC_CYCLE);
+ } else {
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_64K_ERASE << N_SPI_MEM_HSFSC_CYCLE);
+ }
+ }
+ //
+ // If it's write cycle, load data into the SPI data buffer.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, Buffer[Index]);
+ }
+ } else {
+ //
+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+ }
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_SPI_MEM_FADDR),
+ (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK)
+ );
+
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK)),
+ (UINT32) ((((SpiDataCount - 1) << N_SPI_MEM_HSFSC_FDBC) & B_SPI_MEM_HSFSC_FDBC_MASK) | FlashCycle | B_SPI_MEM_HSFSC_CYCLE_FGO)
+ );
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ //
+ // If it's read cycle, load data into the call's buffer.
+ //
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleReadSfdp) ||
+ (FlashCycleType == FlashCycleReadJedecId) ||
+ (FlashCycleType == FlashCycleReadStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index);
+ }
+ } else {
+ //
+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index);
+ }
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ ByteCount -= SpiDataCount;
+ } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+ //
+ // Restore SPI controller state
+ //
+ if (RestoreState) {
+ if (HsfscFdoneSave) {
+ SetHsfscFdone (This, PchSpiBar0, HsfscFcerrSave);
+ }
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ (UINT32) ~(B_SPI_MEM_HSFSC_SAVE_MASK |
+ B_SPI_MEM_HSFSC_SAF_CE | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_SAF_LE | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_SAF_DLE | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_SAF_ERROR | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_AEL | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_FCERR | // This bit clears when set to 1, ensure 0 is written
+ B_SPI_MEM_HSFSC_FDONE), // This bit clears when set to 1, ensure 0 is written
+ HsfscSave
+ );
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FADDR, FaddrSave);
+ for (Index = 0; Index < 64; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, FdataSave[Index >> 2]);
+ }
+ }
+
+ //
+ // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ EnableBiosWriteProtect ();
+ PciSegmentAndThenOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) ~B_SPI_CFG_BC_SRC,
+ BiosCtlSave
+ );
+ }
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // Restore SMIs.
+ //
+ IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave);
+
+ return Status;
+}
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleRead,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleWrite,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleErase,
+ Address,
+ ByteCount,
+ NULL
+ );
+ return Status;
+}
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ *BaseAddress = 0;
+ *RegionSize = SpiInstance->TotalFlashSize;
+ return EFI_SUCCESS;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_SPI_MEM_FREG0_FLASHD + (S_SPI_MEM_FREGX * ((UINT32) FlashRegionType))));
+
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_SPI_MEM_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_SPI_MEM_FREGX_BASE_MASK) >> N_SPI_MEM_FREGX_BASE) <<
+ N_SPI_MEM_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_SPI_MEM_FREGX_LIMIT_MASK) >> N_SPI_MEM_FREGX_LIMIT) + 1) <<
+ N_SPI_MEM_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
new file mode 100644
index 0000000000..2dd80eba7c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
@@ -0,0 +1,387 @@
+/** @file
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SmmCpu.h>
+#include <Library/SpiCommonLib.h>
+#include <PchReservedResources.h>
+#include <Library/PchPciBdfLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/SpiRegs.h>
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assigned to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+//
+// mPchSpiSavedMmioAddr keeps the MMIO range assigned to SPI by PCI enumeration.
+// In SMM this is used to restore the original value for SPI BAR0 after finishing
+// commands to the SPI controller.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiSavedMmioAddr;
+//
+// mPchSpiBar0RefCount stores the reference count for SPI BAR0.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchSpiBar0RefCount;
+//
+// mPchSpiSavedPciCmdReg stores the PCI command register state at the start of the
+// SPI transaction. This is used to restore the original PCI command register
+// state after finishing commands to the SPI controller.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchSpiSavedPciCmdReg;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mBootServiceExited;
+
+/**
+ This function is invoked at ExitBootServices()
+
+ @param[in] Protocol Protocol unique ID.
+ @param[in] Interface Interface instance.
+ @param[in] Handle The handle on which the interface is installed..
+
+ @retval Status.
+**/
+EFI_STATUS
+EFIAPI
+SpiExitBootServicesCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mBootServiceExited = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ <b>SPI Runtime SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in System Management Mode Core Interface Specification .
+
+ - @result
+ The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @endlink with GUID
+ gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+ - <b>Integration Check List</b>\n
+ - This driver supports Descriptor Mode only.
+ - This driver supports Hardware Sequence only.
+ - When using SMM SPI Protocol to perform flash access in an SMI handler,
+ and the SMI occurrence is asynchronous to normal mode code execution,
+ proper synchronization mechanism must be applied, e.g. disable SMI before
+ the normal mode SendSpiCmd() starts and re-enable SMI after
+ the normal mode SendSpiCmd() completes.
+ @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+ SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+ not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+ So the synchronization at caller level is likely needed.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+ mSpiSavedMmioAddr = 0;
+ mPchSpiBar0RefCount = 0;
+ mPchSpiSavedPciCmdReg = 0;
+ mBootServiceExited = FALSE;
+
+ ///
+ /// Allocate pool for SPI protocol instance
+ ///
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, /// MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Register ExitBootServices callback
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmExitBootServicesProtocolGuid,
+ SpiExitBootServicesCallback,
+ &Registration
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install the SMM PCH_SPI_PROTOCOL interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gPchSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire PCH SPI MMIO address.
+ It is not expected for this BAR0 to change because the SPI device is usually
+ hidden from the OS. But if it is ever different from the preallocated address,
+ reassign it back. In SMM, BAR0 will always be overwritten and the reserved
+ MMIO range for SPI will be returned.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINT32 SpiBar0;
+ UINT8 PciCmdReg;
+
+ //
+ // Save original SPI physical MMIO address
+ //
+ SpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+ PciCmdReg = PciSegmentRead8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET);
+
+ if ((SpiBar0 != mSpiResvMmioAddr) || ((PciCmdReg & EFI_PCI_COMMAND_MEMORY_SPACE) == 0)) {
+ //
+ // Save PCI command register state and BAR value assigned by PCI enumeration
+ //
+ mPchSpiSavedPciCmdReg = PciCmdReg;
+ mSpiSavedMmioAddr = SpiBar0;
+
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0, mSpiResvMmioAddr);
+ PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ } else if (mPchSpiBar0RefCount == 0) {
+ mSpiSavedMmioAddr = 0;
+ mPchSpiSavedPciCmdReg = 0;
+ }
+ mPchSpiBar0RefCount++;
+
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+/**
+ Release PCH SPI MMIO address. If AcquireSpiBar0() previously overwrote the
+ value of BAR0, this function will restore the original value assigned by PCI
+ enumeration
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ //
+ // Reference counting is used here because multiple nested calls to
+ // AcquireSpiBar0()/ReleaseSpiBar0() will cause SpiBar0 to be reprogrammed
+ // back to the original value before access to the SPI controller is done.
+ // Reference counting ensures that the BAR is not restored until after access
+ // is complete.
+ //
+ if (mPchSpiBar0RefCount <= 1) {
+ mPchSpiBar0RefCount = 0;
+ if (mSpiSavedMmioAddr != 0) {
+ //
+ // Temporary disable MSE, restore the original SPI MMIO address, then
+ // restore PCI command register state
+ //
+ PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8)~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0, mSpiSavedMmioAddr);
+ PciSegmentWrite8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, mPchSpiSavedPciCmdReg);
+
+ //
+ // Clear saved state
+ //
+ mSpiSavedMmioAddr = 0;
+ mPchSpiSavedPciCmdReg = 0;
+ }
+ } else {
+ mPchSpiBar0RefCount--;
+ }
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
+ //
+ PciSegmentOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC + 1,
+ (B_SPI_CFG_BC_SYNC_SS >> 8)
+ );
+ ///
+ /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ PciSegmentOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ B_SPI_CFG_BC_WPD
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ ///
+ /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ PciSegmentAnd8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) (~B_SPI_CFG_BC_WPD)
+ );
+
+}
+
+/**
+ Check if it's granted to do flash write.
+
+ @retval TRUE It's secure to do flash write.
+ @retval FALSE It's not secure to do flash write.
+**/
+BOOLEAN
+IsSpiFlashWriteGranted (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CpuIndex;
+ UINT64 ProcessorId;
+
+ if (mSmmCpuProtocol == NULL) {
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+ ASSERT_EFI_ERROR (Status);
+ if (mSmmCpuProtocol == NULL) {
+ return TRUE;
+ }
+ }
+
+ for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+ Status = mSmmCpuProtocol->ReadSaveState (
+ mSmmCpuProtocol,
+ sizeof (ProcessorId),
+ EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID,
+ CpuIndex,
+ &ProcessorId
+ );
+ //
+ // If the processor is in SMM at the time the SMI occurred,
+ // it will return success. Otherwise, EFI_NOT_FOUND is returned.
+ //
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Check if a save and restore of the SPI controller state is necessary
+
+ @retval TRUE It's necessary to save and restore SPI controller state
+ @retval FALSE It's not necessary to save and restore SPI controller state
+**/
+BOOLEAN
+IsSpiControllerSaveRestoreEnabled (
+ VOID
+ )
+{
+ return mBootServiceExited;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
new file mode 100644
index 0000000000..78913423fb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SpiSmm
+FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InstallPchSpi
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+UefiDriverEntryPoint
+UefiBootServicesTableLib
+BaseLib
+SmmServicesTableLib
+SpiCommonLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+Spi.c
+
+
+[Protocols]
+gPchSmmSpiProtocolGuid ## PRODUCES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEdkiiSmmExitBootServicesProtocolGuid ## CONSUMES
+
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gEfiSmmCpuProtocolGuid
--
2.36.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108666): https://edk2.groups.io/g/devel/message/108666
Mute This Topic: https://groups.io/mt/101347730/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2023-09-15 3:04 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-13 22:13 [edk2-devel] [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components Saloni Kasbekar
2023-09-13 22:13 ` [edk2-devel] [PATCH 02/10] AlderlakeSiliconPkg/IpBlock: Add Graphics, HostBridge, PcieRp components Saloni Kasbekar
2023-09-14 17:23 ` Chaganty, Rangasai V
2023-09-15 3:02 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 03/10] AlderlakeSiliconPkg/IpBlock: Add P2sb, PchDmi components Saloni Kasbekar
2023-09-14 17:41 ` Chaganty, Rangasai V
2023-09-15 3:02 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 04/10] AlderlakeSiliconPkg/IpBlock: Add Pmc, Spi components Saloni Kasbekar
2023-09-14 21:40 ` Chaganty, Rangasai V
2023-09-15 3:04 ` Chuang, Rosen [this message]
2023-09-13 22:13 ` [edk2-devel] [PATCH 05/10] AlderlakeSiliconPkg/Include: Add ConfigBlock headers Saloni Kasbekar
2023-09-14 21:45 ` Chaganty, Rangasai V
2023-09-15 3:05 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 06/10] AlderlakeSiliconPkg/Include: Add Library, Pins, Ppi Includes Saloni Kasbekar
2023-09-14 22:01 ` Chaganty, Rangasai V
2023-09-15 3:06 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 07/10] AlderlakeSiliconPkg/Include: Add Protocol, Register, Other Includes Saloni Kasbekar
2023-09-14 22:02 ` Chaganty, Rangasai V
2023-09-15 3:06 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 08/10] AlderlakeSiliconPkg/Fru: Add AdlCpu Fru Saloni Kasbekar
2023-09-15 3:07 ` Chuang, Rosen
2023-09-13 22:14 ` [edk2-devel] [PATCH 09/10] AlderlakeSiliconPkg: Add AdlPch Fru and IncludePrivate modules Saloni Kasbekar
2023-09-14 22:20 ` Chaganty, Rangasai V
2023-09-15 3:08 ` Chuang, Rosen
2023-09-13 22:14 ` [edk2-devel] [PATCH 10/10] AlderlakeSiliconPkg: Add Alderlake Product and SiPkg.dec Saloni Kasbekar
2023-09-14 22:23 ` Chaganty, Rangasai V
2023-09-15 3:10 ` Chuang, Rosen
2023-09-14 16:02 ` [edk2-devel] [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components Chaganty, Rangasai V
2023-09-15 2:59 ` Chuang, Rosen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM8PR11MB562470F531B68BC127AC6FEE92F6A@DM8PR11MB5624.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox