summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/Spi
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Spi')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif11
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak125
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl92
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c1425
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h300
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c133
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs39
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h74
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif13
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf83
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak99
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl67
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c322
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs39
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h92
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif13
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf91
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak113
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl66
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c244
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs45
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h76
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif13
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf92
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak112
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl66
26 files changed, 3845 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif
new file mode 100644
index 0000000..5b922d8
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "PchSpiCommonLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Common"
+ RefName = "PchSpiCommonLib"
+[files]
+"PchSpiCommonLib.sdl"
+"PchSpiCommonLib.mak"
+"SpiCommon.c"
+"SpiCommon.h"
+<endComponent>
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak
new file mode 100644
index 0000000..b781d72
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak
@@ -0,0 +1,125 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.mak 1 2/08/12 9:22a Yurenlai $
+#
+# $Revision: 1 $
+#
+# $Date: 2/08/12 9:22a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.mak $
+#
+# 1 2/08/12 9:22a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+all : PchSpiCommonLib
+
+PchSpiCommonLib : PchSpiCommonDxeLib PchSpiCommonSmmLib PchSpiCommonPeiLib
+
+$(PchSpiCommonSmmLib_LIB) : PchSpiCommonSmmLib
+$(PchSpiCommonDxeLib_LIB) : PchSpiCommonDxeLib
+$(PchSpiCommonPeiLib_LIB) : PchSpiCommonPeiLib
+
+PchSpiCommonSmmLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibSmmBin
+
+PchSpiCommonDxeLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibDxeBin
+
+PchSpiCommonPeiLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibPeiBin
+
+$(BUILD_DIR)\PchSpiCommonLib.mak : $(PchSpiCommonLib_DIR)\$(@B).cif $(PchSpiCommonLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PchSpiCommonLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PchSpiCommonLib_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+
+PchSpiCommonLibSmm_INCLUDES=\
+ $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES)
+
+PchSpiCommonLibDxe_INCLUDES=\
+ $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES)
+
+PchSpiCommonLibPeim_INCLUDES=\
+ $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES)
+
+PchSpiCommonLib_DEFINES = \
+ $(CFLAGS)
+
+DxeCpuBuildDefine = \
+!IF "$(x64_BUILD)"=="1"
+ /DMDE_CPU_X64\
+!ELSE
+ /DMDE_CPU_IA32\
+!ENDIF
+
+PeimCpuBuildDefine = \
+ /DMDE_CPU_IA32\
+
+PchSpiCommonLibPeim_DEFINES = \
+ $(PchSpiCommonLib_DEFINES)\
+ $(PeimCpuBuildDefine)\
+
+PchSpiCommonLibDxe_DEFINES = \
+ $(PchSpiCommonLib_DEFINES)\
+ $(DxeCpuBuildDefine)\
+
+PchSpiCommonLibSmm_DEFINES = \
+ $(PchSpiCommonLibDxe_DEFINES)\
+
+PchSpiCommonLibDxeBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \
+ /f $(BUILD_DIR)\PchSpiCommonLib.mak all\
+ "MY_INCLUDES=$(PchSpiCommonLibDxe_INCLUDES)" \
+ "CFLAGS=$(PchSpiCommonLibDxe_DEFINES)"\
+ TYPE=LIBRARY \
+ LIBRARY_NAME=$(PchSpiCommonDxeLib_LIB)
+
+PchSpiCommonLibSmmBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \
+ /f $(BUILD_DIR)\PchSpiCommonLib.mak all\
+ "MY_INCLUDES=$(PchSpiCommonLibSmm_INCLUDES)" \
+ "CFLAGS=$(PchSpiCommonLibSmm_DEFINES)"\
+ TYPE=LIBRARY \
+ BUILD_DIR=$(BUILD_DIR)\Smm\
+ LIBRARY_NAME=$(PchSpiCommonSmmLib_LIB)
+
+PchSpiCommonLibPeiBin :
+!IF "$(x64_BUILD)"=="1"
+ $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32 \
+!ELSE
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \
+!ENDIF
+ /f $(BUILD_DIR)\PchSpiCommonLib.mak all\
+ "MY_INCLUDES=$(PchSpiCommonLibPeim_INCLUDES)" \
+ "CFLAGS=$(PchSpiCommonLibPeim_DEFINES)"\
+ TYPE=PEI_LIBRARY \
+ LIBRARY_NAME=$(PchSpiCommonPeiLib_LIB)
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl
new file mode 100644
index 0000000..33582be
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl
@@ -0,0 +1,92 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.sdl 1 2/08/12 9:22a Yurenlai $
+#
+# $Revision: 1 $
+#
+# $Date: 2/08/12 9:22a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.sdl $
+#
+# 1 2/08/12 9:22a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+TOKEN
+ Name = "PchSpiCommonLib_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PchSpiCommonLib support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "PchSpiCommonLib_DIR"
+End
+
+MODULE
+ Help = "Includes PchSpiCommonLib.mak to Project"
+ File = "PchSpiCommonLib.mak"
+End
+
+ELINK
+ Name = "PchSpiCommonDxeLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiCommonDxeLib.lib"
+ Parent = "PchSpiCommonDxeLib_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PchSpiCommonPeiLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiCommonPeiLib.lib"
+ Parent = "PchSpiCommonPeiLib_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PchSpiCommonSmmLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiCommonSmmLib.lib"
+ Parent = "PchSpiCommonSmmLib_LIB"
+ InvokeOrder = AfterParent
+End
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c
new file mode 100644
index 0000000..2797bd9
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c
@@ -0,0 +1,1425 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSpi.h"
+
+/**
+ Initialize an SPI protocol instance.
+ The function will assert in debug if PCH RCBA has not been initialized
+
+ @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 (
+ SPI_INSTANCE *SpiInstance
+ )
+{
+ ///
+ /// Check if the current PCH is known and supported by this code
+ ///
+ if (!IsPchSupported ()) {
+ DEBUG ((EFI_D_ERROR, "PCH SPI Protocol not supported due to no proper PCH LPC found!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.ReadId = SpiProtocolReadId;
+ SpiInstance->SpiProtocol.Init = SpiProtocolInit;
+ SpiInstance->SpiProtocol.Execute = SpiProtocolExecute;
+
+ ///
+ /// Sanity check to ensure PCH RCBA initialization has occurred previously.
+ ///
+ SpiInstance->PchRootComplexBar = PCH_RCRB_BASE;
+ ASSERT (SpiInstance->PchRootComplexBar != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ JEDEC Read IDs from SPI flash part, this function will return 1-byte Vendor ID and 2-byte Device ID
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] Address This value is for determines the command is sent to SPI Component 1 or 2
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Read Jedec Id completed.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @exception EFI_UNSUPPORTED This function is unsupport after SpiProtocolInit is called
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadId (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINTN Address,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+ UINT16 OpcodeType;
+ UINT8 Code;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ if (SpiInstance->SpiIdTable[0].VendorId != 0) {
+ DEBUG ((EFI_D_ERROR, "This function is unsupport after SpiProtocolInit is called, please use SpiProtocolExecute to get Jedec ID!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+ SpiInstance->SpiInitTable.SpiCmdConfig[0].Operation = EnumSpiOperationJedecId;
+ SpiInstance->SpiInitTable.SpiCmdConfig[0].Frequency = EnumSpiCycle50MHz;
+ OpcodeType = (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR);
+ Code = PCH_SPI_COMMAND_READ_ID;
+
+ ///
+ /// Set Opcode Menu Configuration registers.
+ /// Need to be done before sending any SPI command
+ ///
+ MmioWrite8 (PchRootComplexBar + R_PCH_SPI_OPMENU, Code);
+ MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU);
+ ///
+ /// Set Opcode Type Configuration registers.
+ ///
+ MmioWrite16 (PchRootComplexBar + R_PCH_SPI_OPTYPE, OpcodeType);
+ MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE);
+
+ Status = SpiProtocolExecute (
+ This,
+ 0,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ Address,
+ 3,
+ Buffer,
+ EnumSpiRegionAll
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Descriptor values from the Descriptor Region.
+
+ @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands
+
+ @retval None
+**/
+VOID
+EFIAPI
+GetDescriptorValues (
+ IN EFI_SPI_PROTOCOL *This
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ ///
+ /// Select to Flash Map 0 Register to get the number of flash Component
+ ///
+ MmioAndThenOr32 (
+ PchRootComplexBar + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0)
+ );
+
+ ///
+ /// Copy Zero based Number Of Components
+ ///
+ SpiInstance->SpiDescriptor.NumberComponents = (UINT8) ((MmioRead16 (PchRootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC) >> N_PCH_SPI_FDBAR_NC);
+
+ ///
+ /// Select to Flash Components Register to get the Component 1 Density
+ ///
+ MmioAndThenOr32 (
+ PchRootComplexBar + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP)
+ );
+
+ ///
+ /// Copy Component 1 Density
+ ///
+ SpiInstance->SpiDescriptor.Comp1Density = (UINT8) MmioRead32 (PchRootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_FLCOMP_COMP1_MASK;
+}
+
+/**
+ Get VSCC values from the Descriptor Region (VSCC Table).
+
+ @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands
+ @param[in] ReadDataCmdOpcodeIndex The index of the opcode - "PCH_SPI_COMMAND_READ_DATA"
+ @param[in, out] Vscc0Value VSCC0 (Vendor Specific Component Capabilities) Value
+ @param[in, out] Vscc1Value VSCC1 (Vendor Specific Component Capabilities) Value
+
+ @retval EFI_SUCCESS Found the VSCC values on Descriptor Region
+ @retval EFI_NOT_FOUND Couldn't find the VSCC values on Descriptor Region
+ @exception EFI_UNSUPPORTED ReadDataCmdOpcodeIndex is out of range
+**/
+EFI_STATUS
+EFIAPI
+GetDescriptorVsccValues (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 ReadDataCmdOpcodeIndex,
+ IN OUT UINT32 *Vscc0Value,
+ IN OUT UINT32 *Vscc1Value
+ )
+{
+ UINT32 SpiDescFlashUpperMap1;
+ UINT32 VsccTableBaseAddr;
+ UINT32 VsccTableLength;
+ UINT32 JedecIdRegIndex;
+ EFI_STATUS Status;
+ UINT32 FlashDescriptor;
+ SPI_INSTANCE *SpiInstance;
+ BOOLEAN MatchedVtbEntryFound;
+ UINT8 SpiIndex;
+ UINT32 Data32;
+ Data32 = 0;
+
+ if (ReadDataCmdOpcodeIndex >= SPI_NUM_OPCODE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ Status = SpiProtocolExecute (
+ This,
+ ReadDataCmdOpcodeIndex,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) R_PCH_SPI_FLASH_UMAP1,
+ sizeof (SpiDescFlashUpperMap1),
+ (UINT8 *) &SpiDescFlashUpperMap1,
+ EnumSpiRegionDescriptor
+ );
+ if ((EFI_ERROR (Status)) || (SpiDescFlashUpperMap1 == 0xFFFFFFFF)) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// B_PCH_SPI_FLASH_UMAP1_VTBA represents address bits [11:4]
+ ///
+ VsccTableBaseAddr = ((SpiDescFlashUpperMap1 & B_PCH_SPI_FLASH_UMAP1_VTBA) << 4);
+ ///
+ /// Multiplied by 4? B_PCH_SPI_FDBAR_VTL is the 1-based number of DWORDs.
+ ///
+ VsccTableLength = (((SpiDescFlashUpperMap1 & B_PCH_SPI_FLASH_UMAP1_VTL) >> 8) << 2);
+ if (VsccTableLength < SIZE_OF_SPI_VTBA_ENTRY) {
+ ///
+ /// Non-existent or invalid Vscc Table
+ ///
+ return EFI_NOT_FOUND;
+ }
+
+ for (SpiIndex = 0; SpiIndex <= SpiInstance->SpiDescriptor.NumberComponents; SpiIndex++) {
+ JedecIdRegIndex = 0;
+ MatchedVtbEntryFound = FALSE;
+ while (JedecIdRegIndex <= (VsccTableLength - SIZE_OF_SPI_VTBA_ENTRY)) {
+ Status = SpiProtocolExecute (
+ This,
+ ReadDataCmdOpcodeIndex,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) (VsccTableBaseAddr + JedecIdRegIndex),
+ sizeof (UINT32),
+ (UINT8 *) &FlashDescriptor,
+ EnumSpiRegionDescriptor
+ );
+
+ if ((EFI_ERROR (Status)) || (FlashDescriptor == 0xFFFFFFFF)) {
+ break;
+ }
+
+ if (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_VID) != SpiInstance->SpiIdTable[SpiIndex].VendorId) ||
+ (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_DID0) >> N_PCH_SPI_VTBA_JID0_DID0)
+ != SpiInstance->SpiIdTable[SpiIndex].DeviceId0) ||
+ (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_DID1) >> N_PCH_SPI_VTBA_JID0_DID1)
+ != SpiInstance->SpiIdTable[SpiIndex].DeviceId1)) {
+ JedecIdRegIndex += SIZE_OF_SPI_VTBA_ENTRY;
+ } else {
+ MatchedVtbEntryFound = TRUE;
+ break;
+ }
+ }
+
+ if (!MatchedVtbEntryFound) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = SpiProtocolExecute (
+ This,
+ ReadDataCmdOpcodeIndex,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) (VsccTableBaseAddr + JedecIdRegIndex + R_PCH_SPI_VTBA_VSCC0),
+ sizeof (UINT32),
+ (UINT8 *) &Data32,
+ EnumSpiRegionDescriptor
+ );
+ if ((EFI_ERROR (Status)) || (Data32 == 0xFFFFFFFF)) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Copy correct VSCCn value
+ ///
+ if (SpiIndex == 0) {
+ *Vscc0Value = Data32;
+ } else {
+ *Vscc1Value = Data32;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Discover if the flash parts supports 4KB Block/Sector erase size.
+
+ @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands
+
+ @retval EFI_SUCCESS The flash part supports 4KB erase size.
+ @exception EFI_UNSUPPORTED The flash part does not support 4KB erase size.
+**/
+EFI_STATUS
+EFIAPI
+SpiDiscoveryParameters (
+ IN EFI_SPI_PROTOCOL *This
+ )
+{
+ UINT16 ParameterTableIndex;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+ UINT8 SpiIndex;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ ///
+ /// Check if valid SFDP table is present for SPI0
+ ///
+ Data32 = MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0)) & B_PCH_SPI_VSCC0_CPPTV;
+ if (Data32 == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ ///
+ /// Check if valid SFDP table is present for SPI1
+ ///
+ if (SpiInstance->SpiDescriptor.NumberComponents) {
+ Data32 = MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC1)) & B_PCH_SPI_VSCC1_CPPTV;
+ if (Data32 == 0) {
+ ///
+ /// Program VSCCn values from Flash Descriptor or internal BIOS table
+ /// if both parts do not support SFDP
+ ///
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ for (SpiIndex = 0; SpiIndex <= SpiInstance->SpiDescriptor.NumberComponents; SpiIndex++) {
+ ///
+ /// Read Block/Sector Erase Size in 1st dword in the Flash Parameter Table.
+ ///
+ ParameterTableIndex = (SpiIndex << N_PCH_SPI_PINTX_SPT) | (V_PCH_SPI_PINTX_HORD_DATA << N_PCH_SPI_PINTX_HORD);
+ MmioWrite32 (PchRootComplexBar + R_PCH_SPI_PINTX, ParameterTableIndex);
+ Data32 = MmioRead32 (PchRootComplexBar + R_PCH_SPI_PTDATA) & B_PCH_SPI_VSCC0_BSES_MASK;
+
+ ///
+ /// Program VSCCn.EO from Flash Descriptor or internal BIOS table
+ /// if erase size other than 4KB.
+ ///
+ if (Data32 != V_PCH_SPI_VSCC0_BSES_4K) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the host controller to execute SPI command.
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] InitData Initialization data to be programmed into the SPI host controller.
+
+ @retval EFI_SUCCESS Initialization completed.
+ @retval EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down.
+ @retval EFI_INVALID_PARAMETER Bad input parameters.
+ @exception EFI_UNSUPPORTED Can't get Descriptor mode VSCC values
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+ IN EFI_SPI_PROTOCOL *This,
+ IN SPI_INIT_DATA *InitData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT16 OpcodeType;
+ SPI_INSTANCE *SpiInstance;
+ SPI_SPECIAL_OPCODE_ENTRY *SpecialOpcodeEntry;
+ UINT32 Vscc0Value;
+ UINT32 Vscc1Value;
+ UINTN PchRootComplexBar;
+ UINT8 UnlockCmdOpcodeIndex;
+ UINT8 ReadDataCmdOpcodeIndex;
+ UINT8 JedecIdCmdOpcodeIndex;
+ UINT8 Code;
+ UINT8 FlashPartId[3];
+ UINT32 Data32;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+ Vscc0Value = 0;
+ Vscc1Value = 0;
+
+ if (InitData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check if the SPI interface has been locked-down.
+ ///
+ if ((MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FLOCKDN) != 0) {
+ ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
+ return EFI_ACCESS_DENIED;
+ }
+ ///
+ /// Copy Flash Descriptor Values into SPI driver Private data structure
+ ///
+ SpiInstance->DescriptorMode = PchIsSpiDescriptorMode (PchRootComplexBar);
+ if (SpiInstance->DescriptorMode == TRUE) {
+ GetDescriptorValues (This);
+ }
+ ///
+ /// Clear all the status bits for hardware regs.
+ ///
+ MmioOr16 (
+ (UINTN) (PchRootComplexBar + R_PCH_SPI_HSFS),
+ (UINT16) ((B_PCH_SPI_HSFS_AEL | B_PCH_SPI_HSFS_FCERR | B_PCH_SPI_HSFS_FDONE))
+ );
+ MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFS);
+
+ ///
+ /// Clear all the status bits for software regs.
+ ///
+ MmioOr8 (
+ (UINTN) (PchRootComplexBar + R_PCH_SPI_SSFS),
+ (UINT8) ((B_PCH_SPI_SSFS_FCERR | B_PCH_SPI_SSFS_CDS))
+ );
+ MmioRead8 (PchRootComplexBar + R_PCH_SPI_SSFS);
+
+ ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;
+ UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
+ JedecIdCmdOpcodeIndex = SPI_NUM_OPCODE;
+ ///
+ /// Set Opcode Type Configuration registers.
+ /// Need to be done before sending any SPI command
+ ///
+ for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
+ ///
+ /// Copy Operation and Frequency into SPI driver Private data structure
+ ///
+ SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation = InitData->SpiCmdConfig[Index].Operation;
+ SpiInstance->SpiInitTable.SpiCmdConfig[Index].Frequency = InitData->SpiCmdConfig[Index].Frequency;
+
+ switch (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation) {
+ case EnumSpiOperationReadData:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_READ_DATA;
+ ReadDataCmdOpcodeIndex = Index;
+ break;
+
+ case EnumSpiOperationFastRead:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_FAST_READ;
+ ReadDataCmdOpcodeIndex = Index;
+ break;
+
+ case EnumSpiOperationDualOutputFastRead:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_DUAL_FAST_READ;
+ ReadDataCmdOpcodeIndex = Index;
+ break;
+
+ case EnumSpiOperationDiscoveryParameters:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_DISCOVERY_PARAMETERS;
+ break;
+
+ case EnumSpiOperationProgramData_1_Byte:
+ case EnumSpiOperationProgramData_64_Byte:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_PROGRAM_BYTE;
+ break;
+
+ case EnumSpiOperationErase_256_Byte:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_256B_ERASE;
+ break;
+
+ case EnumSpiOperationErase_4K_Byte:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_4KB_ERASE;
+ break;
+
+ case EnumSpiOperationErase_64K_Byte:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_64KB_ERASE;
+ break;
+
+ case EnumSpiOperationWriteStatus:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_WRITE_STATUS;
+ UnlockCmdOpcodeIndex = Index;
+ break;
+
+ case EnumSpiOperationWriteDisable:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_WRITE_DISABLE;
+ break;
+
+ case EnumSpiOperationWriteEnable:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_WRITE_ENABLE;
+ break;
+
+ case EnumSpiOperationEnableWriteStatus:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_ENABLE_WRITE_STATUS;
+ break;
+
+ case EnumSpiOperationFullChipErase:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_FULL_CHIP_ERASE;
+ break;
+
+ case EnumSpiOperationReadStatus:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_READ_STATUS;
+ break;
+
+ case EnumSpiOperationJedecId:
+ OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR << (Index * 2));
+ Code = PCH_SPI_COMMAND_READ_ID;
+ JedecIdCmdOpcodeIndex = Index;
+ break;
+
+ case EnumSpiOperationErase_8K_Byte:
+ case EnumSpiOperationOther:
+ Code = 0;
+ break;
+
+ default:
+ Code = 0;
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Overrided Opcode Type and Menu Configuration registers per SpecialOpcodeEntry
+ ///
+ if (InitData->SpecialOpcodeEntry != NULL) {
+ SpecialOpcodeEntry = InitData->SpecialOpcodeEntry;
+
+ while (SpecialOpcodeEntry->OpcodeIndex != 0xFF) {
+ if (SpecialOpcodeEntry->OpcodeIndex == Index) {
+ OpcodeType &= (UINT16)~(B_PCH_SPI_OPTYPE0_MASK << (Index * 2));
+ OpcodeType |= (UINT16) (SpecialOpcodeEntry->Type << (Index * 2));
+ Code = SpecialOpcodeEntry->Code;
+ }
+
+ SpecialOpcodeEntry++;
+ }
+ }
+ ///
+ /// Set Opcode Menu Configuration registers.
+ /// Need to be done before sending any SPI command
+ ///
+ MmioWrite8 (
+ PchRootComplexBar + R_PCH_SPI_OPMENU + Index,
+ Code
+ );
+ MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU + Index);
+ }
+ ///
+ /// Set Opcode Type Configuration registers.
+ ///
+ MmioWrite16 (PchRootComplexBar + R_PCH_SPI_OPTYPE, OpcodeType);
+ MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE);
+
+ if (JedecIdCmdOpcodeIndex >= SPI_NUM_OPCODE) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Read VendorId/DeviceId from SPI Component 1
+ ///
+ Status = SpiProtocolExecute (
+ This,
+ JedecIdCmdOpcodeIndex,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) 0,
+ 3,
+ FlashPartId,
+ EnumSpiRegionDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Copy VendorId, DeviceId0, DeviceId1 and BiosStartOffset into SPI
+ /// driver Private data structure
+ ///
+ SpiInstance->SpiIdTable[0].VendorId = FlashPartId[0];
+ SpiInstance->SpiIdTable[0].DeviceId0 = FlashPartId[1];
+ SpiInstance->SpiIdTable[0].DeviceId1 = FlashPartId[2];
+ SpiInstance->SpiInitTable.BiosStartOffset = InitData->BiosStartOffset;
+ if (SpiInstance->SpiDescriptor.NumberComponents == 0x01) {
+ ///
+ /// If SPI Descriptor indicates two SPI components then
+ /// read VendorId/DeviceId from SPI Component 2.
+ /// Calculate SPI Component 2 address. The secondary SPI's address is equal to the first SPI's size
+ /// Note: 512KB (BIT19) is the minimum Componenty Density.
+ ///
+ Data32 = (UINT32) (UINTN) (V_PCH_SPI_FLCOMP_COMP_512KB << SpiInstance->SpiDescriptor.Comp1Density);
+ Status = SpiProtocolExecute (
+ This,
+ JedecIdCmdOpcodeIndex,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) Data32,
+ 3,
+ FlashPartId,
+ EnumSpiRegionAll
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Copy VendorId, DeviceId0, DeviceId1 into SPI
+ /// driver Private data structure
+ ///
+ SpiInstance->SpiIdTable[1].VendorId = FlashPartId[0];
+ SpiInstance->SpiIdTable[1].DeviceId0 = FlashPartId[1];
+ SpiInstance->SpiIdTable[1].DeviceId1 = FlashPartId[2];
+ }
+ }
+ ///
+ /// Set the Prefix Opcode registers.
+ ///
+ MmioWrite16 (
+ PchRootComplexBar + R_PCH_SPI_PREOP,
+ (InitData->PrefixOpcode[1] << 8) | InitData->PrefixOpcode[0]
+ );
+ MmioRead16 (PchRootComplexBar + R_PCH_SPI_PREOP);
+
+ ///
+ /// Copy PrefixOpcode into SPI driver Private data structure
+ ///
+ for (Index = 0; Index < SPI_NUM_PREFIX_OPCODE; Index++) {
+ SpiInstance->SpiInitTable.PrefixOpcode[Index] = InitData->PrefixOpcode[Index];
+ }
+ ///
+ /// Copy BiosSize into SPI driver Private data structure
+ ///
+ SpiInstance->SpiInitTable.BiosSize = InitData->BiosSize;
+ }
+ ///
+ /// Get VSCC values from VTBA table in the Descriptor.
+ ///
+ if (SpiInstance->DescriptorMode == TRUE) {
+ Status = GetDescriptorVsccValues (
+ This,
+ ReadDataCmdOpcodeIndex,
+ &Vscc0Value,
+ &Vscc1Value
+ );
+
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Program the VSCC0 & VSCC1 registers by getting the data from SpiInitTable
+ ///
+ for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
+ ///
+ /// For every platform that supports ME, only 4 KB erase is supported
+ /// Get the opcode from SpiInitTable if the operation is 4 KB erase
+ ///
+ if (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation == EnumSpiOperationErase_4K_Byte) {
+ Vscc0Value = Vscc0Value | (UINT32) (V_PCH_SPI_VSCC0_BSES_4K);
+ Vscc0Value = Vscc0Value | (UINT32) (PCH_SPI_COMMAND_4KB_ERASE << 8);
+ } else if (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation == EnumSpiOperationProgramData_64_Byte) {
+ Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WG_64B);
+ }
+ }
+ ///
+ /// Bit WSR and WEWS should NOT be both set to 1, so we check if there is any "Write enable on Write status" prefix opcode
+ /// from SpiInitTable at first, then check "Write Status Enable" prefix opcode
+ ///
+ if ((SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE) ||
+ (SpiInstance->SpiInitTable.PrefixOpcode[1] == PCH_SPI_COMMAND_WRITE_ENABLE)) {
+ Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WEWS);
+ } else if ((SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_STATUS_EN) ||
+ (SpiInstance->SpiInitTable.PrefixOpcode[1] == PCH_SPI_COMMAND_WRITE_STATUS_EN)) {
+ Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WSR);
+ }
+
+ Vscc1Value = Vscc0Value;
+ }
+ ///
+ /// The VCL locks itself when set, it will assert because we have no way to update VSCC value
+ ///
+ if ((MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0)) & B_PCH_SPI_VSCC0_VCL) != 0) {
+ ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
+ return EFI_ACCESS_DENIED;
+ }
+
+ ASSERT (Vscc0Value != 0);
+ MmioWrite32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0), Vscc0Value);
+ if (SpiInstance->SpiDescriptor.NumberComponents) {
+ MmioWrite32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC1), Vscc1Value);
+ }
+ }
+
+ SpiPhaseInit ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Execute SPI commands from the host controller.
+ This function would be called by runtime driver, please do not use any MMIO marco here
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] OpcodeIndex Index of the command in the OpCode Menu.
+ @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ @param[in] DataCycle TRUE if the SPI cycle contains data
+ @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the
+ SPI cycle.
+ @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @exception EFI_UNSUPPORTED Command not supported.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+{
+ EFI_STATUS Status;
+ UINT8 BiosCtlSave;
+ UINT32 Data32;
+ UINT32 PmBase;
+ UINT32 SmiEnSave;
+
+ BiosCtlSave = 0;
+ SmiEnSave = 0;
+
+ ///
+ /// Check if the parameters are valid.
+ ///
+ if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Make sure it's safe to program the command.
+ /// Poll both Hardware Sequencing and Software Sequencing Status
+ ///
+ if (!WaitForSpiCycleComplete (This, TRUE, FALSE)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (!WaitForSpiCycleComplete (This, FALSE, FALSE)) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Acquire access to the SPI interface is not required any more.
+ ///
+ ///
+ /// 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., B0:D31:F0:Offset A0h [4]='1'),
+ /// clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ /// synchronization methods must be applied either here or in the consumer of the
+ /// EFI_SPI_PROTOCOl.Execute(). An example method is disabling the specific SMI sources
+ /// whose SMI handlers access flash before calling Execute() and re-enabling the SMI
+ /// sources after the call.
+ ///
+ PmBase = PciRead32 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_ACPI_BASE)
+ ) & B_PCH_LPC_ACPI_BASE_BAR;
+
+ SmiEnSave = IoRead32 ((UINTN) (PmBase + R_PCH_SMI_EN));
+ Data32 = SmiEnSave &~B_PCH_SMI_EN_GBL_SMI;
+ IoWrite32 ((UINTN) (PmBase + R_PCH_SMI_EN), Data32);
+ ///
+ /// If shifts the data out, disable Prefetching and Caching.
+ ///
+ if (ShiftOut) {
+ BiosCtlSave = PciRead8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL)
+ ) & V_PCH_LPC_BIOS_CNTL_SRC;
+ PciAndThenOr8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (~V_PCH_LPC_BIOS_CNTL_SRC),
+ (UINT8) ((V_PCH_SRC_PREF_DIS_CACHE_DIS))
+ );
+ }
+ ///
+ /// Sends the command to the SPI interface to execute.
+ ///
+ Status = SendSpiCmd (
+ This,
+ OpcodeIndex,
+ PrefixOpcodeIndex,
+ DataCycle,
+ Atomic,
+ ShiftOut,
+ Address,
+ DataByteCount,
+ Buffer,
+ SpiRegionType
+ );
+ ///
+ /// Restore the settings for SPI Prefetching and Caching.
+ ///
+ if (ShiftOut) {
+ PciAndThenOr8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (~V_PCH_LPC_BIOS_CNTL_SRC),
+ (UINT8) (BiosCtlSave)
+ );
+ }
+ ///
+ /// Restore SMIs.
+ ///
+ IoWrite32 ((UINTN) (PmBase + R_PCH_SMI_EN), SmiEnSave);
+
+ return Status;
+}
+
+/**
+ Convert SPI offset to Physical address of SPI hardware
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] SpiRegionOffset In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ @param[in] BaseAddress Base Address of the region.
+ @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+ @param[in, out] HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address)
+ @param[in, out] BaseAddress Return base address of the region type
+ @param[in, out] LimitAddress Return limit address of the region type
+
+ @retval EFI_SUCCESS Command succeed.
+**/
+VOID
+SpiOffset2Physical (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINTN SpiRegionOffset,
+ IN SPI_REGION_TYPE SpiRegionType,
+ OUT UINTN *HardwareSpiAddress,
+ OUT UINTN *BaseAddress,
+ OUT UINTN *LimitAddress
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ if (SpiInstance->DescriptorMode == TRUE) {
+ switch (SpiRegionType) {
+
+ case EnumSpiRegionBios:
+ *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG1_BIOS)
+ & B_PCH_SPI_FREG1_LIMIT_MASK) >> 16) + 1) << 12;
+ *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG1_BIOS)
+ & B_PCH_SPI_FREG1_BASE_MASK) << 12;
+ break;
+
+ case EnumSpiRegionGbE:
+ *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG3_GBE) & B_PCH_SPI_FREG3_BASE_MASK) << 12;
+ *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG3_GBE)
+ & B_PCH_SPI_FREG3_LIMIT_MASK) >> 16) + 1) << 12;
+ break;
+
+ case EnumSpiRegionMe:
+ *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG2_ME) & B_PCH_SPI_FREG2_BASE_MASK) << 12;
+ *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG2_ME)
+ & B_PCH_SPI_FREG2_LIMIT_MASK) >> 16) + 1) << 12;
+ break;
+
+ case EnumSpiRegionDescriptor:
+ *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG0_FLASHD) & B_PCH_SPI_FREG0_BASE_MASK) << 12;
+ *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG0_FLASHD)
+ & B_PCH_SPI_FREG0_LIMIT_MASK) >> 16) + 1) << 12;
+ break;
+
+ case EnumSpiRegionPlatformData:
+ *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG4_PLATFORM_DATA) & B_PCH_SPI_FREG4_BASE_MASK) << 12;
+ *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG4_PLATFORM_DATA)
+ & B_PCH_SPI_FREG4_LIMIT_MASK) >> 16) + 1) << 12;
+ break;
+
+ default:
+ ///
+ /// EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash
+ /// Linear Address)
+ ///
+ *BaseAddress = 0;
+ *LimitAddress = 0;
+ break;
+ }
+
+ *HardwareSpiAddress = SpiRegionOffset +*BaseAddress;
+ } else {
+ if (SpiRegionType == EnumSpiRegionAll) {
+ ///
+ /// EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash
+ /// Linear Address)
+ ///
+ *HardwareSpiAddress = SpiRegionOffset;
+ } else {
+ ///
+ /// Otherwise address is relative to BIOS image
+ ///
+ *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset;
+ }
+ }
+}
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] OpcodeIndex Index of the command in the OpCode Menu.
+ @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ @param[in] DataCycle TRUE if the SPI cycle contains data
+ @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ @param[in, out] Buffer Data received or sent during the SPI cycle.
+ @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+{
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINTN HardwareSpiAddr;
+ UINTN SpiBiosSize;
+ BOOLEAN UseSoftwareSequence;
+ UINTN BaseAddress;
+ UINTN LimitAddress;
+ UINT32 SpiDataCount;
+ UINT8 OpCode;
+ UINT16 OpType;
+ SPI_OPERATION Operation;
+ UINTN PchRootComplexBar;
+ UINT32 SpiSoftFreq;
+ UINT16 FlashCycle;
+ UINT8 BiosCntl;
+ BOOLEAN BiosWriteProtect;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+ SpiBiosSize = SpiInstance->SpiInitTable.BiosSize;
+ Operation = SpiInstance->SpiInitTable.SpiCmdConfig[OpcodeIndex].Operation;
+ OpCode = MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU + OpcodeIndex);
+ OpType = (MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE) >> OpcodeIndex * 2) & (UINT16) (B_PCH_SPI_OPTYPE0_MASK);
+ ///
+ /// Please use PciRead here, it will link to MmioRead
+ /// if the caller is a Runtime driver, please use PchDxeRuntimePciLibPciExpress library, refer
+ /// PciExpressRead() on Library\DxeRuntimePciLibPciExpress\DxeRuntimePciLibPciExpress.c for the details.
+ /// For the rest please use EdkIIGlueBasePciLibPciExpress library
+ ///
+ BiosCntl = PciRead8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL));
+ ///
+ /// Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0 while SpiRegionType is EnumSpiRegionBios.
+ ///
+ if (OpCode == 0 || (SpiBiosSize == 0 && SpiRegionType == EnumSpiRegionBios)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check if need to disable BIOS Write Protect
+ ///
+ if ((Operation == EnumSpiOperationProgramData_1_Byte) ||
+ (Operation == EnumSpiOperationProgramData_64_Byte) ||
+ (Operation == EnumSpiOperationErase_256_Byte) ||
+ (Operation == EnumSpiOperationErase_4K_Byte) ||
+ (Operation == EnumSpiOperationErase_8K_Byte) ||
+ (Operation == EnumSpiOperationErase_64K_Byte) ||
+ (Operation == EnumSpiOperationFullChipErase)) {
+ DisableBiosWriteProtect ();
+ BiosWriteProtect = FALSE;
+ } else {
+ BiosWriteProtect = TRUE;
+ }
+ ///
+ /// Per PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling,
+ /// If SMM_BWP bit (D31:F0:RegDCh[5]) is set, the BIOS Region can only be updated
+ /// by following the steps:
+ /// - Once all threads enter SMM
+ /// - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh. (This is done in
+ /// DisableBiosWriteProtect())
+ ///
+ if (((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) &&
+ (BiosWriteProtect == FALSE) &&
+ ((MmioRead32 ((UINTN) 0xFED30880) & (UINT32) BIT0) == 0)) {
+ EnableBiosWriteProtect ();
+ return EFI_ACCESS_DENIED;
+ }
+ ///
+ /// When current code is read id OR current is not descriptor mode, we will use compatible mode
+ ///
+ UseSoftwareSequence = FALSE;
+ if ((Operation == EnumSpiOperationJedecId) ||
+ (Operation == EnumSpiOperationReadStatus) ||
+ (Operation == EnumSpiOperationWriteStatus) ||
+ (Operation == EnumSpiOperationWriteDisable) ||
+ (Operation == EnumSpiOperationWriteEnable) ||
+ (Operation == EnumSpiOperationEnableWriteStatus) ||
+ (Operation == EnumSpiOperationOther) ||
+ (Operation == EnumSpiOperationDiscoveryParameters) ||
+ (SpiInstance->DescriptorMode == FALSE)
+ ) {
+ UseSoftwareSequence = TRUE;
+ }
+
+ SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
+ ///
+ /// Have direct access to BIOS region in Descriptor mode,
+ ///
+ if (OpType == EnumSpiOpcodeRead && SpiRegionType == EnumSpiRegionBios) {
+ CopyMem (
+ Buffer,
+ (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
+ DataByteCount
+ );
+ return EFI_SUCCESS;
+ }
+ ///
+ /// DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
+ /// LimitAddress));
+ ///
+ if ((DataCycle == FALSE) && (DataByteCount > 0)) {
+ DataByteCount = 0;
+ }
+
+ do {
+ ///
+ /// 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 + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ } else {
+ SpiDataCount = DataByteCount;
+ }
+ ///
+ /// 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 ((SpiInstance->DescriptorMode == FALSE) &&
+ (OpCode == PCH_SPI_COMMAND_PROGRAM_BYTE || Operation == EnumSpiOperationProgramData_1_Byte)) {
+ SpiDataCount = 1;
+ } else if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ ///
+ /// If shifts data out, load data into the SPI data buffer.
+ ///
+ if (ShiftOut) {
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index, Buffer[Index]);
+ MmioRead8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index);
+ }
+ }
+
+ MmioWrite32 (
+ (PchRootComplexBar + R_PCH_SPI_FADDR),
+ (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
+ );
+ MmioRead32 (PchRootComplexBar + R_PCH_SPI_FADDR);
+
+ ///
+ /// Execute the command on the SPI compatible mode
+ ///
+ if (UseSoftwareSequence) {
+ ///
+ /// Software sequencing ...
+ ///
+ ///
+ /// Clear error flags
+ ///
+ MmioWrite16 (PchRootComplexBar + R_PCH_SPI_HSFS, (UINT16) B_PCH_SPI_HSFS_AEL);
+ MmioWrite8 (PchRootComplexBar + R_PCH_SPI_SSFS, (UINT8) B_PCH_SPI_SSFS_FCERR);
+
+ switch (SpiInstance->SpiInitTable.SpiCmdConfig[OpcodeIndex].Frequency) {
+ case EnumSpiCycle20MHz:
+ SpiSoftFreq = V_PCH_SPI_SSFC_SCF_20MHZ;
+ break;
+
+ case EnumSpiCycle33MHz:
+ SpiSoftFreq = V_PCH_SPI_SSFC_SCF_33MHZ;
+ break;
+
+ case EnumSpiCycle50MHz:
+ SpiSoftFreq = V_PCH_SPI_SSFC_SCF_50MHZ;
+ break;
+
+ default:
+ ///
+ /// This is an invalid use of the protocol
+ /// See definition, but caller must call with valid value
+ ///
+ SpiSoftFreq = 0;
+ ASSERT (!EFI_UNSUPPORTED);
+ break;
+ }
+ ///
+ /// PCH Chipset EDS 1.1, Section 22.1.19
+ /// SSFC BIT23:19 are reserved, BIOS must set this field to '11111'b
+ /// To change the offset to the right DWORD boundary, so use offset 0x90 as the operation address
+ ///
+ if (DataCycle) {
+ MmioWrite32 (
+ (PchRootComplexBar + R_PCH_SPI_SSFC - 1),
+ ( (UINT32) (BIT23 | BIT22 | BIT21 | BIT20 | BIT19) |
+ (UINT32) ((SpiSoftFreq << 16) & B_PCH_SPI_SSFC_SCF_MASK) |
+ (UINT32) (B_PCH_SPI_SSFC_DS) | (UINT32) (((SpiDataCount - 1) << 8) & B_PCH_SPI_SSFC_DBC_MASK) |
+ (UINT32) ((OpcodeIndex << 4) & B_PCH_SPI_SSFC_COP) |
+ (UINT32) ((PrefixOpcodeIndex << 3) & B_PCH_SPI_SSFC_SPOP) |
+ (UINT32) (Atomic ? B_PCH_SPI_SSFC_ACS : 0) |
+ (UINT32) (B_PCH_SPI_SSFC_SCGO)) << 8);
+ } else {
+ MmioWrite32 (
+ (PchRootComplexBar + R_PCH_SPI_SSFC - 1),
+ ( (UINT32) (BIT23 | BIT22 | BIT21 | BIT20 | BIT19) |
+ (UINT32) ((SpiSoftFreq << 16) & B_PCH_SPI_SSFC_SCF_MASK) |
+ (UINT32) ((OpcodeIndex << 4) & B_PCH_SPI_SSFC_COP) |
+ (UINT32) ((PrefixOpcodeIndex << 3) & B_PCH_SPI_SSFC_SPOP) |
+ (UINT32) (Atomic ? B_PCH_SPI_SSFC_ACS : 0) |
+ (UINT32) (B_PCH_SPI_SSFC_SCGO)) << 8);
+ }
+
+ MmioRead32 (PchRootComplexBar + R_PCH_SPI_SSFC - 1);
+ } else {
+ ///
+ /// Hardware sequencing ...
+ ///
+ ///
+ /// check for PCH SPI hardware sequencing required commands
+ ///
+ if (Operation == EnumSpiOperationReadData ||
+ Operation == EnumSpiOperationFastRead ||
+ Operation == EnumSpiOperationDualOutputFastRead) {
+ ///
+ /// Read Cycle
+ ///
+ FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_READ << 1);
+ } else if (Operation == EnumSpiOperationProgramData_1_Byte ||
+ Operation == EnumSpiOperationProgramData_64_Byte) {
+ ///
+ /// Write Cycle
+ ///
+ FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_WRITE << 1);
+ } else if (Operation == EnumSpiOperationErase_256_Byte ||
+ Operation == EnumSpiOperationErase_4K_Byte ||
+ Operation == EnumSpiOperationErase_8K_Byte ||
+ Operation == EnumSpiOperationErase_64K_Byte ||
+ Operation == EnumSpiOperationFullChipErase) {
+ ///
+ /// Erase Cycle
+ ///
+ FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_ERASE << 1);
+ } else {
+ ///
+ /// Unrecognized Operation
+ ///
+ ASSERT (FALSE);
+ return EFI_ACCESS_DENIED;
+ }
+ ///
+ /// Clear error flags
+ ///
+ MmioWrite16 (
+ PchRootComplexBar + R_PCH_SPI_HSFS,
+ (UINT16) (B_PCH_SPI_HSFS_AEL | B_PCH_SPI_HSFS_FCERR)
+ );
+ ///
+ /// Send the command
+ ///
+ MmioWrite16 (
+ PchRootComplexBar + R_PCH_SPI_HSFC,
+ (UINT16) (((SpiDataCount - 1) << 8) & B_PCH_SPI_HSFC_FDBC_MASK) |
+ FlashCycle | B_PCH_SPI_HSFC_FCYCLE_FGO
+ );
+ ///
+ /// Read back for posted write to take effect
+ ///
+ MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFC);
+ }
+ ///
+ /// end of command execution
+ ///
+ /// Wait the SPI cycle to complete.
+ ///
+ if (!WaitForSpiCycleComplete (This, UseSoftwareSequence, TRUE)) {
+ if (BiosWriteProtect == FALSE) {
+ ///
+ /// Enable BIOS Write Protect
+ ///
+ EnableBiosWriteProtect ();
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// If shifts data in, get data from the SPI data bufffer.
+ ///
+ if (!ShiftOut) {
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index);
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ DataByteCount -= SpiDataCount;
+ } while (DataByteCount > 0);
+
+ if (BiosWriteProtect == FALSE) {
+ ///
+ /// Enable BIOS Write Protect
+ ///
+ EnableBiosWriteProtect ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface. Check both Hardware
+ and Software Sequencing status registers
+
+ @param[in] This The SPI protocol instance
+ @param[in] UseSoftwareSequence TRUE if Software Sequencing
+ @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.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN EFI_SPI_PROTOCOL *This,
+ IN BOOLEAN UseSoftwareSequence,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 StatusRegAddr;
+ UINT32 CycleInProgressBit;
+ UINT16 AelBit;
+ UINT16 FcErrBit;
+ UINT16 FcycleDone;
+ UINT16 Data16;
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ if (UseSoftwareSequence) {
+ ///
+ /// This is Software Sequencing
+ ///
+ StatusRegAddr = R_PCH_SPI_SSFS;
+ CycleInProgressBit = B_PCH_SPI_SSFS_SCIP;
+ AelBit = B_PCH_SPI_SSFS_AEL;
+ FcErrBit = B_PCH_SPI_SSFS_FCERR;
+ FcycleDone = B_PCH_SPI_SSFS_CDS;
+ } else {
+ ///
+ /// This is Hardware Sequencing
+ ///
+ StatusRegAddr = R_PCH_SPI_HSFS;
+ CycleInProgressBit = B_PCH_SPI_HSFS_SCIP;
+ AelBit = B_PCH_SPI_HSFS_AEL;
+ FcErrBit = B_PCH_SPI_HSFS_FCERR;
+ FcycleDone = B_PCH_SPI_HSFS_FDONE;
+ }
+ ///
+ /// Convert the wait period allowed into to tick count
+ ///
+ WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+ ///
+ /// Wait for the SPI cycle to complete.
+ ///
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data16 = MmioRead16 (PchRootComplexBar + StatusRegAddr);
+ if ((Data16 & CycleInProgressBit) == 0) {
+ if (UseSoftwareSequence){
+ MmioWrite8 (PchRootComplexBar + StatusRegAddr, (UINT8)(AelBit | FcErrBit | FcycleDone));
+ }else{
+ MmioWrite16 (PchRootComplexBar + StatusRegAddr, (AelBit | FcErrBit | FcycleDone));
+ }
+ if (((Data16 & AelBit) || (Data16 & FcErrBit)) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+
+ PchPmTimerStall (WAIT_PERIOD);
+ }
+
+ return FALSE;
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h
new file mode 100644
index 0000000..224ebee
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h
@@ -0,0 +1,300 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef _SPI_COMMON_H_
+#define _SPI_COMMON_H_
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#endif
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
+#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
+//
+// PCH Required SPI Commands -------- COMMAND SET I ------------
+// SPI flash device must support in order to be compatible with PCH
+//
+#define PCH_SPI_COMMAND_WRITE_STATUS 0x01
+#define PCH_SPI_COMMAND_PROGRAM_BYTE 0x02
+#define PCH_SPI_COMMAND_READ_DATA 0x03
+#define PCH_SPI_COMMAND_WRITE_DISABLE 0x04
+#define PCH_SPI_COMMAND_READ_STATUS 0x05
+#define PCH_SPI_COMMAND_WRITE_ENABLE 0x06
+#define PCH_SPI_COMMAND_FAST_READ 0x0B
+#define PCH_SPI_COMMAND_DUAL_FAST_READ 0x3B ///< Dual Output Fast Read
+#define PCH_SPI_COMMAND_ENABLE_WRITE_STATUS 0x50 ///< Enable Write Status Register
+#define PCH_SPI_COMMAND_DISCOVERY_PARAMETERS 0x5A ///< Serial Flash Discovery Parameters
+#define PCH_SPI_COMMAND_READ_ID 0x9F ///< JEDEC Read ID
+#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7 ///< Full Chip Erase
+//
+// Need to support at least one of the following three kinds of size of sector for erasing
+//
+#define PCH_SPI_COMMAND_4KB_ERASE 0x20
+#define PCH_SPI_COMMAND_64KB_ERASE 0xD8
+#define PCH_SPI_COMMAND_256B_ERASE 0xDB
+//
+// ICH8M Recommended SPI Commands -------- COMMAND SET II ------------
+// SPI flash device best to support
+//
+#define PCH_SPI_COMMAND_WRITE_STATUS 0x01
+#define PCH_SPI_COMMAND_WRITE_STATUS_EN 0x50
+#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7
+
+#define SIZE_OF_SPI_VTBA_ENTRY (S_PCH_SPI_VTBA_JID0 + S_PCH_SPI_VTBA_VSCC0)
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+///
+/// Initialization data table loaded to the SPI host controller
+/// PrefixOpcode Prefix opcodes which are loaded into the SPI host controller
+/// SpiCmdConfig Determines Opcode Type, Menu and Frequency of the SPI commands
+/// BiosStartOffset The offset of the start of the BIOS image relative to the flash device.
+/// Please note this is a Flash Linear Address, NOT a memory space address.
+/// This value is platform specific and depends on the system flash map.
+/// This value is only used on non Descriptor mode.
+/// BiosSize The the BIOS Image size in flash. This value is platform specific
+/// and depends on the system flash map. Please note BIOS Image size may
+/// be smaller than BIOS Region size (in Descriptor Mode) or the flash size
+/// (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be
+/// placed at the top end of the BIOS Region (in Descriptor Mode) or the flash
+/// (in Non Descriptor Mode)
+///
+typedef struct _SPI_INIT_TABLE {
+ UINT8 PrefixOpcode[SPI_NUM_PREFIX_OPCODE];
+ SPI_COMMAND_CONFIG SpiCmdConfig[SPI_NUM_OPCODE];
+ UINTN BiosStartOffset;
+ UINTN BiosSize;
+} SPI_INIT_TABLE;
+
+typedef struct _SPI_ID_TABLE {
+ UINT8 VendorId;
+ UINT8 DeviceId0;
+ UINT8 DeviceId1;
+} SPI_ID_TABLE;
+
+typedef struct _SPI_DESCRIPTOR_TABLE {
+ UINT8 NumberComponents :2;
+ UINT8 Comp1Density :4;
+ UINT8 Rsvd :2;
+} SPI_DESCRIPTOR_TABLE;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SPI_PROTOCOL SpiProtocol;
+ SPI_INIT_TABLE SpiInitTable;
+ SPI_ID_TABLE SpiIdTable[2];
+ UINTN PchRootComplexBar;
+ SPI_DESCRIPTOR_TABLE SpiDescriptor;
+ BOOLEAN DescriptorMode;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+ Initialize an SPI protocol instance.
+ The function will assert in debug if PCH RCBA has not been initialized
+
+ @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 (
+ SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ JEDEC Read IDs from SPI flash part, this function will return 1-byte Vendor ID and 2-byte Device ID
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] Address This value is for determines the command is sent to SPI Component 1 or 2
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Read Jedec Id completed.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @exception EFI_UNSUPPORTED This function is unsupport after SpiProtocolInit is called
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadId (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINTN Address,
+ IN OUT UINT8 *Buffer
+ );
+
+/**
+ Initialize the host controller to execute SPI command.
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] InitData Initialization data to be programmed into the SPI host controller.
+
+ @retval EFI_SUCCESS Initialization completed.
+ @retval EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down.
+ @retval EFI_INVALID_PARAMETER Bad input parameters.
+ @exception EFI_UNSUPPORTED Can't get Descriptor mode VSCC values
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+ IN EFI_SPI_PROTOCOL *This,
+ IN SPI_INIT_DATA *InitData
+ );
+
+/**
+ Execute SPI commands from the host controller.
+ This function would be called by runtime driver, please do not use any MMIO marco here
+
+ @param[in] This Pointer to the EFI_SPI_PROTOCOL instance.
+ @param[in] OpcodeIndex Index of the command in the OpCode Menu.
+ @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ @param[in] DataCycle TRUE if the SPI cycle contains data
+ @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the
+ SPI cycle.
+ @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @exception EFI_UNSUPPORTED Command not supported.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ );
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] OpcodeIndex Index of the command in the OpCode Menu.
+ @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ @param[in] DataCycle TRUE if the SPI cycle contains data
+ @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ @param[in, out] Buffer Data received or sent during the SPI cycle.
+ @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ );
+
+/**
+ Wait execution cycle to complete on the SPI interface. Check both Hardware
+ and Software Sequencing status registers
+
+ @param[in] This The SPI protocol instance
+ @param[in] UseSoftwareSequence TRUE if this is a Hardware Sequencing operation
+ @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.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN EFI_SPI_PROTOCOL *This,
+ IN BOOLEAN UseSoftwareSequence,
+ IN BOOLEAN ErrorCheck
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c
new file mode 100644
index 0000000..f5b0062
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c
@@ -0,0 +1,133 @@
+/** @file
+ PCH SPI PEIM implements the SPI Host Controller Compatibility Interface.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSpi.h"
+
+/**
+ Installs PCH SPI PPI
+
+ @param[in] FfsHeader Not used.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS PCH SPI PPI is installed successfully
+ @retval EFI_OUT_OF_RESOURCES Can't allocate pool
+**/
+EFI_STATUS
+InstallPchSpi (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ PEI_SPI_INSTANCE *PeiSpiInstance;
+ SPI_INSTANCE *SpiInstance;
+
+ DEBUG ((EFI_D_INFO, "InstallPchSpi() Start\n"));
+
+ PeiSpiInstance = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_SPI_INSTANCE));
+ if (NULL == PeiSpiInstance) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SpiInstance = &(PeiSpiInstance->SpiInstance);
+ SpiProtocolConstructor (SpiInstance);
+
+ PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PeiSpiInstance->PpiDescriptor.Guid = &gPeiSpiPpiGuid;
+ PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol);
+
+ ///
+ /// Install the SPI PPI
+ ///
+ Status = (**PeiServices).InstallPpi (PeiServices, &PeiSpiInstance->PpiDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "SPI PPI Installed\n"));
+
+ DEBUG ((EFI_D_INFO, "InstallPchSpi() End\n"));
+
+ return Status;
+}
+
+/**
+ This function is a a hook for Spi Pei phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ ///
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ PciOr8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ ///
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ PciAnd8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs
new file mode 100644
index 0000000..a2a2f80
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs
@@ -0,0 +1,39 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "PeimDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h
new file mode 100644
index 0000000..d7be0a2
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h
@@ -0,0 +1,74 @@
+/** @file
+ Header file for the PCH SPI Runtime Driver.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include EFI_PPI_PRODUCER (Spi)
+#include "SpiCommon.h"
+#endif
+
+typedef struct {
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ SPI_INSTANCE SpiInstance;
+} PEI_SPI_INSTANCE;
+
+/**
+ This function is a hook for Spi Pei phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif
new file mode 100644
index 0000000..e6e60c4
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PchSpiPeim"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Pei"
+ RefName = "PchSpiPeim"
+[files]
+"PchSpiPeim.sdl"
+"PchSpiPeim.mak"
+"PchSpi.c"
+"PchSpi.h"
+"PchSpi.dxs"
+"PchSpiPeim.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf
new file mode 100644
index 0000000..44d0485
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf
@@ -0,0 +1,83 @@
+## @file
+# Component description file for the SPI PEIM.
+#
+#@copyright
+# Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PchSpiPeim
+FILE_GUID = AA652CB9-2D52-4624-9FAE-D4E58B67CA46
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ PchSpi.h
+ PchSpi.c
+ ../Common/SpiCommon.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+
+[includes.common]
+ .
+ ../Common
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ $(PROJECT_PCH_FAMILY)PpiLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkIIGluePeiMemoryAllocationLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkPpiLib
+ PchPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PchSpi.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ -D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak
new file mode 100644
index 0000000..5504366
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak
@@ -0,0 +1,99 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.mak 2 2/24/12 2:24a Victortu $
+#
+# $Revision: 2 $
+#
+# $Date: 2/24/12 2:24a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.mak $
+#
+# 2 2/24/12 2:24a Victortu
+# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00.
+#
+# 1 2/08/12 9:23a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+
+#---------------------------------------------------------------------------
+# Create PchSpiPeim Driver
+#---------------------------------------------------------------------------
+EDK : PchSpiPeim
+PchSpiPeim : $(BUILD_DIR)\PchSpiPeim.mak PchSpiPeimBin
+
+
+$(BUILD_DIR)\PchSpiPeim.mak : $(PchSpiPeim_DIR)\$(@B).cif $(PchSpiPeim_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PchSpiPeim_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PchSpiPeim_INCLUDES=\
+ $(PCH_SPI_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+
+PchSpiPeim_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ /D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
+
+PchSpiPeim_LIB_LINKS =\
+ $(PchPlatformPeiLib_LIB)\
+ $(PchSpiCommonPeiLib_LIB)\
+ $(IntelPchPpiLib_LIB)\
+ $(IntelPchPpiLib_BIN)\
+ $(EDKFRAMEWORKGUIDLIB)\
+ $(EdkIIGlueBaseLibIA32_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\
+ $(EdkIIGluePeiReportStatusCodeLib_LIB)\
+ $(EdkIIGluePeiServicesLib_LIB)\
+ $(EdkIIGluePeiMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+
+PchSpiPeimBin: $(PchSpiPeim_LIB_LINKS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PchSpiPeim.mak all\
+ NAME=PchSpiPeim\
+ MAKEFILE=$(BUILD_DIR)\PchSpiPeim.mak \
+ GUID=AA652CB9-2D52-4624-9FAE-D4E58B67CA46\
+ "MY_INCLUDES=$(PchSpiPeim_INCLUDES)"\
+ "MY_DEFINES=$(MY_DEFINES) $(PchSpiPeim_DEFINES)"\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(PchSpiPeim_DIR)\PchSpi.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl
new file mode 100644
index 0000000..526a272
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl
@@ -0,0 +1,67 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.sdl 1 2/08/12 9:23a Yurenlai $
+#
+# $Revision: 1 $
+#
+# $Date: 2/08/12 9:23a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.sdl $
+#
+# 1 2/08/12 9:23a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+TOKEN
+ Name = "PchSpiPeim_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable PchSpiPeim support in Project"
+End
+
+PATH
+ Name = "PchSpiPeim_DIR"
+ Help = "PchSpiPeim file source directory"
+End
+
+MODULE
+ File = "PchSpiPeim.mak"
+ Help = "Includes PchSpiPeim.mak to Project"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiPeim.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c
new file mode 100644
index 0000000..b833b63
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c
@@ -0,0 +1,322 @@
+/** @file
+ PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
+
+@copyright
+ Copyright (c) 2004 - 2015 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSpi.h"
+
+///
+/// Global variables
+///
+SPI_INSTANCE *mSpiInstance;
+EFI_SPI_DATA_PROTOCOL mSpiDataInfoProtocol;
+
+static CONST UINT32 mSpiRegister[] = {
+ R_PCH_SPI_SSFS,
+ R_PCH_SPI_PREOP,
+ R_PCH_SPI_OPMENU,
+ R_PCH_SPI_OPMENU + 4,
+ R_PCH_SPI_VSCC0,
+ R_PCH_SPI_VSCC1
+};
+
+//
+// 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.
+
+ @retval None.
+**/
+EFI_RUNTIMESERVICE
+VOID
+PchSpiVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->PchRootComplexBar));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Init));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiDescriptor));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance));
+}
+
+/**
+ Entry point for the SPI host controller driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT64 BaseAddress;
+ UINT64 Length;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR LpcMemorySpaceDescriptor;
+ UINT64 Attributes;
+
+ DEBUG ((EFI_D_INFO, "InstallPchSpi() Start\n"));
+
+ Status = PciLibConstructor ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// 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;
+ }
+ ///
+ /// Install the EFI_SPI_PROTOCOL interface
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mSpiInstance->Handle),
+ &gEfiSpiProtocolGuid,
+ &(mSpiInstance->SpiProtocol),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Set RCBA 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 RCBA Memory Space is not allocated
+ /// The caller is responsible for the existence and allocation of the RCBA Memory Spaces
+ ///
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar);
+ Length = 0x4000;
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// LPC memory space
+ ///
+ BaseAddress = MmPciAddress(0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ Length = 4096;
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &LpcMemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = LpcMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PciLibRegisterMemory (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0),
+ (UINTN) Length
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "InstallPchSpi() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save SPI VSCC0/VSCC1 register into S3 resume script table.
+
+ @param[in] Event The event that triggered this notification function
+ @param[in] ParentImageHandle Pointer to the notification functions context
+**/
+VOID
+EFIAPI
+VsccS3SaveRestore (
+ IN EFI_EVENT Event,
+ IN VOID *ParentImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave;
+ UINTN Index;
+
+ ///
+ /// Check whether this is real BootScriptSave notification, or just a SignalEvent
+ ///
+ Status = gBS->LocateProtocol (&gEfiBootScriptSaveGuid, NULL, (VOID **) &BootScriptSave);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ ///
+ /// Closed the event to avoid call twice when launch shell
+ ///
+ gBS->CloseEvent (Event);
+
+ ///
+ /// Save SPI Registers for S3 resume usage
+ ///
+ INITIALIZE_SCRIPT (ParentImageHandle, gST);
+
+ for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),
+ 1,
+ (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])
+ );
+ }
+
+ return;
+}
+
+/**
+ This function is a hook for Spi Dxe phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+{
+ VOID *Registration;
+ EFI_STATUS Status;
+
+ ///
+ /// Create event for the SPI flash VSCC registers S3 save/restore.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiBootScriptSaveGuid,
+ TPL_CALLBACK,
+ VsccS3SaveRestore,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Initialize and Install the SPI Data protocol
+ ///
+ mSpiDataInfoProtocol.BiosSize = mSpiInstance->SpiInitTable.BiosSize;
+ mSpiDataInfoProtocol.BiosStartMemoryAddress = SIZE_4GB - mSpiDataInfoProtocol.BiosSize;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mSpiInstance->Handle),
+ &gEfiSpiDataProtocolGuid,
+ &mSpiDataInfoProtocol,
+ NULL
+ );
+ if (EFI_ERROR(Status))
+ {
+ ASSERT(FALSE);
+ }
+
+ return;
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ ///
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ PciOr8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ ///
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ PciAnd8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs
new file mode 100644
index 0000000..7a9a510
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs
@@ -0,0 +1,39 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h
new file mode 100644
index 0000000..aaee7fb
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h
@@ -0,0 +1,92 @@
+/** @file
+ Header file for the PCH SPI Runtime Driver.
+
+@copyright
+ Copyright (c) 2004 - 2015 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include EFI_PROTOCOL_PRODUCER (Spi)
+#include "SpiCommon.h"
+#include "DxeRuntimePciLibPciExpress.h"
+#include "EfiScriptLib.h"
+#include EFI_PROTOCOL_CONSUMER (BootScriptSave)
+#endif
+
+#define SIZE_4GB 0x0000000100000000ULL
+
+//
+// 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.
+
+ @retval None.
+**/
+VOID
+PchSpiVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ This function is a hook for Spi Dxe phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif
new file mode 100644
index 0000000..f721bd8
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PchSpiRuntime"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\RuntimeDxe"
+ RefName = "PchSpiRuntime"
+[files]
+"PchSpiRuntime.sdl"
+"PchSpiRuntime.mak"
+"PchSpi.c"
+"PchSpi.h"
+"PchSpi.dxs"
+"PchSpiRuntime.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf
new file mode 100644
index 0000000..cd4ced8
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf
@@ -0,0 +1,91 @@
+## @file
+# Component description file for the SPI Runtime driver.
+#
+#@copyright
+# Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PchSpiRuntime
+FILE_GUID = C194C6EA-B68C-4981-B64B-9BD271474B20
+COMPONENT_TYPE = RT_DRIVER
+
+[sources.common]
+ PchSpi.h
+ PchSpi.c
+ ../Common/SpiCommon.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+
+[includes.common]
+ .
+ ../Common
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library
+
+[libraries.common]
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueEdkDxeRuntimeDriverLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeServicesTableLib
+ EdkProtocolLib
+ $(PROJECT_PCH_FAMILY)ProtocolLib
+ PchDxeRuntimePciLibPciExpress
+ PchPlatformLib
+ EfiScriptLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PchSpi.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_SET_VIRTUAL_ADDRESS_MAP_EVENT_HANDLER__=PchSpiVirtualAddressChangeEvent
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_EDK_DXE_RUNTIME_DRIVER_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ No newline at end of file
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak
new file mode 100644
index 0000000..39646e9
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak
@@ -0,0 +1,113 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.mak 2 2/24/12 2:27a Victortu $
+#
+# $Revision: 2 $
+#
+# $Date: 2/24/12 2:27a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.mak $
+#
+# 2 2/24/12 2:27a Victortu
+# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00.
+#
+# 1 2/08/12 9:26a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+
+#---------------------------------------------------------------------------
+# Create PchSpiRuntime Driver
+#---------------------------------------------------------------------------
+EDK : PchSpiRuntime
+PchSpiRuntime : $(BUILD_DIR)\PchSpiRuntime.mak PchSpiRuntimeBin
+
+
+$(BUILD_DIR)\PchSpiRuntime.mak : $(PchSpiRuntime_DIR)\$(@B).cif $(PchSpiRuntime_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PchSpiRuntime_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PchSpiRuntime_INCLUDES=\
+ $(INTEL_PCH_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(EDK_INCLUDES)\
+ $(PCH_SPI_INCLUDES)\
+
+PchSpiRuntime_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\
+ /D "__EDKII_GLUE_SET_VIRTUAL_ADDRESS_MAP_EVENT_HANDLER__=PchSpiVirtualAddressChangeEvent"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_EDK_DXE_RUNTIME_DRIVER_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+
+
+PchSpiRuntime_LIB_LINKS =\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueEdkDxeRuntimeDriverLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EDKPROTOCOLLIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(DxeRuntimePciLibPciExpressLib_LIB)\
+ $(PchPlatformDxeLib_LIB)\
+ $(EFISCRIPTLIB)\
+ $(PchSpiCommonDxeLib_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+
+PchSpiRuntimeBin: $(PchSpiRuntime_LIB_LINKS)
+ $(ECHO) DEPENDENCY_START > $(BUILD_DIR)\Fake.dxs
+ $(ECHO) FALSE >> $(BUILD_DIR)\Fake.dxs
+ $(ECHO) DEPENDENCY_END >> $(BUILD_DIR)\Fake.dxs
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PchSpiRuntime.mak all \
+ "MY_INCLUDES=$(PchSpiRuntime_INCLUDES)"\
+ "MY_DEFINES=$(PchSpiRuntime_DEFINES)"\
+ GUID=C194C6EA-B68C-4981-B64B-9BD271474B20\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER\
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(BUILD_DIR)\Fake.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl
new file mode 100644
index 0000000..02546b0
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl
@@ -0,0 +1,66 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.sdl 1 2/08/12 9:25a Yurenlai $
+#
+# $Revision: 1 $
+#
+# $Date: 2/08/12 9:25a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.sdl $
+#
+# 1 2/08/12 9:25a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+TOKEN
+ Name = "PchSpiRuntime_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PchSpiRuntime support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "PchSpiRuntime_DIR"
+End
+
+MODULE
+ File = "PchSpiRuntime.mak"
+ Help = "Includes PchSpiRuntime to Project"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiRuntime.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c
new file mode 100644
index 0000000..9c041ad
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c
@@ -0,0 +1,244 @@
+/** @file
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSpi.h"
+
+//
+// Global variables
+//
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+EFI_SMM_SYSTEM_TABLE *mSmst;
+SPI_INSTANCE *mSpiInstance;
+
+/**
+ Entry point for the SPI host controller driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Locate SMM Base Protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize our module variables
+ ///
+ Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Allocate pool for SPI protocol instance
+ ///
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, /// MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Install the SMM EFI_SPI_PROTOCOL interface
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mSpiInstance->Handle),
+ &gEfiSmmSpiProtocolGuid,
+ &(mSpiInstance->SpiProtocol),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ mSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a a hook for Spi Smm phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+{
+ UINTN Index;
+ static CONST UINT32 SpiRegister[] = {
+ R_PCH_SPI_SSFS,
+ R_PCH_SPI_PREOP,
+ R_PCH_SPI_OPMENU,
+ R_PCH_SPI_OPMENU + 4,
+ R_PCH_SPI_VSCC0,
+ R_PCH_SPI_VSCC1
+ };
+
+ ///
+ /// Save SPI Registers for S3 resume usage
+ ///
+ for (Index = 0; Index < sizeof (SpiRegister) / sizeof (UINT32); Index++) {
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index]),
+ 1,
+ (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index])
+ );
+ }
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT8 Data8;
+ UINT32 Data32;
+
+ ///
+ /// Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b
+ ///
+ PciOr8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 3.7 BIOS Region SMM Protection Enabling
+ /// If the following steps are implemented:
+ /// - Set the SMM_BWP bit (B0:D31:F0 Offset DCh [5]) = 1b
+ /// - Follow the 1st recommendation in section 3.6
+ /// the BIOS Region can only be updated by following the steps bellow:
+ /// - Once all threads enter SMM
+ /// - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ /// - Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b
+ /// - Modify BIOS Region
+ /// - Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b
+ /// - Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data8 = PciRead8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL)
+ );
+ ///
+ /// Check if SMM_BWP bit is set
+ ///
+ if ((Data8 & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {
+ ///
+ /// Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0);
+ AsmWriteMsr32 (0x1FE, Data32);
+ }
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT8 Data8;
+ UINT32 Data32;
+
+ ///
+ /// Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b
+ ///
+ PciAnd8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL),
+ (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE)
+ );
+
+ Data8 = PciRead8 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_BIOS_CNTL)
+ );
+ ///
+ /// Check if SMM_BWP bit is set
+ ///
+ if ((Data8 & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {
+ ///
+ /// Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0);
+ AsmWriteMsr32 (0x1FE, Data32);
+ }
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs
new file mode 100644
index 0000000..0f2e9b0
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs
@@ -0,0 +1,45 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+#include EFI_PROTOCOL_DEFINITION (BootScriptSave)
+#include EFI_PROTOCOL_DEFINITION (Pfat)
+#endif
+
+DEPENDENCY_START
+#ifdef EFI_S3_RESUME
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND
+#endif
+ EFI_SMM_BASE_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h
new file mode 100644
index 0000000..1f9244e
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h
@@ -0,0 +1,76 @@
+/** @file
+ Header file for the PCH SPI SMM Driver.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include EFI_PROTOCOL_PRODUCER (Spi)
+#include "SpiCommon.h"
+#include "EfiScriptLib.h"
+
+//
+// Driver Dependency Protocols
+//
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_CONSUMER (BootScriptSave)
+#endif
+
+/**
+ This function is a a hook for Spi Smm phase specific initialization
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif
new file mode 100644
index 0000000..8ae77f5
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PchSpiSmm"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Smm"
+ RefName = "PchSpiSmm"
+[files]
+"PchSpiSmm.sdl"
+"PchSpiSmm.mak"
+"PchSpi.c"
+"PchSpi.h"
+"PchSpi.dxs"
+"PchSpiSmm.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf
new file mode 100644
index 0000000..5fe34a2
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf
@@ -0,0 +1,92 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+#@copyright
+# Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PchSpiSmm
+FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ PchSpi.h
+ PchSpi.c
+ ../Common/SpiCommon.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+
+[includes.common]
+ .
+ ../Common
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+ $(PROJECT_PCH_FAMILY)ProtocolLib
+ PchPlatformLib
+ EfiScriptLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PchSpi.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak
new file mode 100644
index 0000000..9b15d4d
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak
@@ -0,0 +1,112 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.mak 3 9/26/12 3:40a Victortu $
+#
+# $Revision: 3 $
+#
+# $Date: 9/26/12 3:40a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.mak $
+#
+# 3 9/26/12 3:40a Victortu
+# Lynx Point PCH Chipset Framework Reference Code Beta 0.7.0
+#
+# 2 2/24/12 2:26a Victortu
+# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00.
+#
+# 1 2/08/12 9:24a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+
+#---------------------------------------------------------------------------
+# Create PchSpi SMM Driver
+#---------------------------------------------------------------------------
+EDK : PchSpiSmm
+PchSpiSmm : $(BUILD_DIR)\PchSpiSmm.mak PchSpiSmmBin
+
+
+$(BUILD_DIR)\PchSpiSmm.mak : $(PchSpiSmm_DIR)\$(@B).cif $(PchSpiSmm_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PchSpiSmm_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PchSpiSmm_INCLUDES=\
+ $(INTEL_PCH_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(PCH_SPI_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+
+PchSpiSmm_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+
+PchSpiSmm_LIB_LINKS =\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiDevicePathLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(PchPlatformSmmLib_LIB)\
+ $(PchSpiCommonSmmLib_LIB)\
+ $(EFISCRIPTLIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+
+PchSpiSmmBin: $(PchSpiSmm_LIB_LINKS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PchSpiSmm.mak all \
+ "MY_INCLUDES=$(PchSpiSmm_INCLUDES)"\
+ "MY_DEFINES=$(PchSpiSmm_DEFINES)"\
+ GUID=27F4917B-A707-4aad-9676-26DF168CBF0D\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER\
+ EDKIIModule=SMMDRIVER\
+ DEPEX1=$(PchSpiSmm_DIR)\PchSpi.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl
new file mode 100644
index 0000000..5310706
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl
@@ -0,0 +1,66 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.sdl 1 2/08/12 9:24a Yurenlai $
+#
+# $Revision: 1 $
+#
+# $Date: 2/08/12 9:24a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.sdl $
+#
+# 1 2/08/12 9:24a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+TOKEN
+ Name = "PchSpiSmm_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PchSpi SMM support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "PchSpiSmm_DIR"
+End
+
+MODULE
+ File = "PchSpiSmm.mak"
+ Help = "Includes PchSpi to Project"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSpiSmm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************