summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c322
1 files changed, 322 insertions, 0 deletions
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)
+ );
+}