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

Kubacki, Michael A michael.a.kubacki at intel.com
Sat Aug 17 00:15:47 UTC 2019


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 at intel.com>
Cc: Chasel Chiu <chasel.chiu at intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
Cc: Liming Gao <liming.gao at intel.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Cc: Ankit Sinha <ankit.sinha at intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki at 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/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list