[edk2-devel] [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances

Kubacki, Michael A posted 37 patches 6 years, 4 months ago
[edk2-devel] [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances
Posted by Kubacki, Michael A 6 years, 4 months ago
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082

Adds Pch/Library/Private Base library class instances.

* BaseGpioHelpersLibNull
* BasePchSpiCommonlib
* BaseSiScheduleResetLib
* BaseSiScheduleResetLibFsp

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
---
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf     |   26 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf           |   28 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf     |   40 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf  |   40 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c       |  108 ++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c                       | 1081 ++++++++++++++++++++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c       |   70 ++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c |  125 +++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c    |   61 ++
 9 files changed, 1579 insertions(+)

diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
new file mode 100644
index 0000000000..5502af824f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# Component description file for the NULL GpioHelpersLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseGpioHelpersLib
+FILE_GUID = AB282608-2A50-4AE3-9242-64064ECF40D4
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioHelpersLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseGpioHelpersLibNull.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..ea23e628c8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,28 @@
+## @file
+#  Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePchSpiCommonLib
+  FILE_GUID                      = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PchSpiCommonLib
+
+[Sources]
+  SpiCommon.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  CoffeelakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  PmcLib
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
new file mode 100644
index 0000000000..de7f6eeb73
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for Si Reset Schedule Library.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiScheduleResetLib
+FILE_GUID = E6F3D551-36C0-4737-80C7-47FC57593163
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiScheduleResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+ResetSystemLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Guids]
+gSiScheduleResetHobGuid
+gPchConfigHobGuid
+
+[Sources]
+BaseSiScheduleResetLibCommon.c
+BaseSiScheduleResetLib.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf
new file mode 100644
index 0000000000..c8fe9e6079
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for Si Reset Schedule Library.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiScheduleResetLibFsp
+FILE_GUID = 1478D005-8DEC-4A6E-9619-309C6A7F313A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiScheduleResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+PeiServicesTablePointerLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Guids]
+gSiScheduleResetHobGuid
+gPchConfigHobGuid
+
+[Sources]
+BaseSiScheduleResetLibCommon.c
+BaseSiScheduleResetLibFsp.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
new file mode 100644
index 0000000000..46390eeca1
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
@@ -0,0 +1,108 @@
+/** @file
+  This file contains NULL implementation for GPIO Helpers Lib
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <GpioConfig.h>
+
+/**
+  This procedure stores GPIO pad unlock information
+
+  @param[in] GpioPad         GPIO pad
+  @param[in] GpioLockConfig  GPIO Lock Configuration
+
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+  IN GPIO_PAD             GpioPad,
+  IN GPIO_LOCK_CONFIG     GpioLockConfig
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @param[in]  UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: Skip, 1: Leave unlocked
+
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum,
+  IN UINT32                       UnlockedPads
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @param[in]  UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: Skip, 1: Leave unlocked
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum,
+  IN UINT32                       UnlockedPads
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @retval     UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum
+  )
+{
+  return 0;
+}
+
+/**
+  This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @retval     UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum
+  )
+{
+  return 0;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..bc84a4f27f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1081 @@
+/** @file
+  PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/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 <Private/Library/PchSpiCommonLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsSpi.h>
+#include <Register/PchRegsPmc.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;
+
+  //
+  // 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 = PCI_SEGMENT_LIB_ADDRESS (
+                              DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+                              DEFAULT_PCI_BUS_NUMBER_PCH,
+                              PCI_DEVICE_NUMBER_PCH_SPI,
+                              PCI_FUNCTION_NUMBER_PCH_SPI,
+                              0
+                              );
+
+  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_SPI_FLASH_FDBAR_FLASH_MAP0)
+    );
+
+  //
+  // Copy Zero based Number Of Components
+  //
+  SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FDOD) & B_SPI_FLASH_FDBAR_NC) >> N_SPI_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_SPI_FLASH_FCBA_FLCOMP)
+    );
+
+  //
+  // Copy Component 0 Density
+  //
+  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+  if (SpiInstance->NumberOfComponents > 0) {
+    SpiInstance->Component1StartAddr = V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      (Data32 & B_SPI_FLASH_FLCOMP_COMP0_MASK);
+    DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+    SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+      (V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      ((Data32 & B_SPI_FLASH_FLCOMP_COMP1_MASK) >>
+      N_SPI_FLASH_FLCOMP_COMP1));
+  } else {
+    SpiInstance->TotalFlashSize = V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      (Data32 & B_SPI_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_SPI_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_SPI_FLASH_FDBAR_FPSBA)
+                                             >> N_SPI_FLASH_FDBAR_FPSBA)
+                                            << N_SPI_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_SPI_FLASH_FDBAR_PCHSL)
+                                         >> N_SPI_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_SPI_FLASH_FDBAR_FLASH_MAP2)
+    );
+  //
+  // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+  //
+  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+  SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_FCPUSBA)
+                                             >> N_SPI_FLASH_FDBAR_FCPUSBA)
+                                            << N_SPI_FLASH_FDBAR_FCPUSBA_REPR);
+  DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+  ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+  //
+  // CPU Strap Length, [15:8] represents number of Dwords
+  //
+  SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_CPUSL)
+                                         >> N_SPI_FLASH_FDBAR_CPUSL)
+                                        * sizeof (UINT32));
+  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 (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.
+**/
+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;
+
+  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.
+**/
+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;
+
+  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.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+  IN     PCH_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // 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.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+  IN     PCH_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // 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/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
new file mode 100644
index 0000000000..dfc49d9bf6
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
@@ -0,0 +1,70 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <Private/Library/SiScheduleResetLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  );
+
+/**
+  This function performs reset based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+  VOID
+  )
+{
+  UINTN                 DataSize;
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+
+  if (!SiScheduleResetIsRequired ()) {
+    return FALSE;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+
+  if (SiScheduleResetHob == NULL) {
+    return TRUE;
+  }
+
+  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  switch (SiScheduleResetHob->ResetType) {
+  case EfiResetWarm:
+    ResetWarm ();
+    break;
+
+  case EfiResetCold:
+    ResetCold ();
+    break;
+
+  case EfiResetShutdown:
+    ResetShutdown ();
+    break;
+
+  case EfiResetPlatformSpecific:
+    DataSize = sizeof (PCH_RESET_DATA);
+    ResetPlatformSpecific (DataSize, &SiScheduleResetHob->ResetData);
+    break;
+  }
+  // Code should never reach here
+  ASSERT (FALSE);
+  return TRUE;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c
new file mode 100644
index 0000000000..e1d783b2e2
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c
@@ -0,0 +1,125 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  )
+{
+  STATIC SI_SCHEDULE_RESET_HOB *SiScheduleResetHob = NULL;
+  SI_SCHEDULE_RESET_HOB        *SiScheduleResetHobTemp;
+  VOID                         *HobPtr;
+
+  if (SiScheduleResetHob != NULL) {
+    return SiScheduleResetHob;
+  }
+
+  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+  if (HobPtr == NULL) {
+    SiScheduleResetHobTemp = BuildGuidHob (&gSiScheduleResetHobGuid, sizeof (SI_SCHEDULE_RESET_HOB));
+    if (SiScheduleResetHobTemp == NULL) {
+      ASSERT (FALSE);
+      return SiScheduleResetHobTemp;
+    }
+    SiScheduleResetHobTemp->ResetType = 0xFF;
+    DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Init SiScheduleResetHob\n"));
+  } else {
+    SiScheduleResetHobTemp = (SI_SCHEDULE_RESET_HOB*) GET_GUID_HOB_DATA (HobPtr);
+  }
+  SiScheduleResetHob = SiScheduleResetHobTemp;
+  return SiScheduleResetHobTemp;
+}
+
+/**
+  This function updates the reset information in SiScheduleResetHob
+  @param[in] ResetType        UEFI defined reset type.
+  @param[in] ResetData        Optional element used to introduce a platform specific reset.
+                               The exact type of the reset is defined by the EFI_GUID that follows
+                               the Null-terminated Unicode string.
+**/
+VOID
+SiScheduleResetSetType (
+  IN EFI_RESET_TYPE     ResetType,
+  IN PCH_RESET_DATA     *ResetData OPTIONAL
+  )
+{
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+  if (ResetType > EfiResetPlatformSpecific) {
+    DEBUG ((DEBUG_INFO, "Unsupported Reset Type Requested\n"));
+    return;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+  if (SiScheduleResetHob == NULL) {
+    return;
+  }
+  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Current Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  if (SiScheduleResetHob->ResetType == ResetType) {
+    DEBUG ((DEBUG_INFO, "Current Reset Type is same as requested Reset Type\n"));
+    return;
+  }
+  if (SiScheduleResetHob->ResetType == 0xFF) {
+    //
+    // Init Reset Type to lowest ResetType
+  //
+    SiScheduleResetHob->ResetType = EfiResetWarm;
+  }
+  //
+  // ResetType Priority set as : ResetPlatformSpecific(3) > ResetShutdown(2) > ResetCold(0) > ResetWarm(1)
+  //
+  switch (ResetType) {
+    case EfiResetWarm:
+      break;
+
+    case EfiResetCold:
+      if (SiScheduleResetHob->ResetType == EfiResetWarm) {
+        SiScheduleResetHob->ResetType = ResetType;
+      }
+      break;
+
+    case EfiResetShutdown:
+      if (SiScheduleResetHob->ResetType < ResetType)
+      SiScheduleResetHob->ResetType = ResetType;
+      break;
+
+    case EfiResetPlatformSpecific:
+      SiScheduleResetHob->ResetType = ResetType;
+      SiScheduleResetHob->ResetData = *ResetData;
+      break;
+  }
+  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : New Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+}
+
+/**
+  This function returns TRUE or FALSE depending on whether a reset is required based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetIsRequired (
+  VOID
+  )
+{
+  VOID                  *HobPtr;
+
+  HobPtr = NULL;
+  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+  if (HobPtr == NULL) {
+    return FALSE;
+  }
+  return TRUE;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c
new file mode 100644
index 0000000000..15ac61a21b
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c
@@ -0,0 +1,61 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Pi/PiPeiCis.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/HobLib.h>
+#include <Private/Library/SiScheduleResetLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  );
+
+/**
+  This function performs reset based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+  VOID
+  )
+{
+  UINTN                 DataSize;
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+
+  if (!SiScheduleResetIsRequired ()) {
+    return FALSE;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+
+  if (SiScheduleResetHob == NULL) {
+    return TRUE;
+  }
+
+  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  if (SiScheduleResetHob->ResetType == EfiResetPlatformSpecific) {
+    DataSize = sizeof (PCH_RESET_DATA);
+    (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->ResetType, EFI_SUCCESS, DataSize, &SiScheduleResetHob->ResetData);
+  } else {
+    (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->ResetType, EFI_SUCCESS, 0, NULL);
+  }
+  //
+  // Code should never reach here
+  //
+  ASSERT (FALSE);
+  return TRUE;
+}
-- 
2.16.2.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45898): https://edk2.groups.io/g/devel/message/45898
Mute This Topic: https://groups.io/mt/32918190/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances
Posted by Nate DeSimone 6 years, 4 months ago
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Kubacki, Michael A 
Sent: Friday, August 16, 2019 5:16 PM
To: devel@edk2.groups.io
Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Sinha, Ankit <ankit.sinha@intel.com>
Subject: [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances

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

Adds Pch/Library/Private Base library class instances.

* BaseGpioHelpersLibNull
* BasePchSpiCommonlib
* BaseSiScheduleResetLib
* BaseSiScheduleResetLibFsp

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
---
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf     |   26 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf           |   28 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf     |   40 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf  |   40 +
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c       |  108 ++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c                       | 1081 ++++++++++++++++++++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c       |   70 ++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c |  125 +++
 Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c    |   61 ++
 9 files changed, 1579 insertions(+)

diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
new file mode 100644
index 0000000000..5502af824f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# Component description file for the NULL GpioHelpersLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseGpioHelpersLib
+FILE_GUID = AB282608-2A50-4AE3-9242-64064ECF40D4
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioHelpersLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseGpioHelpersLibNull.c
+
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..ea23e628c8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,28 @@
+## @file
+#  Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePchSpiCommonLib
+  FILE_GUID                      = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PchSpiCommonLib
+
+[Sources]
+  SpiCommon.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  CoffeelakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  PmcLib
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
new file mode 100644
index 0000000000..de7f6eeb73
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for Si Reset Schedule Library.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiScheduleResetLib
+FILE_GUID = E6F3D551-36C0-4737-80C7-47FC57593163
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiScheduleResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+ResetSystemLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Guids]
+gSiScheduleResetHobGuid
+gPchConfigHobGuid
+
+[Sources]
+BaseSiScheduleResetLibCommon.c
+BaseSiScheduleResetLib.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf
new file mode 100644
index 0000000000..c8fe9e6079
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for Si Reset Schedule Library.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiScheduleResetLibFsp
+FILE_GUID = 1478D005-8DEC-4A6E-9619-309C6A7F313A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiScheduleResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+PeiServicesTablePointerLib
+
+[Packages]
+MdePkg/MdePkg.dec
+CoffeelakeSiliconPkg/SiPkg.dec
+
+[Guids]
+gSiScheduleResetHobGuid
+gPchConfigHobGuid
+
+[Sources]
+BaseSiScheduleResetLibCommon.c
+BaseSiScheduleResetLibFsp.c
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
new file mode 100644
index 0000000000..46390eeca1
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
@@ -0,0 +1,108 @@
+/** @file
+  This file contains NULL implementation for GPIO Helpers Lib
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <GpioConfig.h>
+
+/**
+  This procedure stores GPIO pad unlock information
+
+  @param[in] GpioPad         GPIO pad
+  @param[in] GpioLockConfig  GPIO Lock Configuration
+
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+  IN GPIO_PAD             GpioPad,
+  IN GPIO_LOCK_CONFIG     GpioLockConfig
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @param[in]  UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: Skip, 1: Leave unlocked
+
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum,
+  IN UINT32                       UnlockedPads
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @param[in]  UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: Skip, 1: Leave unlocked
+  @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum,
+  IN UINT32                       UnlockedPads
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @retval     UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum
+  )
+{
+  return 0;
+}
+
+/**
+  This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+  @param[in]  GroupIndex          GPIO group index
+  @param[in]  DwNum               DWORD index for a group.
+                                  For group which has less then 32 pads per group DwNum must be 0.
+  @retval     UnlockedPads        DWORD bitmask for pads which are going to be left unlocked
+                                  Bit position - PadNumber
+                                  Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+  IN UINT32                       GroupIndex,
+  IN UINT32                       DwNum
+  )
+{
+  return 0;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..bc84a4f27f
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1081 @@
+/** @file
+  PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/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 <Private/Library/PchSpiCommonLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsSpi.h>
+#include <Register/PchRegsPmc.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;
+
+  //
+  // 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 = PCI_SEGMENT_LIB_ADDRESS (
+                              DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+                              DEFAULT_PCI_BUS_NUMBER_PCH,
+                              PCI_DEVICE_NUMBER_PCH_SPI,
+                              PCI_FUNCTION_NUMBER_PCH_SPI,
+                              0
+                              );
+
+  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_SPI_FLASH_FDBAR_FLASH_MAP0)
+    );
+
+  //
+  // Copy Zero based Number Of Components
+  //
+  SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FDOD) & B_SPI_FLASH_FDBAR_NC) >> N_SPI_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_SPI_FLASH_FCBA_FLCOMP)
+    );
+
+  //
+  // Copy Component 0 Density
+  //
+  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+  if (SpiInstance->NumberOfComponents > 0) {
+    SpiInstance->Component1StartAddr = V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      (Data32 & B_SPI_FLASH_FLCOMP_COMP0_MASK);
+    DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+    SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+      (V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      ((Data32 & B_SPI_FLASH_FLCOMP_COMP1_MASK) >>
+      N_SPI_FLASH_FLCOMP_COMP1));
+  } else {
+    SpiInstance->TotalFlashSize = V_SPI_FLASH_FLCOMP_COMP_512KB <<
+      (Data32 & B_SPI_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_SPI_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_SPI_FLASH_FDBAR_FPSBA)
+                                             >> N_SPI_FLASH_FDBAR_FPSBA)
+                                            << N_SPI_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_SPI_FLASH_FDBAR_PCHSL)
+                                         >> N_SPI_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_SPI_FLASH_FDBAR_FLASH_MAP2)
+    );
+  //
+  // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+  //
+  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+  SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_FCPUSBA)
+                                             >> N_SPI_FLASH_FDBAR_FCPUSBA)
+                                            << N_SPI_FLASH_FDBAR_FCPUSBA_REPR);
+  DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+  ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+  //
+  // CPU Strap Length, [15:8] represents number of Dwords
+  //
+  SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_CPUSL)
+                                         >> N_SPI_FLASH_FDBAR_CPUSL)
+                                        * sizeof (UINT32));
+  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 (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.
+**/
+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;
+
+  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.
+**/
+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;
+
+  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.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+  IN     PCH_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // 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.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+  IN     PCH_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // 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/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
new file mode 100644
index 0000000000..dfc49d9bf6
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
@@ -0,0 +1,70 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <Private/Library/SiScheduleResetLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  );
+
+/**
+  This function performs reset based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+  VOID
+  )
+{
+  UINTN                 DataSize;
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+
+  if (!SiScheduleResetIsRequired ()) {
+    return FALSE;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+
+  if (SiScheduleResetHob == NULL) {
+    return TRUE;
+  }
+
+  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  switch (SiScheduleResetHob->ResetType) {
+  case EfiResetWarm:
+    ResetWarm ();
+    break;
+
+  case EfiResetCold:
+    ResetCold ();
+    break;
+
+  case EfiResetShutdown:
+    ResetShutdown ();
+    break;
+
+  case EfiResetPlatformSpecific:
+    DataSize = sizeof (PCH_RESET_DATA);
+    ResetPlatformSpecific (DataSize, &SiScheduleResetHob->ResetData);
+    break;
+  }
+  // Code should never reach here
+  ASSERT (FALSE);
+  return TRUE;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c
new file mode 100644
index 0000000000..e1d783b2e2
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibCommon.c
@@ -0,0 +1,125 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  )
+{
+  STATIC SI_SCHEDULE_RESET_HOB *SiScheduleResetHob = NULL;
+  SI_SCHEDULE_RESET_HOB        *SiScheduleResetHobTemp;
+  VOID                         *HobPtr;
+
+  if (SiScheduleResetHob != NULL) {
+    return SiScheduleResetHob;
+  }
+
+  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+  if (HobPtr == NULL) {
+    SiScheduleResetHobTemp = BuildGuidHob (&gSiScheduleResetHobGuid, sizeof (SI_SCHEDULE_RESET_HOB));
+    if (SiScheduleResetHobTemp == NULL) {
+      ASSERT (FALSE);
+      return SiScheduleResetHobTemp;
+    }
+    SiScheduleResetHobTemp->ResetType = 0xFF;
+    DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Init SiScheduleResetHob\n"));
+  } else {
+    SiScheduleResetHobTemp = (SI_SCHEDULE_RESET_HOB*) GET_GUID_HOB_DATA (HobPtr);
+  }
+  SiScheduleResetHob = SiScheduleResetHobTemp;
+  return SiScheduleResetHobTemp;
+}
+
+/**
+  This function updates the reset information in SiScheduleResetHob
+  @param[in] ResetType        UEFI defined reset type.
+  @param[in] ResetData        Optional element used to introduce a platform specific reset.
+                               The exact type of the reset is defined by the EFI_GUID that follows
+                               the Null-terminated Unicode string.
+**/
+VOID
+SiScheduleResetSetType (
+  IN EFI_RESET_TYPE     ResetType,
+  IN PCH_RESET_DATA     *ResetData OPTIONAL
+  )
+{
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+  if (ResetType > EfiResetPlatformSpecific) {
+    DEBUG ((DEBUG_INFO, "Unsupported Reset Type Requested\n"));
+    return;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+  if (SiScheduleResetHob == NULL) {
+    return;
+  }
+  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Current Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  if (SiScheduleResetHob->ResetType == ResetType) {
+    DEBUG ((DEBUG_INFO, "Current Reset Type is same as requested Reset Type\n"));
+    return;
+  }
+  if (SiScheduleResetHob->ResetType == 0xFF) {
+    //
+    // Init Reset Type to lowest ResetType
+  //
+    SiScheduleResetHob->ResetType = EfiResetWarm;
+  }
+  //
+  // ResetType Priority set as : ResetPlatformSpecific(3) > ResetShutdown(2) > ResetCold(0) > ResetWarm(1)
+  //
+  switch (ResetType) {
+    case EfiResetWarm:
+      break;
+
+    case EfiResetCold:
+      if (SiScheduleResetHob->ResetType == EfiResetWarm) {
+        SiScheduleResetHob->ResetType = ResetType;
+      }
+      break;
+
+    case EfiResetShutdown:
+      if (SiScheduleResetHob->ResetType < ResetType)
+      SiScheduleResetHob->ResetType = ResetType;
+      break;
+
+    case EfiResetPlatformSpecific:
+      SiScheduleResetHob->ResetType = ResetType;
+      SiScheduleResetHob->ResetData = *ResetData;
+      break;
+  }
+  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : New Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+}
+
+/**
+  This function returns TRUE or FALSE depending on whether a reset is required based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetIsRequired (
+  VOID
+  )
+{
+  VOID                  *HobPtr;
+
+  HobPtr = NULL;
+  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+  if (HobPtr == NULL) {
+    return FALSE;
+  }
+  return TRUE;
+}
diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c
new file mode 100644
index 0000000000..15ac61a21b
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.c
@@ -0,0 +1,61 @@
+/** @file
+  Reset scheduling library services
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Pi/PiPeiCis.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/HobLib.h>
+#include <Private/Library/SiScheduleResetLib.h>
+#include <Private/SiScheduleResetHob.h>
+
+/**
+  This function returns SiScheduleResetHob for library use
+**/
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+  VOID
+  );
+
+/**
+  This function performs reset based on SiScheduleResetHob
+
+  @retval     BOOLEAN       The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+  VOID
+  )
+{
+  UINTN                 DataSize;
+  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+
+  if (!SiScheduleResetIsRequired ()) {
+    return FALSE;
+  }
+  SiScheduleResetHob = SiScheduleGetResetData ();
+
+  if (SiScheduleResetHob == NULL) {
+    return TRUE;
+  }
+
+  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+  if (SiScheduleResetHob->ResetType == EfiResetPlatformSpecific) {
+    DataSize = sizeof (PCH_RESET_DATA);
+    (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->ResetType, EFI_SUCCESS, DataSize, &SiScheduleResetHob->ResetData);
+  } else {
+    (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->ResetType, EFI_SUCCESS, 0, NULL);
+  }
+  //
+  // Code should never reach here
+  //
+  ASSERT (FALSE);
+  return TRUE;
+}
-- 
2.16.2.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45935): https://edk2.groups.io/g/devel/message/45935
Mute This Topic: https://groups.io/mt/32918190/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances
Posted by Chiu, Chasel 6 years, 4 months ago
Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>


> -----Original Message-----
> From: Kubacki, Michael A
> Sent: Saturday, August 17, 2019 8:16 AM
> To: devel@edk2.groups.io
> Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Chiu, Chasel
> <chasel.chiu@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Sinha, Ankit
> <ankit.sinha@intel.com>
> Subject: [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add
> Base library instances
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082
> 
> Adds Pch/Library/Private Base library class instances.
> 
> * BaseGpioHelpersLibNull
> * BasePchSpiCommonlib
> * BaseSiScheduleResetLib
> * BaseSiScheduleResetLibFsp
> 
> Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
> Cc: Chasel Chiu <chasel.chiu@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ankit Sinha <ankit.sinha@intel.com>
> Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
> ---
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibN
> ull/BaseGpioHelpersLibNull.inf     |   26 +
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLi
> b/BasePchSpiCommonLib.inf           |   28 +
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLi
> b/BaseSiScheduleResetLib.inf     |   40 +
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLi
> b/BaseSiScheduleResetLibFsp.inf  |   40 +
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibN
> ull/BaseGpioHelpersLibNull.c       |  108 ++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLi
> b/SpiCommon.c                       | 1081 ++++++++++++++++++++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLi
> b/BaseSiScheduleResetLib.c       |   70 ++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLi
> b/BaseSiScheduleResetLibCommon.c |  125 +++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleResetLi
> b/BaseSiScheduleResetLibFsp.c    |   61 ++
>  9 files changed, 1579 insertions(+)
> 
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.inf
> new file mode 100644
> index 0000000000..5502af824f
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.inf
> @@ -0,0 +1,26 @@
> +## @file
> +# Component description file for the NULL GpioHelpersLib
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = BaseGpioHelpersLib
> +FILE_GUID = AB282608-2A50-4AE3-9242-64064ECF40D4
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = GpioHelpersLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +BaseGpioHelpersLibNull.c
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommon
> Lib/BasePchSpiCommonLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommo
> nLib/BasePchSpiCommonLib.inf
> new file mode 100644
> index 0000000000..ea23e628c8
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommo
> nLib/BasePchSpiCommonLib.inf
> @@ -0,0 +1,28 @@
> +## @file
> +#  Component description file for the PchSpiCommonLib
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BasePchSpiCommonLib
> +  FILE_GUID                      = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PchSpiCommonLib
> +
> +[Sources]
> +  SpiCommon.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  CoffeelakeSiliconPkg/SiPkg.dec
> +
> +[LibraryClasses]
> +  IoLib
> +  DebugLib
> +  PmcLib
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.inf
> new file mode 100644
> index 0000000000..de7f6eeb73
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.inf
> @@ -0,0 +1,40 @@
> +## @file
> +# Component description file for Si Reset Schedule Library.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = BaseSiScheduleResetLib
> +FILE_GUID = E6F3D551-36C0-4737-80C7-47FC57593163
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = SiScheduleResetLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF
> +#
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +HobLib
> +ResetSystemLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +[Guids]
> +gSiScheduleResetHobGuid
> +gPchConfigHobGuid
> +
> +[Sources]
> +BaseSiScheduleResetLibCommon.c
> +BaseSiScheduleResetLib.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.inf
> new file mode 100644
> index 0000000000..c8fe9e6079
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.inf
> @@ -0,0 +1,40 @@
> +## @file
> +# Component description file for Si Reset Schedule Library.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = BaseSiScheduleResetLibFsp
> +FILE_GUID = 1478D005-8DEC-4A6E-9619-309C6A7F313A
> +VERSION_STRING = 1.0
> +MODULE_TYPE = BASE
> +LIBRARY_CLASS = SiScheduleResetLib
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF
> +#
> +
> +[LibraryClasses]
> +BaseLib
> +IoLib
> +DebugLib
> +HobLib
> +PeiServicesTablePointerLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +[Guids]
> +gSiScheduleResetHobGuid
> +gPchConfigHobGuid
> +
> +[Sources]
> +BaseSiScheduleResetLibCommon.c
> +BaseSiScheduleResetLibFsp.c
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.c
> new file mode 100644
> index 0000000000..46390eeca1
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLib
> Null/BaseGpioHelpersLibNull.c
> @@ -0,0 +1,108 @@
> +/** @file
> +  This file contains NULL implementation for GPIO Helpers Lib
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +#include <GpioConfig.h>
> +
> +/**
> +  This procedure stores GPIO pad unlock information
> +
> +  @param[in] GpioPad         GPIO pad
> +  @param[in] GpioLockConfig  GPIO Lock Configuration
> +
> +  @retval Status
> +**/
> +EFI_STATUS
> +GpioStoreUnlockData (
> +  IN GPIO_PAD             GpioPad,
> +  IN GPIO_LOCK_CONFIG     GpioLockConfig
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This procedure stores GPIO group data about pads which PadConfig needs
> to be unlocked.
> +
> +  @param[in]  GroupIndex          GPIO group index
> +  @param[in]  DwNum               DWORD index for a group.
> +                                  For group which has less then 32 pads per group
> DwNum must be 0.
> +  @param[in]  UnlockedPads        DWORD bitmask for pads which are going
> to be left unlocked
> +                                  Bit position - PadNumber
> +                                  Bit value - 0: Skip, 1: Leave unlocked
> +
> +  @retval Status
> +**/
> +EFI_STATUS
> +GpioStoreGroupDwUnlockPadConfigData (
> +  IN UINT32                       GroupIndex,
> +  IN UINT32                       DwNum,
> +  IN UINT32                       UnlockedPads
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This procedure stores GPIO group data about pads which Output state
> needs to be unlocked.
> +
> +  @param[in]  GroupIndex          GPIO group index
> +  @param[in]  DwNum               DWORD index for a group.
> +                                  For group which has less then 32 pads per group
> DwNum must be 0.
> +  @param[in]  UnlockedPads        DWORD bitmask for pads which are going
> to be left unlocked
> +                                  Bit position - PadNumber
> +                                  Bit value - 0: Skip, 1: Leave unlocked
> +  @retval Status
> +**/
> +EFI_STATUS
> +GpioStoreGroupDwUnlockOutputData (
> +  IN UINT32                       GroupIndex,
> +  IN UINT32                       DwNum,
> +  IN UINT32                       UnlockedPads
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This procedure will get GPIO group data with pads, which PadConfig is
> supposed to be left unlock
> +
> +  @param[in]  GroupIndex          GPIO group index
> +  @param[in]  DwNum               DWORD index for a group.
> +                                  For group which has less then 32 pads per group
> DwNum must be 0.
> +  @retval     UnlockedPads        DWORD bitmask for pads which are going to
> be left unlocked
> +                                  Bit position - PadNumber
> +                                  Bit value - 0: to be locked, 1: Leave unlocked
> +**/
> +UINT32
> +GpioGetGroupDwUnlockPadConfigMask (
> +  IN UINT32                       GroupIndex,
> +  IN UINT32                       DwNum
> +  )
> +{
> +  return 0;
> +}
> +
> +/**
> +  This procedure will get GPIO group data with pads, which Output is
> supposed to be left unlock
> +
> +  @param[in]  GroupIndex          GPIO group index
> +  @param[in]  DwNum               DWORD index for a group.
> +                                  For group which has less then 32 pads per group
> DwNum must be 0.
> +  @retval     UnlockedPads        DWORD bitmask for pads which are going to
> be left unlocked
> +                                  Bit position - PadNumber
> +                                  Bit value - 0: to be locked, 1: Leave unlocked
> +**/
> +UINT32
> +GpioGetGroupDwUnlockOutputMask (
> +  IN UINT32                       GroupIndex,
> +  IN UINT32                       DwNum
> +  )
> +{
> +  return 0;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommon
> Lib/SpiCommon.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommo
> nLib/SpiCommon.c
> new file mode 100644
> index 0000000000..bc84a4f27f
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommo
> nLib/SpiCommon.c
> @@ -0,0 +1,1081 @@
> +/** @file
> +  PCH SPI Common Driver implements the SPI Host Controller Compatibility
> Interface.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi/UefiBaseType.h>
> +#include <Library/BaseLib.h>
> +#include <Library/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 <Private/Library/PchSpiCommonLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsSpi.h>
> +#include <Register/PchRegsPmc.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;
> +
> +  //
> +  // 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 = PCI_SEGMENT_LIB_ADDRESS (
> +                              DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                              DEFAULT_PCI_BUS_NUMBER_PCH,
> +                              PCI_DEVICE_NUMBER_PCH_SPI,
> +                              PCI_FUNCTION_NUMBER_PCH_SPI,
> +                              0
> +                              );
> +
> +  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_SPI_FLASH_FDBAR_FLASH_MAP0)
> +    );
> +
> +  //
> +  // Copy Zero based Number Of Components
> +  //
> +  SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0
> + R_SPI_MEM_FDOD) & B_SPI_FLASH_FDBAR_NC) >>
> N_SPI_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_SPI_FLASH_FCBA_FLCOMP)
> +    );
> +
> +  //
> +  // Copy Component 0 Density
> +  //
> +  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
> +  if (SpiInstance->NumberOfComponents > 0) {
> +    SpiInstance->Component1StartAddr =
> V_SPI_FLASH_FLCOMP_COMP_512KB <<
> +      (Data32 & B_SPI_FLASH_FLCOMP_COMP0_MASK);
> +    DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n",
> SpiInstance->Component1StartAddr));
> +    SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
> +      (V_SPI_FLASH_FLCOMP_COMP_512KB <<
> +      ((Data32 & B_SPI_FLASH_FLCOMP_COMP1_MASK) >>
> +      N_SPI_FLASH_FLCOMP_COMP1));
> +  } else {
> +    SpiInstance->TotalFlashSize = V_SPI_FLASH_FLCOMP_COMP_512KB <<
> +      (Data32 & B_SPI_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_SPI_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_SPI_FLASH_FDBAR_FPSBA)
> +                                             >> N_SPI_FLASH_FDBAR_FPSBA)
> +                                            << N_SPI_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_SPI_FLASH_FDBAR_PCHSL)
> +                                         >> N_SPI_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_SPI_FLASH_FDBAR_FLASH_MAP2)
> +    );
> +  //
> +  // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
> +  //
> +  Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
> +  SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 &
> B_SPI_FLASH_FDBAR_FCPUSBA)
> +                                             >> N_SPI_FLASH_FDBAR_FCPUSBA)
> +                                            << N_SPI_FLASH_FDBAR_FCPUSBA_REPR);
> +  DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n",
> SpiInstance->CpuStrapBaseAddr));
> +  ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
> +  //
> +  // CPU Strap Length, [15:8] represents number of Dwords
> +  //
> +  SpiInstance->CpuStrapSize = (UINT16) (((Data32 &
> B_SPI_FLASH_FDBAR_CPUSL)
> +                                         >> N_SPI_FLASH_FDBAR_CPUSL)
> +                                        * sizeof (UINT32));
> +  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 (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.
> +**/
> +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;
> +
> +  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.
> +**/
> +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;
> +
> +  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.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SpiProtocolFlashWriteStatus (
> +  IN     PCH_SPI_PROTOCOL   *This,
> +  IN     UINT32             ByteCount,
> +  IN     UINT8              *StatusValue
> +  )
> +{
> +  EFI_STATUS        Status;
> +
> +  //
> +  // 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.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SpiProtocolFlashReadStatus (
> +  IN     PCH_SPI_PROTOCOL   *This,
> +  IN     UINT32             ByteCount,
> +  OUT    UINT8              *StatusValue
> +  )
> +{
> +  EFI_STATUS        Status;
> +
> +  //
> +  // 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/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.c
> new file mode 100644
> index 0000000000..dfc49d9bf6
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLib.c
> @@ -0,0 +1,70 @@
> +/** @file
> +  Reset scheduling library services
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/ResetSystemLib.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Uefi.h>
> +#include <Pi/PiMultiPhase.h>
> +#include <Library/HobLib.h>
> +#include <Private/Library/SiScheduleResetLib.h>
> +#include <Private/SiScheduleResetHob.h>
> +
> +/**
> +  This function returns SiScheduleResetHob for library use
> +**/
> +SI_SCHEDULE_RESET_HOB *
> +SiScheduleGetResetData (
> +  VOID
> +  );
> +
> +/**
> +  This function performs reset based on SiScheduleResetHob
> +
> +  @retval     BOOLEAN       The function returns FALSE if no reset is required
> +**/
> +BOOLEAN
> +SiScheduleResetPerformReset (
> +  VOID
> +  )
> +{
> +  UINTN                 DataSize;
> +  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
> +
> +  if (!SiScheduleResetIsRequired ()) {
> +    return FALSE;
> +  }
> +  SiScheduleResetHob = SiScheduleGetResetData ();
> +
> +  if (SiScheduleResetHob == NULL) {
> +    return TRUE;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type =
> 0x%x\n", SiScheduleResetHob->ResetType));
> +  switch (SiScheduleResetHob->ResetType) {
> +  case EfiResetWarm:
> +    ResetWarm ();
> +    break;
> +
> +  case EfiResetCold:
> +    ResetCold ();
> +    break;
> +
> +  case EfiResetShutdown:
> +    ResetShutdown ();
> +    break;
> +
> +  case EfiResetPlatformSpecific:
> +    DataSize = sizeof (PCH_RESET_DATA);
> +    ResetPlatformSpecific (DataSize, &SiScheduleResetHob->ResetData);
> +    break;
> +  }
> +  // Code should never reach here
> +  ASSERT (FALSE);
> +  return TRUE;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibCommon.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibCommon.c
> new file mode 100644
> index 0000000000..e1d783b2e2
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibCommon.c
> @@ -0,0 +1,125 @@
> +/** @file
> +  Reset scheduling library services
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Uefi.h>
> +#include <Pi/PiMultiPhase.h>
> +#include <Library/HobLib.h>
> +#include <Private/SiScheduleResetHob.h>
> +
> +/**
> +  This function returns SiScheduleResetHob for library use
> +**/
> +SI_SCHEDULE_RESET_HOB *
> +SiScheduleGetResetData (
> +  VOID
> +  )
> +{
> +  STATIC SI_SCHEDULE_RESET_HOB *SiScheduleResetHob = NULL;
> +  SI_SCHEDULE_RESET_HOB        *SiScheduleResetHobTemp;
> +  VOID                         *HobPtr;
> +
> +  if (SiScheduleResetHob != NULL) {
> +    return SiScheduleResetHob;
> +  }
> +
> +  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
> +  if (HobPtr == NULL) {
> +    SiScheduleResetHobTemp = BuildGuidHob (&gSiScheduleResetHobGuid,
> sizeof (SI_SCHEDULE_RESET_HOB));
> +    if (SiScheduleResetHobTemp == NULL) {
> +      ASSERT (FALSE);
> +      return SiScheduleResetHobTemp;
> +    }
> +    SiScheduleResetHobTemp->ResetType = 0xFF;
> +    DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Init
> SiScheduleResetHob\n"));
> +  } else {
> +    SiScheduleResetHobTemp = (SI_SCHEDULE_RESET_HOB*)
> GET_GUID_HOB_DATA (HobPtr);
> +  }
> +  SiScheduleResetHob = SiScheduleResetHobTemp;
> +  return SiScheduleResetHobTemp;
> +}
> +
> +/**
> +  This function updates the reset information in SiScheduleResetHob
> +  @param[in] ResetType        UEFI defined reset type.
> +  @param[in] ResetData        Optional element used to introduce a platform
> specific reset.
> +                               The exact type of the reset is defined by the EFI_GUID
> that follows
> +                               the Null-terminated Unicode string.
> +**/
> +VOID
> +SiScheduleResetSetType (
> +  IN EFI_RESET_TYPE     ResetType,
> +  IN PCH_RESET_DATA     *ResetData OPTIONAL
> +  )
> +{
> +  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
> +  if (ResetType > EfiResetPlatformSpecific) {
> +    DEBUG ((DEBUG_INFO, "Unsupported Reset Type Requested\n"));
> +    return;
> +  }
> +  SiScheduleResetHob = SiScheduleGetResetData ();
> +  if (SiScheduleResetHob == NULL) {
> +    return;
> +  }
> +  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Current Reset Type =
> 0x%x\n", SiScheduleResetHob->ResetType));
> +  if (SiScheduleResetHob->ResetType == ResetType) {
> +    DEBUG ((DEBUG_INFO, "Current Reset Type is same as requested Reset
> Type\n"));
> +    return;
> +  }
> +  if (SiScheduleResetHob->ResetType == 0xFF) {
> +    //
> +    // Init Reset Type to lowest ResetType
> +  //
> +    SiScheduleResetHob->ResetType = EfiResetWarm;
> +  }
> +  //
> +  // ResetType Priority set as : ResetPlatformSpecific(3) > ResetShutdown(2) >
> ResetCold(0) > ResetWarm(1)
> +  //
> +  switch (ResetType) {
> +    case EfiResetWarm:
> +      break;
> +
> +    case EfiResetCold:
> +      if (SiScheduleResetHob->ResetType == EfiResetWarm) {
> +        SiScheduleResetHob->ResetType = ResetType;
> +      }
> +      break;
> +
> +    case EfiResetShutdown:
> +      if (SiScheduleResetHob->ResetType < ResetType)
> +      SiScheduleResetHob->ResetType = ResetType;
> +      break;
> +
> +    case EfiResetPlatformSpecific:
> +      SiScheduleResetHob->ResetType = ResetType;
> +      SiScheduleResetHob->ResetData = *ResetData;
> +      break;
> +  }
> +  DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : New Reset Type =
> 0x%x\n", SiScheduleResetHob->ResetType));
> +}
> +
> +/**
> +  This function returns TRUE or FALSE depending on whether a reset is
> required based on SiScheduleResetHob
> +
> +  @retval     BOOLEAN       The function returns FALSE if no reset is required
> +**/
> +BOOLEAN
> +SiScheduleResetIsRequired (
> +  VOID
> +  )
> +{
> +  VOID                  *HobPtr;
> +
> +  HobPtr = NULL;
> +  HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
> +  if (HobPtr == NULL) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.c
> new file mode 100644
> index 0000000000..15ac61a21b
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleRese
> tLib/BaseSiScheduleResetLibFsp.c
> @@ -0,0 +1,61 @@
> +/** @file
> +  Reset scheduling library services
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Uefi/UefiBaseType.h>
> +#include <Uefi.h>
> +#include <Pi/PiMultiPhase.h>
> +#include <Pi/PiPeiCis.h>
> +#include <Library/PeiServicesTablePointerLib.h>
> +#include <Library/HobLib.h>
> +#include <Private/Library/SiScheduleResetLib.h>
> +#include <Private/SiScheduleResetHob.h>
> +
> +/**
> +  This function returns SiScheduleResetHob for library use
> +**/
> +SI_SCHEDULE_RESET_HOB *
> +SiScheduleGetResetData (
> +  VOID
> +  );
> +
> +/**
> +  This function performs reset based on SiScheduleResetHob
> +
> +  @retval     BOOLEAN       The function returns FALSE if no reset is required
> +**/
> +BOOLEAN
> +SiScheduleResetPerformReset (
> +  VOID
> +  )
> +{
> +  UINTN                 DataSize;
> +  SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
> +
> +  if (!SiScheduleResetIsRequired ()) {
> +    return FALSE;
> +  }
> +  SiScheduleResetHob = SiScheduleGetResetData ();
> +
> +  if (SiScheduleResetHob == NULL) {
> +    return TRUE;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type =
> 0x%x\n", SiScheduleResetHob->ResetType));
> +  if (SiScheduleResetHob->ResetType == EfiResetPlatformSpecific) {
> +    DataSize = sizeof (PCH_RESET_DATA);
> +    (*GetPeiServicesTablePointer ())->ResetSystem2
> (SiScheduleResetHob->ResetType, EFI_SUCCESS, DataSize,
> &SiScheduleResetHob->ResetData);
> +  } else {
> +    (*GetPeiServicesTablePointer ())->ResetSystem2
> (SiScheduleResetHob->ResetType, EFI_SUCCESS, 0, NULL);
> +  }
> +  //
> +  // Code should never reach here
> +  //
> +  ASSERT (FALSE);
> +  return TRUE;
> +}
> --
> 2.16.2.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45983): https://edk2.groups.io/g/devel/message/45983
Mute This Topic: https://groups.io/mt/32918190/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-