From 881e6232de63fbbee19d320706aa7c7527790650 Mon Sep 17 00:00:00 2001 From: lushifex Date: Mon, 13 Feb 2017 10:08:52 +0800 Subject: Add SPI modules. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: lushifex Reviewed-by: David Wei --- .../BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c | 249 +++++++++++++++++++++ .../BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h | 33 +++ .../BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf | 49 ++++ 3 files changed, 331 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm') diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c new file mode 100644 index 0000000000..1a84f6fb3c --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.c @@ -0,0 +1,249 @@ +/** @file + SC SPI SMM Driver implements the SPI Host Controller Compatibility Interface. + + Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "ScSpi.h" + +/// +/// Global variables +/// +GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance; + +/// +/// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI. +/// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range +/// won't overlap with SMRAM range, and trusted. +/// +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr; + +/** + SPI Runtime SMM Module Entry Point. + + Introduction: + The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM. + + Pre: + EFI_SMM_BASE2_PROTOCOL + Documented in System Management Mode Core Interface Specification. + + Result: + The SPI SMM driver produces PCH_SPI_PROTOCOL with GUID + gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver. + + Integration Check List: + This driver supports Descriptor Mode only. + This driver supports Hardware Sequence only. + When using SMM SPI Protocol to perform flash access in an SMI handler, + and the SMI occurrence is asynchronous to normal mode code execution, + proper synchronization mechanism must be applied, e.g. disable SMI before + the normal mode SendSpiCmd() starts and re-enable SMI after + the normal mode SendSpiCmd() completes. + @note The implementation of SendSpiCmd() uses GBL_SMI_EN in + SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may + not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]). + So the synchronization at caller level is likely needed. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_UNSUPPORTED The chipset is unsupported by this driver. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. + +**/ +EFI_STATUS +EFIAPI +InstallScSpi ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Init PCH spi reserved MMIO address. + // + mSpiResvMmioAddr = SC_SPI_BASE_ADDRESS; + + // + // Allocate pool for SPI protocol instance + // + Status = gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof (SPI_INSTANCE), + (VOID **) &mSpiInstance + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mSpiInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE)); + + // + // Initialize the SPI protocol instance + // + Status = SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install the SMM SC_SPI_PROTOCOL interface + // + Status = gSmst->SmmInstallProtocolInterface ( + &(mSpiInstance->Handle), + &gScSmmSpiProtocolGuid, + EFI_NATIVE_INTERFACE, + &(mSpiInstance->SpiProtocol) + ); + if (EFI_ERROR (Status)) { + gSmst->SmmFreePool (mSpiInstance); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Acquire SC spi mmio address. + It is not expected for this BAR0 to change because the SPI device is hidden + from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1), + but if it is ever different from the preallocated address, reassign it back. + In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI. + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval PchSpiBar0 Return SPI MMIO address + +**/ +UINT32 +AcquireSpiBar0 ( + IN SPI_INSTANCE *SpiInstance + ) +{ + UINT32 SpiBar0; + + // + // Save original SPI MMIO address + // + SpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_SPI_BASE) & B_SPI_BASE_BAR; + + if (SpiBar0 != mSpiResvMmioAddr) { + // + // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE. + // + MmioAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE); + MmioWrite32 (SpiInstance->PchSpiBase + R_SPI_BASE, mSpiResvMmioAddr); + MmioOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE); + } + + // + // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg. + // + return mSpiResvMmioAddr; +} + + +/** + Release SC spi mmio address. Do nothing. + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval None + +**/ +VOID +ReleaseSpiBar0 ( + IN SPI_INSTANCE *SpiInstance + ) +{ +} + + +/** + This function is a hook for Spi to disable BIOS Write Protect. + + @param[in] None + + @retval EFI_SUCCESS The protocol instance was properly initialized + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase + +**/ +EFI_STATUS +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + UINTN SpiBaseAddress; + UINT32 Data32; + + SpiBaseAddress = MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_SPI, + PCI_FUNCTION_NUMBER_SPI + ); + + // + // Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b + // Enable the access to the BIOS space for both read and write cycles + // + MmioOr8 ( + SpiBaseAddress + R_SPI_BCR, + B_SPI_BCR_BIOSWE + ); + + return EFI_SUCCESS; +} + + +/** + This function is a hook for Spi to enable BIOS Write Protect. + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + UINTN SpiBaseAddress; + UINT32 Data32; + + SpiBaseAddress = MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_SPI, + PCI_FUNCTION_NUMBER_SPI + ); + + // + // Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b + // Disable the access to the BIOS space for write cycles + // + MmioAnd8 ( + SpiBaseAddress + R_SPI_BCR, + (UINT8) (~N_SPI_BCR_BIOSWE) + ); +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h new file mode 100644 index 0000000000..7b27974d06 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpi.h @@ -0,0 +1,33 @@ +/** @file + Header file for the SC SPI SMM Driver. + + Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SC_SPI_SMM_H_ +#define _SC_SPI_SMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf new file mode 100644 index 0000000000..9c82067faa --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Spi/Smm/ScSpiSmm.inf @@ -0,0 +1,49 @@ +## @file +# Component description file for SPI SMM driver. +# +# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = ScSpiSmm + FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = InstallScSpi + +[Sources] + ScSpi.h + ScSpi.c + +[Packages] + MdePkg/MdePkg.dec + Silicon/BroxtonSiPkg/BroxtonSiPkg.dec + Silicon/BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + DebugLib + IoLib + UefiDriverEntryPoint + UefiBootServicesTableLib + BaseLib + SmmServicesTableLib + ScSpiCommonLib + MmPciLib + +[Protocols] + gScSmmSpiProtocolGuid ## PRODUCES + +[Depex] + TRUE + -- cgit v1.2.3