alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/PciPlatformDxe/PciPlatform.c

488 lines
18 KiB
C

/** @file
PciPlatformDxe driver will produces the PciPlatform Protocol for Dxe driver.
;******************************************************************************
;* Copyright (c) 2018 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Protocol/PciPlatform.h>
#include <Protocol/PlatformPhaseNotify.h>
#include <Protocol/PciEnumerationComplete.h>
#include <IrqRoutingInformation.h>
#include <ChipsetAccess.h>
//#include <Library/PchPlatformLib.h>
#include <Library/PchPcrLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/MmPciLib.h>
#include <Library/TbtCommonLib.h>
#include <Library/UefiLib.h>
#include <ITbtInfoHob.h>
#include <Protocol/ITbtNvsArea.h>
#include <Protocol/DTbtNvsArea.h>
#include <SetupVariable.h>
#include <Library/HobLib.h>
//[-start-200420-IB17800056-remove]//
//#include <DTbtInfoHob.h>
//[-end-200420-IB17800056-remove]//
#include <Register/PchPcieRpRegs.h>
// no this file in ClientOneSilicon path >>
// #include <Register/PchRegsPcr.h>
// no this file in ClientOneSilicon path <<
#include <Register/PchRegsLpc.h>
#include <Library/PchPcrLib.h>
// need PID_SPA and PID_SPB define >>
#include <Register/PchPcrRegs.h>
// need PID_SPA and PID_SPB define <<
#include <PchBdfAssignment.h>
#include <Register/PchRegsSmbus.h>
#include <Library/PchPciBdfLib.h>
#include <Library/S3BootScriptLib.h>
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN ITbtSmiDone = FALSE;
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN DTbtSmiDone = FALSE;
EFI_STATUS
PlatformNotify (
IN EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE HostBridge,
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
);
EFI_STATUS
PlatformPrepController (
IN EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE HostBridge,
IN EFI_HANDLE RootBridge,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
);
EFI_STATUS
GetPlatformPolicy (
IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
);
EFI_STATUS
GetPciRom (
IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE PciHandle,
OUT VOID **RomImage,
OUT UINTN *RomSize
);
STATIC
VOID
EFIAPI
PciEnumCompletedNotifyFunction (
IN EFI_EVENT Event,
IN VOID *Context
);
EFI_HANDLE mPciPlatformHandle = NULL;
EFI_PCI_PLATFORM_PROTOCOL mPciPlatform = {
PlatformNotify,
PlatformPrepController,
GetPlatformPolicy,
GetPciRom
};
EFI_STATUS
EFIAPI
PciPlatformDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT Event;
VOID *Registration;
//
// Registers the gEfiPciEnumerationCompleteProtocolGuid protocol notification for PCIe port switching
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
PciEnumCompletedNotifyFunction,
NULL,
&Event
);
if (Status == EFI_SUCCESS) {
Status = gBS->RegisterProtocolNotify (
&gEfiPciEnumerationCompleteProtocolGuid,
Event,
&Registration
);
}
Status = gBS->InstallProtocolInterface (
&mPciPlatformHandle,
&gEfiPciPlatformProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPciPlatform
);
return Status;
}
EFI_STATUS
PlatformNotify (
IN EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE HostBridge,
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
IN EFI_PCI_CHIPSET_EXECUTION_PHASE ExecPhase
)
{
ITBT_NVS_AREA_PROTOCOL *ITbtNvsAreaProtocol;
//[-start-200420-IB17800056-remove]//
// DTBT_NVS_AREA_PROTOCOL *DTbtNvsAreaProtocol;
//[-end-200420-IB17800056-remove]//
UINTN DataSize;
SETUP_DATA SetupData;
UINT8 RootPortSelected;
//[-start-200420-IB17800056-remove]//
// DTBT_INFO_HOB *gDTbtInfoHob = NULL;
//[-end-200420-IB17800056-remove]//
EFI_STATUS Status;
UINT32 BaseAddress;
UINT64 BootScriptPciAddress;
if ( ( Phase == EfiPciHostBridgeEndResourceAllocation ) && ( ExecPhase == ChipsetExit ) ) {
DataSize = sizeof (SETUP_DATA);
Status = gRT->GetVariable (
L"Setup",
&gSetupVariableGuid,
NULL,
&DataSize,
&SetupData
);
if (!EFI_ERROR(Status) && (SetupData.IntegratedTbtSupport)) {
Status = gBS->LocateProtocol (&gITbtNvsAreaProtocolGuid, NULL, (VOID **) &ITbtNvsAreaProtocol);
if (!EFI_ERROR(Status)) {
// ITbtNvsAreaProtocol->Area->ThunderboltHotSmi = SetupData.TBTHotSMI;
// ITbtNvsAreaProtocol->Area->ThunderboltHotNotify = SetupData.TBTHotNotify;
if (!ITbtSmiDone) {
//
// As Root Port will be up always , need to enumerate the devices irresepctive of
// Booton support
//
for(RootPortSelected = 0; RootPortSelected < MAX_ITBT_PCIE_PORT; RootPortSelected++) {
if(SetupData.ITbtRootPort[RootPortSelected] == 1) {
ITbtNvsAreaProtocol->Area->CurrentIntegratedTbtRootPort = RootPortSelected + 1;
ITbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 22;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiITbtEnumerate));
ITbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 21;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiITbtEnumerate));
}
}
ITbtNvsAreaProtocol->Area->CurrentIntegratedTbtRootPort = 0;
}
ITbtSmiDone = TRUE;
}
}
//[-start-200420-IB17800056-remove]//
#if 0
if (!EFI_ERROR(Status) && (SetupData.DiscreteTbtSupport)) {
Status = gBS->LocateProtocol (&gDTbtNvsAreaProtocolGuid, NULL, (VOID **) &DTbtNvsAreaProtocol);
if (!EFI_ERROR(Status)) {
DTbtNvsAreaProtocol->Area->ThunderboltHotSmi = SetupData.TBTHotSMI;
DTbtNvsAreaProtocol->Area->ThunderboltHotNotify = SetupData.TBTHotNotify;
Status = EfiGetSystemConfigurationTable(&gEfiHobListGuid, (VOID **)&gDTbtInfoHob);
if (!EFI_ERROR(Status)) {
DEBUG((DEBUG_INFO, "Searching Thunderbolt(TM) information Hob... \n"));
gDTbtInfoHob = GetNextGuidHob(&gDTbtInfoHobGuid, gDTbtInfoHob);
if (gDTbtInfoHob != NULL) {
DEBUG((DEBUG_INFO, "Thunderbolt(TM) information Hob is Not NULL \n"));
if (SetupData.DiscreteTbtSupport == 1) {
if (!DTbtSmiDone) {
for (RootPortSelected = 0; RootPortSelected < MAX_DTBT_CONTROLLER_NUMBER; RootPortSelected++) {
if (gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].DTbtControllerEn == 0x01) {
DTbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPort = gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].PcieRpNumber;
DTbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPortType = gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].Type;
DEBUG((DEBUG_INFO, "Triggering Tbt Sw SMI"));
DTbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 22;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiDTbtEnumerate));
DTbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 21;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiDTbtEnumerate));
}
}
DTbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPort = 0;
DTbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPortType = 0;
}
DTbtSmiDone = TRUE;
}
}
}
}
}
if (!EFI_ERROR(Status) && (SetupData.DiscreteTbtSupport
|| SetupData.IntegratedTbtSupport
)) {
Status = gBS->LocateProtocol (&gITbtNvsAreaProtocolGuid, NULL, (VOID **) &ITbtNvsAreaProtocol);
ASSERT_EFI_ERROR (Status);
ITbtNvsAreaProtocol->Area->ThunderboltHotSmi = SetupData.TBTHotSMI;
ITbtNvsAreaProtocol->Area->ThunderboltHotNotify = SetupData.TBTHotNotify;
Status = EfiGetSystemConfigurationTable(&gEfiHobListGuid, (VOID **)&gDTbtInfoHob);
if (!EFI_ERROR(Status)) {
DEBUG((DEBUG_INFO, "Searching Thunderbolt(TM) information Hob... \n"));
gDTbtInfoHob = GetNextGuidHob(&gDTbtInfoHobGuid, gDTbtInfoHob);
if (gDTbtInfoHob != NULL) {
DEBUG((DEBUG_INFO, "Thunderbolt(TM) information Hob is Not NULL \n"));
if (SetupData.DiscreteTbtSupport == 1) {
if (!TbtSmiDone) {
for (RootPortSelected = 0; RootPortSelected < MAX_DTBT_CONTROLLER_NUMBER; RootPortSelected++) {
if (gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].DTbtControllerEn == 0x01) {
ITbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPort = gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].PcieRpNumber;
ITbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPortType = gDTbtInfoHob->DTbtControllerConfig[RootPortSelected].Type;
DEBUG((DEBUG_INFO, "Triggering Tbt Sw SMI"));
// TbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 22;
// IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiDTbtEnumerate));
ITbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 21;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiDTbtEnumerate));
}
}
ITbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPort = 0;
ITbtNvsAreaProtocol->Area->CurrentDiscreteTbtRootPortType = 0;
}
}
else {
if (!TbtSmiDone) {
//
// As Root Port will be up always , need to enumerate the devices irresepctive of
// Booton support
//
for(RootPortSelected = 0; RootPortSelected < MAX_ITBT_PCIE_PORT; RootPortSelected++) {
if(SetupData.ITbtRootPort[RootPortSelected] == 1) {
ITbtNvsAreaProtocol->Area->CurrentIntegratedTbtRootPort = RootPortSelected + 1;
// TbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 22;
// IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiITbtEnumerate));
ITbtNvsAreaProtocol->Area->ThunderboltSmiFunction = 21;
IoWrite8(R_PCH_IO_APM_CNT, PcdGet8 (PcdSwSmiITbtEnumerate));
}
}
ITbtNvsAreaProtocol->Area->CurrentIntegratedTbtRootPort = 0;
}
}
}
}
}
TbtSmiDone = TRUE;
#endif
//[-end-200420-IB17800056-remove]//
Status = gBS->InstallProtocolInterface (
&mPciPlatformHandle,
&gEfiPciHostBridgeEndResourceAllocationNotifyGuid,
EFI_NATIVE_INTERFACE,
NULL
);
return Status;
//
// For DGR function that allows access right in SMM mode.
//
if (Phase == EfiPciHostBridgeEndResourceAllocation) {
BaseAddress = PcdGet16 (PcdSmbusBaseAddress); // 0xEFA0
PciSegmentWrite32 (
SmbusPciCfgBase () + R_SMBUS_CFG_BASE,
(UINT32)BaseAddress
);
DEBUG((DEBUG_INFO, "Set SmBus CFG Base to 0x%08x.\n", PcdGet16 (PcdSmbusBaseAddress)));
BootScriptPciAddress = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_SMBUS_CFG_BASE);
S3BootScriptSavePciCfgWrite (
S3BootScriptWidthUint32,
BootScriptPciAddress,
1,
&BaseAddress
);
}
return EFI_SUCCESS;
}
/**
GC_TODO: Add function description
@param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
@param HostBridge The associated PCI host bridge handle.
@param RootBridge The associated PCI root bridge handle.
@param PciAddress The address of the PCI device on the PCI bus.
@param Phase The phase of the PCI controller enumeration.
@param ChipsetPhase Defines the execution phase of the PCI chipset driver.
@retval EFI_UNSUPPORTED
EFI_SUCCESS
**/
EFI_STATUS
PlatformPrepController (
IN EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE HostBridge,
IN EFI_HANDLE RootBridge,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
)
{
//
// If there is any code in this function, Default Status must be EFI_SUCCESS
//
EFI_STATUS Status = EFI_INVALID_PARAMETER;
return Status;
}
EFI_STATUS
GetPlatformPolicy (
IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
)
{
*PciPolicy &= ~EFI_RESERVE_VGA_IO_ALIAS;
return EFI_SUCCESS;
}
/**
Return a PCI ROM image for the onboard device represented by PciHandle
@param This Protocol instance pointer.
@param PciHandle PCI device to return the ROM image for.
@param RomImage PCI Rom Image for onboard device
@param RomSize Size of RomImage in bytes
@retval EFI_SUCCESS RomImage is valid
EFI_NOT_FOUND No RomImageEFI_UNSUPPORTED
**/
EFI_STATUS
GetPciRom (
IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
IN EFI_HANDLE PciHandle,
OUT VOID **RomImage,
OUT UINTN *RomSize
)
{
//
// If there is any code in this function, Default Status must be EFI_SUCCESS
//
EFI_STATUS Status = EFI_SUCCESS;
return Status;
}
/**
The gEfiPciEnumerationCompleteProtocolGuid installed callback routine
This routine is going to adjust the VirtualSecondaryBus number in
PcdVirtualBusTable to match the actual of PCIe root port number when
PCIe root port switched. Without this adjustment, the Pirq table will
based on incorrect virtual bus table to produce wrong IRQ setting to PCIe
downstring port devices
@param[in] Event Event
@param[in] Context Context for the event
**/
STATIC
VOID
EFIAPI
PciEnumCompletedNotifyFunction (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Interface;
LEGACY_MODIFY_PIR_TABLE *VirtualBusTable;
UINTN VirtualBusTableEntries;
INT8 *VirtualBusConvertTable;
UINT32 RootPortFunctionNumber=0;
UINTN Index;
UINTN Function;
UINT8 ChangedFunction;
INT8 ChangedVirtualBus;
UINT32 Rpfn1;
UINT32 Rpfn2;
//
// Insure the protocol really installed
//
Status = gBS->LocateProtocol (
&gEfiPciEnumerationCompleteProtocolGuid,
NULL,
(VOID **)&Interface
);
if (Status != EFI_SUCCESS) {
return;
}
//
// Close event for one time shot
//
gBS->CloseEvent (Event);
VirtualBusTable = PcdGetExPtr (&gChipsetPkgTokenSpaceGuid, PcdVirtualBusTable);
VirtualBusTableEntries = (UINTN)(LibPcdGetExSize (&gChipsetPkgTokenSpaceGuid, PcdToken(PcdVirtualBusTable)) / sizeof (LEGACY_MODIFY_PIR_TABLE));
if (VirtualBusTable == NULL || VirtualBusTableEntries == 0) {
return;
}
//
// Allocate virtual bus lookup table for PCIe port switching
//
VirtualBusConvertTable = AllocateZeroPool (VirtualBusTableEntries);
if (VirtualBusConvertTable == NULL) {
return;
}
//
// Copy virtial bus produced by PCIe(device 0x1c) into lookup table
//
for (Index = 0; Index < VirtualBusTableEntries; Index ++) {
if (VirtualBusTable[Index].BridgeDevice == 0x1c) {
VirtualBusConvertTable[Index] = VirtualBusTable[Index].VirtualSecondaryBus;
}
}
//
// Adjust virtual bus value based on actual PCIe device port position
//
Rpfn1 = PchPcrRead32 (PID_SPA, R_SPX_PCR_PCD);
Rpfn2 = PchPcrRead32 (PID_SPB, R_SPX_PCR_PCD);
RootPortFunctionNumber = Rpfn1 | (Rpfn2 << 16);
for (Function = 0; Function < 8; Function ++) {
ChangedFunction = (UINT8)((RootPortFunctionNumber >> (Function * S_SPX_PCR_PCD_RP_FIELD)) & B_SPX_PCR_PCD_RP1FN);
for (Index = 0, ChangedVirtualBus = 0; Index < VirtualBusTableEntries; Index ++) {
if (VirtualBusTable[Index].BridgeDevice == 0x1c && VirtualBusTable[Index].BridgeFunction == ChangedFunction) {
ChangedVirtualBus = VirtualBusConvertTable[Index];
break;
}
}
if (ChangedVirtualBus != 0) {
for (Index = 0; Index < VirtualBusTableEntries; Index ++) {
if (VirtualBusTable[Index].BridgeDevice == 0x1c && VirtualBusTable[Index].BridgeFunction == Function) {
VirtualBusTable[Index].VirtualSecondaryBus = ChangedVirtualBus;
break;
}
}
}
}
FreePool (VirtualBusConvertTable);
}