summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.c313
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.h50
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpiRuntime.inf60
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c249
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h33
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf49
6 files changed, 754 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.c
new file mode 100644
index 0000000000..f2a15ea735
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.c
@@ -0,0 +1,313 @@
+/** @file
+ SC SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScSpi.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+
+///
+/// PchSpiBar0PhysicalAddr keeps the reserved MMIO range assiged to SPI from PEI.
+/// It won't be updated no matter the SPI MMIO is reallocated by BIOS PCI enum.
+/// And it's used to override the SPI BAR0 register in runtime environment,
+///
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchSpiBar0PhysicalAddr;
+
+///
+/// PchSpiBar0VirtualAddr keeps the virtual address of PchSpiBar0PhysicalAddr.
+/// And it's used to provide the SPI BAR0 virtual address mapping to PchSpiBar0PhysicalAddr
+/// in runtime environment.
+///
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchSpiBar0VirtualAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mRuntimeFlag;
+
+//
+// Function implementations
+//
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context. Not used in this event handler.
+
+**/
+VOID
+EFIAPI
+PchSpiVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mRuntimeFlag = TRUE;
+
+ EfiConvertPointer (0x0, (VOID **) &mPchSpiBar0VirtualAddr);
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->PchSpiBase));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashRead));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashWrite));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashErase));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashReadSfdp));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashReadJedecId));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashWriteStatus));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.FlashReadStatus));
+ EfiConvertPointer (0x0, (VOID **) &(mSpiInstance->SpiProtocol.ReadPchSoftStrap));
+ EfiConvertPointer (0x0, (VOID **) &mSpiInstance);
+}
+
+
+/**
+ SPI Runtime DXE Module Entry Point.
+
+ Introduction:
+ The SPI Runtime DXE module provide a standard way for other modules to use the PCH SPI Interface in DXE/Runtime.
+
+ Pre:
+ If SPI Runtime DXE driver is run before Status Code Runtime Protocol is installed
+ and there is the need to use Status code in the driver, it will be necessary
+ to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+
+ Result:
+ The SPI Runtime DXE driver produces SC_SPI_PROTOCOL.
+
+ Integration Check List:
+ This driver supports Descriptor Mode only.
+ This driver supports Hardware Sequence only.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @retval EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallScSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT64 BaseAddress;
+ UINT64 Length;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR SpiPciMemorySpaceDescriptor;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR SpiBar0MemorySpaceDescriptor;
+ UINT64 Attributes;
+ EFI_EVENT AddressChangeEvent;
+
+ DEBUG ((DEBUG_INFO, "InstallScSpi() Start\n"));
+
+ //
+ // Allocate Runtime memory for the SPI protocol instance.
+ //
+ mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPchSpiBar0PhysicalAddr = SC_SPI_BASE_ADDRESS;
+ mPchSpiBar0VirtualAddr = mPchSpiBar0PhysicalAddr;
+
+ //
+ // Install the PCH_SPI_PROTOCOL interface
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mSpiInstance->Handle),
+ &gScSpiProtocolGuid,
+ &(mSpiInstance->SpiProtocol),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Create Address Change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ PchSpiVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &AddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set SPI space in GCD to be RUNTIME so that the range will be supported in
+ // virtual address mode in EFI aware OS runtime.
+ // It will assert if SPI Memory Space is not allocated
+ // The caller is responsible for the existence and allocation of the SPi Memory Spaces
+ //
+ //
+ // SPI memory space
+ //
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) mSpiInstance->PchSpiBase;
+ Length = 0x1000;
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &SpiPciMemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = SpiPciMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // SPI MMIO memory space
+ //
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) mPchSpiBar0PhysicalAddr;
+ Length = 0x1000;
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &SpiBar0MemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = SpiBar0MemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "InstallScSpi() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Acquire SC SPI MMIO address.
+ It is not expected for this BAR0 to change because the SPI device is hidden
+ from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+ but if it is ever different from the preallocated address, reassign it back.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval UINT32 Return SPI MMIO address
+
+**/
+UINT32
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINT32 SpiBar0;
+
+ //
+ // Save original SPI MMIO address
+ //
+ SpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);
+
+ if (SpiBar0 != mPchSpiBar0PhysicalAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ MmioAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiInstance->PchSpiBase + R_SPI_BASE, mPchSpiBar0PhysicalAddr);
+ MmioOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ if (mRuntimeFlag) {
+ return mPchSpiBar0VirtualAddr;
+ } else {
+ return mPchSpiBar0PhysicalAddr;
+ }
+}
+
+
+/**
+ Release SC spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect.
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = mSpiInstance->PchSpiBase;
+ if ((MmioRead8 (SpiBaseAddress + R_SPI_BCR) & B_SPI_BCR_EISS) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Enable the access to the BIOS space for both read and write cycles
+ //
+ MmioOr8 (
+ SpiBaseAddress + R_SPI_BCR,
+ (UINT8) (B_SPI_BCR_BIOSWE)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect.
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = mSpiInstance->PchSpiBase;
+
+ //
+ // Disable the access to the BIOS space for write cycles
+ //
+ MmioAnd8 (
+ SpiBaseAddress + R_SPI_BCR,
+ (UINT8) (~B_SPI_BCR_BIOSWE)
+ );
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.h
new file mode 100644
index 0000000000..ad2cb454ad
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpi.h
@@ -0,0 +1,50 @@
+/** @file
+ Header file for the SC SPI Runtime Driver.
+
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SC_SPI_RT_H_
+#define _SC_SPI_RT_H_
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <ScAccess.h>
+#include <Protocol/Spi.h>
+#include <Library/ScSpiCommonLib.h>
+#include <IndustryStandard/Pci30.h>
+
+//
+// Function prototypes used by the SPI protocol.
+//
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context. Not used in this event handler.
+
+**/
+VOID
+EFIAPI
+PchSpiVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpiRuntime.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpiRuntime.inf
new file mode 100644
index 0000000000..ea8f42a7f3
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/RuntimeDxe/ScSpiRuntime.inf
@@ -0,0 +1,60 @@
+## @file
+# Component description file for SPI Runtime driver.
+#
+# Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ScSpiRuntime
+ FILE_GUID = C194C6EA-B68C-4981-B64B-9BD271474B20
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InstallScSpi
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+
+[Sources]
+ ScSpi.h
+ ScSpi.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesTableLib
+ UefiLib
+ DebugLib
+ MemoryAllocationLib
+ IoLib
+ MmPciLib
+ ScSpiCommonLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid ## UNDEFINED
+
+[Protocols]
+ gScSpiProtocolGuid ## PRODUCES
+
+[Depex]
+ gEfiStatusCodeRuntimeProtocolGuid AND
+ TRUE
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c
new file mode 100644
index 0000000000..1a84f6fb3c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c
@@ -0,0 +1,249 @@
+/** @file
+ SC SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScSpi.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+
+///
+/// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+/// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+/// won't overlap with SMRAM range, and trusted.
+///
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+
+/**
+ SPI Runtime SMM Module Entry Point.
+
+ Introduction:
+ The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+ Pre:
+ EFI_SMM_BASE2_PROTOCOL
+ Documented in System Management Mode Core Interface Specification.
+
+ Result:
+ The SPI SMM driver produces PCH_SPI_PROTOCOL with GUID
+ gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+ Integration Check List:
+ This driver supports Descriptor Mode only.
+ This driver supports Hardware Sequence only.
+ When using SMM SPI Protocol to perform flash access in an SMI handler,
+ and the SMI occurrence is asynchronous to normal mode code execution,
+ proper synchronization mechanism must be applied, e.g. disable SMI before
+ the normal mode SendSpiCmd() starts and re-enable SMI after
+ the normal mode SendSpiCmd() completes.
+ @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+ SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+ not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+ So the synchronization at caller level is likely needed.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @retval EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallScSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = SC_SPI_BASE_ADDRESS;
+
+ //
+ // Allocate pool for SPI protocol instance
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install the SMM SC_SPI_PROTOCOL interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gScSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Acquire SC spi mmio address.
+ It is not expected for this BAR0 to change because the SPI device is hidden
+ from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+ but if it is ever different from the preallocated address, reassign it back.
+ In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 Return SPI MMIO address
+
+**/
+UINT32
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINT32 SpiBar0;
+
+ //
+ // Save original SPI MMIO address
+ //
+ SpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_SPI_BASE) & B_SPI_BASE_BAR;
+
+ if (SpiBar0 != mSpiResvMmioAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ MmioAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiInstance->PchSpiBase + R_SPI_BASE, mSpiResvMmioAddr);
+ MmioOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+
+/**
+ Release SC spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+ UINT32 Data32;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SPI,
+ PCI_FUNCTION_NUMBER_SPI
+ );
+
+ //
+ // Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ // Enable the access to the BIOS space for both read and write cycles
+ //
+ MmioOr8 (
+ SpiBaseAddress + R_SPI_BCR,
+ B_SPI_BCR_BIOSWE
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect.
+
+ @param[in] None
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+ UINT32 Data32;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SPI,
+ PCI_FUNCTION_NUMBER_SPI
+ );
+
+ //
+ // Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ // Disable the access to the BIOS space for write cycles
+ //
+ MmioAnd8 (
+ SpiBaseAddress + R_SPI_BCR,
+ (UINT8) (~N_SPI_BCR_BIOSWE)
+ );
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h
new file mode 100644
index 0000000000..7b27974d06
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h
@@ -0,0 +1,33 @@
+/** @file
+ Header file for the SC SPI SMM Driver.
+
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SC_SPI_SMM_H_
+#define _SC_SPI_SMM_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <ScAccess.h>
+#include <Protocol/Spi.h>
+#include <Library/ScSpiCommonLib.h>
+#include <Library/MmPciLib.h>
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf
new file mode 100644
index 0000000000..9c82067faa
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for SPI SMM driver.
+#
+# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ScSpiSmm
+ FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InstallScSpi
+
+[Sources]
+ ScSpi.h
+ ScSpi.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Silicon/BroxtonSiPkg/BroxtonSiPkg.dec
+ Silicon/BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ BaseLib
+ SmmServicesTableLib
+ ScSpiCommonLib
+ MmPciLib
+
+[Protocols]
+ gScSmmSpiProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
+