mirror of https://github.com/acidanthera/audk.git
206 lines
5.2 KiB
C
206 lines
5.2 KiB
C
/** @file
|
|
PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
|
|
|
|
Copyright (c) 2013-2015 Intel Corporation.
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
#include "PchSpi.h"
|
|
|
|
extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
SPI_INSTANCE *mSpiInstance;
|
|
CONST UINT32 mSpiRegister[] = {
|
|
R_QNC_RCRB_SPIS,
|
|
R_QNC_RCRB_SPIPREOP,
|
|
R_QNC_RCRB_SPIOPMENU,
|
|
R_QNC_RCRB_SPIOPMENU + 4
|
|
};
|
|
|
|
//
|
|
// Function implementations
|
|
//
|
|
VOID
|
|
PchSpiVirtualddressChangeEvent (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fixup internal data pointers so that the services can be called in virtual mode.
|
|
|
|
Arguments:
|
|
|
|
Event The event registered.
|
|
Context Event context. Not used in this event handler.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
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.Lock));
|
|
gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute));
|
|
gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance));
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InstallPchSpi (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Entry point for the SPI host controller driver.
|
|
|
|
Arguments:
|
|
|
|
ImageHandle Image handle of this driver.
|
|
SystemTable Global system service table.
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS Initialization complete.
|
|
EFI_UNSUPPORTED The chipset is unsupported by this driver.
|
|
EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
|
|
EFI_DEVICE_ERROR Device error, driver exits abnormally.
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 BaseAddress;
|
|
UINT64 Length;
|
|
EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;
|
|
UINT64 Attributes;
|
|
EFI_EVENT Event;
|
|
|
|
DEBUG ((DEBUG_INFO, "InstallPchSpi() Start\n"));
|
|
|
|
//
|
|
// Allocate Runtime memory for the SPI protocol instance.
|
|
//
|
|
mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
|
|
if (mSpiInstance == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
//
|
|
// Initialize the SPI protocol instance
|
|
//
|
|
Status = SpiProtocolConstructor (mSpiInstance);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// 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 = PcdGet64 (PcdRcbaMmioSize);
|
|
|
|
Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
|
|
|
|
Status = gDS->AddMemorySpace (
|
|
EfiGcdMemoryTypeMemoryMappedIo,
|
|
BaseAddress,
|
|
Length,
|
|
EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
|
|
);
|
|
ASSERT_EFI_ERROR(Status);
|
|
|
|
Status = gDS->SetMemorySpaceAttributes (
|
|
BaseAddress,
|
|
Length,
|
|
Attributes
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
PchSpiVirtualddressChangeEvent,
|
|
NULL,
|
|
&gEfiEventVirtualAddressChangeGuid,
|
|
&Event
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
DEBUG ((DEBUG_INFO, "InstallPchSpi() End\n"));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
SpiPhaseInit (
|
|
VOID
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This function is a a hook for Spi Dxe phase specific initialization
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
UINTN Index;
|
|
|
|
//
|
|
// Disable SMM BIOS write protect if it's not a SMM protocol
|
|
//
|
|
MmioAnd8 (
|
|
PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
|
|
PCI_DEVICE_NUMBER_QNC_LPC,
|
|
PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_BIOS_CNTL,
|
|
(UINT8) (~B_QNC_LPC_BIOS_CNTL_SMM_BWP)
|
|
);
|
|
|
|
//
|
|
// Save SPI Registers for S3 resume usage
|
|
//
|
|
for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {
|
|
S3BootScriptSaveMemWrite (
|
|
S3BootScriptWidthUint32,
|
|
(UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),
|
|
1,
|
|
(VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])
|
|
);
|
|
}
|
|
}
|