diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c')
-rw-r--r-- | ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c | 322 |
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) + ); +} |