public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Heng Luo" <heng.luo@intel.com>
To: devel@edk2.groups.io
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component
Date: Fri,  5 Feb 2021 15:40:34 +0800	[thread overview]
Message-ID: <20210205074045.3916-29-heng.luo@intel.com> (raw)
In-Reply-To: <20210205074045.3916-1-heng.luo@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171

Adds the following files:
  * 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>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h                                 |   40 ++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h                                        |  364 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h                                            |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf                      |   33 ++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c                                 |  477 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf                         |   31 +++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c                                  | 1115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf |   40 ++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c            |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c                                                                    |  296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf                                                               |   47 +++++++++++++++++++++++++++++++++++++
 11 files changed, 2712 insertions(+)

diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h
new file mode 100644
index 0000000000..6da88a9047
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h
@@ -0,0 +1,40 @@
+/** @file
+  SPI library header for abstraction of SPI HW registers accesses
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SPI_ACCESS_PRIVATE_LIB_H_
+#define _SPI_ACCESS_PRIVATE_LIB_H_
+
+/**
+  Disable EISS (Enable InSMM.STS)
+**/
+VOID
+SpiDisableEiss (
+  VOID
+  );
+
+/**
+  Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting.
+
+  @param[in] BiosLockEnable     Policy for BiosLockEnable bit programming
+  @param[in] BiosInterfaceLock  Policy for BiosInterfaceLock bit programming
+
+**/
+VOID
+SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (
+  IN BOOLEAN  BiosLockEnable,
+  IN BOOLEAN  BiosInterfaceLock
+  );
+
+/**
+  Clears BIOS Write Protect Disable bit
+**/
+VOID
+SpiClearBiosWriteProtectDisable (
+  VOID
+  );
+
+#endif // _SPI_ACCESS_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
new file mode 100644
index 0000000000..3290f77122
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
@@ -0,0 +1,364 @@
+/** @file
+  Header file for the PCH SPI Common Driver.
+
+  Copyright (c) 2021, 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
+  );
+
+/**
+  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/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
new file mode 100644
index 0000000000..8e2029500c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
@@ -0,0 +1,136 @@
+/** @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 -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) 2021, 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_BDE                       0xD8
+
+#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_BBS                    BIT6            ///< Boot BIOS strap
+#define N_SPI_CFG_BC_BBS                    6
+#define V_SPI_CFG_BC_BBS_SPI                0               ///< Boot BIOS strapped to SPI
+#define B_SPI_CFG_BC_EISS                   BIT5            ///< Enable InSMM.STS
+#define B_SPI_CFG_BC_TSS                    BIT4
+#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 B_SPI_CFG_BC_LE                     BIT1            ///< Lock Enable
+#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_FLOCKDN             BIT15                         ///< Flash Configuration Lock-Down
+#define B_SPI_MEM_HSFSC_FDV                 BIT14                         ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_SPI_MEM_HSFSC_FDOPSS              BIT13                         ///< Flash Descriptor Override Pin-Strap Status
+#define B_SPI_MEM_HSFSC_WRSDIS              BIT11                         ///< Write Status Disable
+#define B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE     BIT7                          ///< Indicates flash is attached either directly to the PCH via the SPI bus or EC/BMC
+#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_DLOCK                     0x0C                          ///< Discrete Lock Bits
+#define B_SPI_MEM_DLOCK_PR0LOCKDN           BIT8                          ///< PR0LOCKDN
+#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 B_SPI_MEM_FRAP_BMRAG_MASK           0x00FF0000                    ///< BIOS Master Read Access Grant
+#define B_SPI_MEM_FRAP_BMWAG_MASK           0xFF000000                    ///< BIOS Master Write Access Grant
+#define R_SPI_MEM_FREG0_FLASHD              0x54                          ///< Flash Region 0(Flash Descriptor)(32bits)
+#define R_SPI_MEM_FREG3_GBE                 0x60                          ///< Flash Region 3(GbE)(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_PR0                       0x84                          ///< Protected Region 0 Register
+#define S_SPI_MEM_PRX                       4                             ///< Protected Region X Register size
+#define B_SPI_MEM_PRX_WPE                   BIT31                         ///< Write Protection Enable
+#define B_SPI_MEM_PRX_PRL_MASK              0x7FFF0000                    ///< Protected Range Limit Mask, [30:16] here represents upper limit of address [26:12]
+#define N_SPI_MEM_PRX_PRL                   16                            ///< Protected Range Limit bit position
+#define B_SPI_MEM_PRX_RPE                   BIT15                         ///< Read Protection Enable
+#define B_SPI_MEM_PRX_PRB_MASK              0x00007FFF                    ///< Protected Range Base Mask, [14:0] here represents base limit of address [26:12]
+#define N_SPI_MEM_PRX_PRB                   0                             ///< Protected Range Base bit 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 V_SPI_MEM_FDOC_FDSS_MSTR            0x3000                        ///< Master
+#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_CPPTV         BIT31                         ///< Component Property Parameter Table Valid
+#define B_SPI_MEM_SFDP0_VSCC0_VCL           BIT30                         ///< Vendor Component Lock
+#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/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf
new file mode 100644
index 0000000000..bba0b1fef3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Component description file for PCH SPI access library
+#
+#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION     = 0x00010017
+BASE_NAME       = PeiDxeSmmSpiAccessLib
+FILE_GUID       = A6D4C05A-F6CB-46D5-4BA1-8C47B139DCA6
+VERSION_STRING  = 1.0
+MODULE_TYPE     = BASE
+LIBRARY_CLASS   = SpiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchPciBdfLib
+PchPcrLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SpiAccessLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c
new file mode 100644
index 0000000000..c91b9aaf4d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c
@@ -0,0 +1,477 @@
+/** @file
+  SPI library for abstraction of SPI HW registers accesses
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/SpiAccessLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PchPcrLib.h>
+#include <Register/SpiRegs.h>
+#include <Register/FlashRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchDmiRegs.h>
+
+/**
+  Checks if PCH SPI Controler is present and available
+
+  @retval TRUE    PCH SPI controller is avaialable
+  @retval FALSE   PCH SPI controller is not available
+**/
+BOOLEAN
+SpiIsControllerAvailable (
+  VOID
+  )
+{
+  //
+  // Checks for SPI controller
+  //
+  return (PciSegmentRead16 (SpiPciCfgBase () + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+}
+
+/**
+  Returns PCH SPI BAR0 value
+
+  @retval  UINT32  PCH SPI BAR0 value
+**/
+UINT32
+SpiGetBar0 (
+  VOID
+  )
+{
+  UINT32  SpiBar0;
+
+  ASSERT (SpiIsControllerAvailable ());
+  SpiBar0 = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BAR0) & ~B_SPI_CFG_BAR0_MASK;
+  ASSERT (SpiBar0 != 0);
+
+  return SpiBar0;
+}
+
+/**
+  Reads given descriptor section and returns value
+
+  @param[in] UINT16   Descriptor section
+  @param[in] UINT16   Offset
+
+  @retval UINT32      Read value from a section under given offset
+**/
+STATIC
+UINT32
+SpiReadDescriptor (
+  IN  UINT16  DescriptorSection,
+  IN  UINT16  Offset
+  )
+{
+  UINT32  SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  MmioWrite32 (SpiBar0 + R_SPI_MEM_FDOC, (DescriptorSection | Offset));
+  return MmioRead32 (SpiBar0 + R_SPI_MEM_FDOD);
+}
+
+/**
+  Returns descriptor signature
+
+  @retval UINT32    Descriptor signature
+**/
+UINT32
+SpiGetDescriptorSignature (
+  VOID
+  )
+{
+  //
+  // Read Descriptor offset 0x10 - To get Descriptor Signature
+  // Signature section 0x0000 + offset 0x0 which points to Descriptor offset 0x10
+  //
+  return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, 0x0);
+}
+
+/**
+  Returns supported features and R/W frequencies of Flash Component
+
+  @retval UINT32    Flash Component features descriptor
+**/
+UINT32
+SpiGetFlashComponentDescription (
+  VOID
+  )
+{
+  //
+  // Read Descriptor offset 0x30 - To get supported features and R/W frequencies
+  // Component section 0x1000 + offset 0x0 which points to Descriptor offset 0x30
+  //
+  return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_COMP, 0x0);
+}
+
+/**
+  Returns number of Flash Components
+
+  @retval UINT32    Flash components number
+**/
+UINT32
+SpiGetFlashComponentsNumber (
+  VOID
+  )
+{
+  //
+  // Read Descriptor offset 0x14 - To get number of components
+  // Signature section 0x0000 + offset 0x4 which points to Descriptor offset 0x14
+  //
+  return ((SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_FDBAR_FLASH_MAP0) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);
+}
+
+/**
+  Returns total Flash size with regards to number of flash components
+
+  @retval UINT32    Total Flash Memory size
+**/
+UINT32
+SpiGetTotalFlashSize (
+  VOID
+  )
+{
+  UINT32  Data32;
+  UINT32  ComponentsNumber;
+  UINT32  TotalFlashSize;
+
+  Data32 = SpiGetFlashComponentDescription ();
+  ComponentsNumber = SpiGetFlashComponentsNumber ();
+
+  TotalFlashSize = (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) (Data32 & B_FLASH_FLCOMP_COMP0_MASK)));
+  if (ComponentsNumber == 1) {
+    TotalFlashSize += (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >> 4)));
+  }
+
+  return TotalFlashSize;
+}
+
+/**
+  Checks BIOS lock bits for proper value and checks if write protection is enabled
+  Expected vales are: LE bit set, EISS bit set and WPD bit cleared
+
+  @retval  TRUE    All protection bits are set correctly
+  @retval  FALSE   Not all protection bits had exepcted values
+**/
+BOOLEAN
+SpiIsWriteProtectionEnabled (
+  VOID
+  )
+{
+  UINT32  BiosControl;
+  BiosControl = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC);
+
+  DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL LE: %x\n", (BiosControl & B_SPI_CFG_BC_LE) != 0 ));
+  DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL WPD: %x\n", (BiosControl & B_SPI_CFG_BC_WPD) != 0 ));
+  DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL EISS: %x\n", (BiosControl & B_SPI_CFG_BC_EISS) != 0 ));
+
+  return (((BiosControl & B_SPI_CFG_BC_LE) != 0) &&
+          ((BiosControl & B_SPI_CFG_BC_WPD) == 0) &&
+          ((BiosControl & B_SPI_CFG_BC_EISS) != 0));
+}
+
+/**
+  Returns status of BIOS Interface Lockdown
+
+  @retval TRUE  BIOS Interface Lockdown is enabled
+  @retval FALSE BIOS Interface Lockdown is disabled
+**/
+BOOLEAN
+SpiIsBiosInterfaceLockdownEnabled (
+  VOID
+  )
+{
+  return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD);
+}
+
+/**
+  Returns Flash Descriptor Override Pin Strap status
+
+  @retval TRUE     Flash Descriptor override is enabled
+  @retval FALSE    Flash Descriptor override is disabled
+**/
+BOOLEAN
+SpiIsFlashDescriptorOverrideEnabled (
+  VOID
+  )
+{
+  UINT32  SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDOPSS);
+}
+
+/**
+  Returns Flash Configuration Lock Down bit status
+
+  @retval TRUE    Flash Configuration Lock Down bit is set
+  @retval FALSE   Flash Configuration Lock Down bit is not set
+**/
+BOOLEAN
+SpiIsFlashConfigurationLockDownEnabled (
+  VOID
+  )
+{
+  UINT32  SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FLOCKDN);
+}
+
+/**
+  Returns Top Swap functionality enable state
+
+  @retval TRUE    Top Swap is enabled
+  @retval FALSE   Top Swap is disabled
+**/
+BOOLEAN
+SpiIsTopSwapEnabled (
+  VOID
+  )
+{
+  return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_TSS);
+}
+
+/**
+  Return Component Property Parameter Table for a given component number
+
+  @param[in]  ComponentNumber   SPI Component number
+  @param[out] CppTable          Component Poperty Parameter Table value
+
+  @retval TRUE  Vendor Specific Component Capabilities Register value was read
+  @reval  FALSE Vendor Specific Component Capabilities Register value was not present
+**/
+BOOLEAN
+SpiGetComponentPropertyParameterTable (
+  IN  UINT8  ComponentNumber,
+  OUT UINT32 *CppTable
+  )
+{
+  UINT32 SpiBar0;
+  UINT32 Data32;
+  SpiBar0 = SpiGetBar0 ();
+
+  //
+  // More than 2 components not supported
+  //
+  switch (ComponentNumber) {
+    case 0:
+      *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP0_VSCC0);
+      return TRUE;
+    case 1:
+      Data32    = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_FDBAR_FLASH_MAP0);
+      *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP1_VSCC1);
+      return !!(Data32 & BIT8);
+    default:
+      return FALSE;
+  }
+}
+
+/**
+  Returns valid bit status in given Component Property Parameter Table
+
+  @param[in] CppTable          Component Poperty Parameter Table value
+
+  @retval TRUE    Valid bit is set
+  @reval  FALSE   Valid bit is not set
+**/
+BOOLEAN
+SpiIsCppValidBitSet (
+  IN UINT32  CppTable
+  )
+{
+  return !!(CppTable & B_SPI_MEM_SFDPX_VSCCX_CPPTV);
+}
+
+/**
+  Checks if Flash Descriptor is valid
+
+  @retval TRUE  Flash Descriptor is valid
+  @retval FALSE Flash Descriptor is invalid
+**/
+BOOLEAN
+SpiIsFlashDescriptorValid (
+  VOID
+  )
+{
+  UINT32 SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV);
+}
+
+/**
+  Reads and returns value from Flash Region Access Permissions Register (FRAP)
+
+  @retval UINT32  Flash Region Access Permissions Register value
+**/
+STATIC
+UINT32
+SpiGetFlashRegionAccessPermissions (
+  VOID
+  )
+{
+  return MmioRead32 (SpiGetBar0 () + R_SPI_MEM_FRAP);
+}
+
+/**
+  Returns masked BIOS Master Read Access
+
+  @retval UINT32    Already masked BIOS Master Read Access
+**/
+UINT32
+SpiGetMasterReadAccess (
+  VOID
+  )
+{
+  UINT32 Data32;
+  Data32 = SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMRAG_MASK;
+  DEBUG ((DEBUG_INFO, "BMRAG 0x%x\n", Data32));
+
+  return Data32;
+}
+
+/**
+  Returns masked BIOS Master Write Access
+
+  @retval UINT32    Already masked BIOS Master Write Access
+**/
+UINT32
+SpiGetMasterWriteAccess (
+  VOID
+  )
+{
+  UINT32 Data32;
+  Data32 = SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMWAG_MASK;
+  DEBUG ((DEBUG_INFO, "BMWAG 0x%x\n", Data32));
+
+  return Data32;
+}
+
+/**
+  Returns GbE Region Access rights
+
+  @retval UINT32    GbE Region access rights
+**/
+UINT32
+SpiGetGbeRegionAccess (
+  VOID
+  )
+{
+  UINT32 Data32;
+
+  Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x8);
+  DEBUG ((DEBUG_INFO, "GbE Region Access 0x%x\n", Data32));
+
+  return Data32;
+}
+
+/**
+  Returns CSME region access rights
+
+  @retval UINT32    CSME Region Access rights
+**/
+UINT32
+SpiGetCsmeRegionAccess (
+  VOID
+  )
+{
+  UINT32 Data32;
+
+  Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x4);
+  DEBUG ((DEBUG_INFO, "CSME Region Access 0x%x\n", Data32));
+
+  return Data32;
+}
+
+/**
+  Returns EC region access right
+
+  @retval UINT32     EC Region access rights
+**/
+UINT32
+SpiGetEcRegionAccess (
+  VOID
+  )
+{
+  UINT32 Data32;
+
+  Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x10);
+  DEBUG ((DEBUG_INFO, "EC Region Access 0x%x\n", Data32));
+
+  return Data32;
+}
+
+/**
+  Checks if Slave Attached Flash (SAF) mode is active
+
+  @retval TRUE    SAF mode is active
+  @retval FALSE   SAF mode is not active
+**/
+BOOLEAN
+SpiIsSafModeActive (
+  VOID
+  )
+{
+  UINT32 SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE);
+}
+
+/**
+  Checks validity of GbE region
+
+  @retval TRUE    GbE region is valid
+  @retval FALSE   GbE regios in invalid
+**/
+BOOLEAN
+SpiIsGbeRegionValid (
+  VOID
+  )
+{
+  UINT32  SpiBar0;
+  SpiBar0 = SpiGetBar0 ();
+
+  if (MmioRead32 (SpiBar0 + R_SPI_MEM_FREG3_GBE) != B_SPI_MEM_FREGX_BASE_MASK) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Returns TRUE if BIOS Boot Strap is set to SPI
+
+  @retval TRUE    BIOS Boot strap is set to SPI
+  @retval FALSE   BIOS Boot strap is set to LPC/eSPI
+**/
+BOOLEAN
+SpiIsBiosBootFromSpi (
+  VOID
+  )
+{
+  return !!(((PciSegmentRead8 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_BBS) >> N_SPI_CFG_BC_BBS) == V_SPI_CFG_BC_BBS_SPI);
+}
+
+/**
+  Check SPI write status disable is set
+
+  @retval TRUE    Write status disable is set
+  @retval FALSE   Write status disable is not set
+**/
+BOOLEAN
+SpiIsWriteStatusDisable (
+  VOID
+  )
+{
+  return !!(MmioRead32 (SpiGetBar0 () + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_WRSDIS);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
new file mode 100644
index 0000000000..a1a5467745
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
@@ -0,0 +1,31 @@
+## @file
+#  Component description file for the PchSpiCommonLib
+#
+#  Copyright (c) 2021, 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
+  TigerlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  PmcLib
+  PchPciBdfLib
+  SpiAccessLib
+
+[Pcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..954b349e7c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1115 @@
+/** @file
+  PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2021, 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>
+#include <Library/SpiAccessLib.h>
+
+/**
+  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 (SpiInstance->CpuStrapBaseAddr != 0x300) {
+    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_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_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) {
+      MmioWrite32 (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 sends the programmed SPI command to the slave 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
+  )
+{
+  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;
+
+  //
+  // 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;
+  PchSpiBar0        = AcquireSpiBar0 (SpiInstance);
+  ABase             = SpiInstance->PchAcpiBase;
+
+  //
+  // 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;
+
+  //
+  // 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)
+      );
+  }
+  //
+  // 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 atmost 64 byte
+      //   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 duing 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 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
+      );
+  }
+  //
+  // Restore SMIs.
+  //
+  IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave);
+
+  ReleaseSpiBar0 (SpiInstance);
+
+  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
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  EFI_STATUS        Status;
+  UINT32            FlashAddress;
+
+  if (SpiIsSafModeActive ()) {
+    DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+    return EFI_UNSUPPORTED;
+  }
+
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  Status            = EFI_SUCCESS;
+
+  if (ComponentNumber > SpiInstance->NumberOfComponents) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FlashAddress = 0;
+  if (ComponentNumber == FlashComponent1) {
+    FlashAddress = SpiInstance->Component1StartAddr;
+  }
+  FlashAddress += Address;
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadSfdp,
+             FlashAddress,
+             ByteCount,
+             SfdpData
+             );
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  EFI_STATUS        Status;
+  UINT32            Address;
+
+  if (SpiIsSafModeActive ()) {
+    DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+    return EFI_UNSUPPORTED;
+  }
+
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  Status            = EFI_SUCCESS;
+
+  if (ComponentNumber > SpiInstance->NumberOfComponents) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Address = 0;
+  if (ComponentNumber == FlashComponent1) {
+    Address = SpiInstance->Component1StartAddr;
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadJedecId,
+             Address,
+             ByteCount,
+             JedecId
+             );
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  EFI_STATUS        Status;
+
+  if (SpiIsSafModeActive ()) {
+    DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleWriteStatus,
+             0,
+             ByteCount,
+             StatusValue
+             );
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  EFI_STATUS        Status;
+
+  if (SpiIsSafModeActive ()) {
+    DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadStatus,
+             0,
+             ByteCount,
+             StatusValue
+             );
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  UINT32            StrapFlashAddr;
+  EFI_STATUS        Status;
+
+  SpiInstance     = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  if (ByteCount == 0) {
+    *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+    return EFI_SUCCESS;
+  }
+
+  if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // PCH Strap Flash Address = FPSBA + RamAddr
+  //
+  StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+  //
+  // Read PCH Soft straps from using execute command
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionDescriptor,
+             FlashCycleRead,
+             StrapFlashAddr,
+             ByteCount,
+             SoftStrapValue
+             );
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  UINT32            StrapFlashAddr;
+  EFI_STATUS        Status;
+
+  SpiInstance     = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  if (ByteCount == 0) {
+    *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+    return EFI_SUCCESS;
+  }
+
+  if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // CPU Strap Flash Address = FCPUSBA + RamAddr
+  //
+  StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+  //
+  // Read Cpu Soft straps from using execute command
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionDescriptor,
+             FlashCycleRead,
+             StrapFlashAddr,
+             ByteCount,
+             SoftStrapValue
+             );
+  return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf
new file mode 100644
index 0000000000..4e059494d8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for PCH SPI access private library
+#
+#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION     = 0x00010017
+BASE_NAME       = PeiDxeSmmSpiAccessPrivateLib
+FILE_GUID       = 2CD382D7-9928-C32A-601D-69797C618A6D
+VERSION_STRING  = 1.0
+MODULE_TYPE     = BASE
+LIBRARY_CLASS   = SpiAccessPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+SpiAccessLib
+PcdLib
+S3BootScriptLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SpiAccessPrivateLib.c
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c
new file mode 100644
index 0000000000..de1f3d3f86
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c
@@ -0,0 +1,133 @@
+/** @file
+  SPI library for abstraction of SPI HW registers accesses
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/SpiAccessLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/SpiRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+  Disable EISS (Enable InSMM.STS)
+**/
+VOID
+SpiDisableEiss (
+  VOID
+  )
+{
+  UINT64  SpiBaseAddress;
+  SpiBaseAddress = SpiPciCfgBase ();
+
+  ASSERT ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_LE) == 0);
+
+  PciSegmentAnd8 (SpiBaseAddress + R_SPI_CFG_BC, (UINT8) ~(B_SPI_CFG_BC_EISS));
+}
+
+/**
+  Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting.
+
+  @param[in] BiosLockEnable     Policy for BiosLockEnable bit programming
+  @param[in] BiosInterfaceLock  Policy for BiosInterfaceLock bit programming
+
+**/
+VOID
+SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (
+  IN BOOLEAN  BiosLockEnable,
+  IN BOOLEAN  BiosInterfaceLock
+  )
+{
+  UINT64                   SpiBaseAddress;
+  UINT8                    SpiData8;
+
+  if (!BiosLockEnable && !BiosInterfaceLock) {
+    return;
+  }
+
+  SpiBaseAddress = SpiPciCfgBase ();
+
+  ///
+  /// PCH BIOS Spec Flash Security Recommendation
+  ///
+  /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting
+  /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
+  /// When this bit is set, attempts to write the Write Protect Disable (WPD) bit
+  /// in PCH will cause a SMI which will allow the BIOS to verify that the write is
+  /// from a valid source.
+  /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable
+  /// BIOS region protection before exiting the SMI handler.
+  /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep
+  /// BLE feature enabled after booting to the OS.
+  /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to
+  /// ensure SMM protection of flash.
+  /// RC installs a default SMI handler that clears WPD.
+  /// There could be additional SMI handler to log such attempt if desired.
+  ///
+  /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the PCH by setting
+  /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 1b for eSPI.
+  /// When this bit is set, the BIOS region is not writable until SMM sets the InSMM.STS bit,
+  /// to ensure BIOS can only be modified from SMM. Please refer to CPU BWG for more details
+  /// on InSMM.STS bit.
+  /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to ensure
+  /// SMM protection of flash.
+  /// SPI PCI offset DCh[1] = 1b for SPI or setting eSPI PCI offset DCh[1] = 1b for eSPI.
+  /// When this bit is set, EISS is locked down.
+  ///
+  SpiData8 = 0;
+  if (BiosLockEnable) {
+    SpiData8 |= B_SPI_CFG_BC_EISS | B_SPI_CFG_BC_LE;
+  }
+  ///
+  /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations
+  /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]).
+  /// (done in PchInit/Dxe/PchInit.c by PchDmiSetBiosLockDownWithS3BootScript ()) for PCR[DMI] 274Ch)
+  /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations)
+  /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software
+  /// attempts to replace the system BIOS option ROM with its own code.
+  ///
+  if (BiosInterfaceLock) {
+    SpiData8 |= B_SPI_CFG_BC_BILD;
+  }
+
+  PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, SpiData8);
+  S3BootScriptSaveMemWrite (
+    S3BootScriptWidthUint8,
+    PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
+    1,
+    (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC)
+    );
+  //
+  // Reads back for posted write to take effect
+  //
+  SpiData8 = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC);
+  S3BootScriptSaveMemPoll  (
+    S3BootScriptWidthUint8,
+    PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
+    &SpiData8,
+    &SpiData8,
+    1,
+    1
+    );
+}
+
+/**
+  Clears BIOS Write Protect Disable bit
+**/
+VOID
+SpiClearBiosWriteProtectDisable (
+  VOID
+  )
+{
+  //
+  // Disable BIOSWE bit to protect BIOS
+  //
+  PciSegmentAnd8 (SpiPciCfgBase () + R_SPI_CFG_BC, (UINT8) ~B_SPI_CFG_BC_WPD);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
new file mode 100644
index 0000000000..419eddaff3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
@@ -0,0 +1,296 @@
+/** @file
+  PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2021, 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/SmmPchPrivateLib.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 assiged 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;
+
+/**
+  <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;
+
+  //
+  // Init PCH spi reserved MMIO address.
+  //
+  mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+  ///
+  /// 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;
+  }
+  ///
+  /// 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.
+  If it is ever different from the preallocated address, reassign it back.
+  In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval PchSpiBar0              return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+  IN  SPI_INSTANCE                *SpiInstance
+  )
+{
+  UINT32                          SpiBar0;
+  //
+  // Save original SPI physical MMIO address
+  //
+  SpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+
+  if (SpiBar0 != mSpiResvMmioAddr) {
+    //
+    // 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);
+  }
+  //
+  // 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. 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 ();
+  // 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
+    );
+
+  ///
+  /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling
+  /// If the following steps are implemented:
+  ///  - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b
+  ///  - Follow the 1st recommendation in section 3.6
+  /// the BIOS Region can only be updated by following the steps bellow:
+  ///  - Once all threads enter SMM
+  ///  - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+  ///    and write data to lower 32 bits of MSR 1FEh (sample code available)
+  ///  - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+  ///  - Modify BIOS Region
+  ///  - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+  ///
+  if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS) != 0) {
+    PchSetInSmmSts ();
+  }
+
+  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 EISS bit is set
+  ///
+  if (((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC)) & B_SPI_CFG_BC_EISS) == B_SPI_CFG_BC_EISS) {
+    PchClearInSmmSts ();
+  }
+}
+
+/**
+  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;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
new file mode 100644
index 0000000000..033134cea1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+#  Copyright (c) 2021, 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
+SmmPchPrivateLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+Spi.c
+
+
+[Protocols]
+gPchSmmSpiProtocolGuid ## PRODUCES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()
-- 
2.24.0.windows.2


  parent reply	other threads:[~2021-02-05  7:41 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05  7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
2021-02-05  7:40 ` [Patch V3 02/40] TigerlakeSiliconPkg/Include: Add Library, PPI and Protocol include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 03/40] TigerlakeSiliconPkg/Include: Add Pins, Register and other " Heng Luo
2021-02-05  7:40 ` [Patch V3 04/40] TigerlakeSiliconPkg/Cpu: Add Include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 05/40] TigerlakeSiliconPkg/Pch: Add include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 06/40] TigerlakeSiliconPkg/Pch: Add IncludePrivate headers Heng Luo
2021-02-05  7:40 ` [Patch V3 07/40] TigerlakeSiliconPkg/SystemAgent: Add include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 08/40] TigerlakeSiliconPkg/SystemAgent: Add IncludePrivate headers Heng Luo
2021-02-05  7:40 ` [Patch V3 09/40] TigerlakeSiliconPkg/Fru: Add TglCpu/Include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 10/40] TigerlakeSiliconPkg/Fru: Add TglCpu/IncludePrivate headers Heng Luo
2021-02-05  7:40 ` [Patch V3 11/40] TigerlakeSiliconPkg/Fru: Add TglPch/Include headers Heng Luo
2021-02-05  7:40 ` [Patch V3 12/40] TigerlakeSiliconPkg/Fru: Add TglPch/IncludePrivate headers Heng Luo
2021-02-05  7:40 ` [Patch V3 13/40] TigerlakeSiliconPkg/IpBlock: Add Cnvi component Heng Luo
2021-02-05  7:40 ` [Patch V3 14/40] TigerlakeSiliconPkg/IpBlock: Add CpuPcieRp component Heng Luo
2021-02-05  7:40 ` [Patch V3 15/40] TigerlakeSiliconPkg/IpBlock: Add Espi component Heng Luo
2021-02-05  7:40 ` [Patch V3 16/40] TigerlakeSiliconPkg/IpBlock: Add Gbe component Heng Luo
2021-02-05  7:40 ` [Patch V3 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component Heng Luo
2021-02-05  7:40 ` [Patch V3 18/40] TigerlakeSiliconPkg/IpBlock: Add Graphics component Heng Luo
2021-02-05  7:40 ` [Patch V3 19/40] TigerlakeSiliconPkg/IpBlock: Add Hda component Heng Luo
2021-02-05  7:40 ` [Patch V3 20/40] TigerlakeSiliconPkg/IpBlock: Add HostBridge component Heng Luo
2021-02-05  7:40 ` [Patch V3 21/40] TigerlakeSiliconPkg/IpBlock: Add P2sb component Heng Luo
2021-02-05  7:40 ` [Patch V3 22/40] TigerlakeSiliconPkg/IpBlock: Add PchDmi component Heng Luo
2021-02-05  7:40 ` [Patch V3 23/40] TigerlakeSiliconPkg/IpBlock: Add PcieRp component Heng Luo
2021-02-05  7:40 ` [Patch V3 24/40] TigerlakeSiliconPkg/IpBlock: Add Pmc component Heng Luo
2021-02-05  7:40 ` [Patch V3 25/40] TigerlakeSiliconPkg/IpBlock: Add Psf component Heng Luo
2021-02-05  7:40 ` [Patch V3 26/40] TigerlakeSiliconPkg/IpBlock: Add Sata component Heng Luo
2021-02-05  7:40 ` [Patch V3 27/40] TigerlakeSiliconPkg/IpBlock: Add SerialIo component Heng Luo
2021-02-05  7:40 ` [Patch V3 28/40] TigerlakeSiliconPkg/IpBlock: Add Smbus component Heng Luo
2021-02-05  7:40 ` Heng Luo [this message]
2021-02-05  7:40 ` [Patch V3 30/40] TigerlakeSiliconPkg/IpBlock: Add Vtd component Heng Luo
2021-02-05  7:40 ` [Patch V3 31/40] TigerlakeSiliconPkg/Library: Add package common library instances Heng Luo
2021-02-05  7:40 ` [Patch V3 32/40] TigerlakeSiliconPkg/Pch: Add Pch " Heng Luo
2021-02-05  7:40 ` [Patch V3 33/40] TigerlakeSiliconPkg/Pch: Add Pch private " Heng Luo
2021-02-05  7:40 ` [Patch V3 34/40] TigerlakeSiliconPkg/SystemAgent: Add Acpi Tables and " Heng Luo
2021-02-05  7:40 ` [Patch V3 35/40] TigerlakeSiliconPkg/Fru/TglCpu: Add CpuPcieRp and Vtd " Heng Luo
2021-02-05  7:40 ` [Patch V3 36/40] TigerlakeSiliconPkg/Pch: Add Pch modules Heng Luo
2021-02-05  7:40 ` [Patch V3 37/40] TigerlakeSiliconPkg/SystemAgent: Add SystemAgent modules Heng Luo
2021-02-05  7:40 ` [Patch V3 38/40] TigerlakeSiliconPkg/Fru: Add Fru DSC files Heng Luo
2021-02-05  7:40 ` [Patch V3 39/40] TigerlakeSiliconPkg: Add package " Heng Luo
2021-02-05  7:40 ` [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers Heng Luo
2021-02-05 18:36   ` Nate DeSimone
2021-02-05 18:57     ` Chaganty, Rangasai V

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=20210205074045.3916-29-heng.luo@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox