/** @file
This is the FSP driver that initializes the Intel PCH.
Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PchInit.h"
EFI_STATUS
EFIAPI
PchOnPciEnumCompleteFsp (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
STATIC
EFI_PEI_NOTIFY_DESCRIPTOR mPchOnPciEnumCompleteNotifyList[] = {
{
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPciEnumerationCompleteProtocolGuid,
PchOnPciEnumCompleteFsp
}
};
EFI_STATUS
EFIAPI
PchReadyToBootEventFsp (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
STATIC EFI_PEI_NOTIFY_DESCRIPTOR mReadyToBootNotifyList[] = {
{
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEventReadyToBootGuid,
PchReadyToBootEventFsp
}
};
/**
FSP PchInit Module Entry Point for FSP\n
@param[in] FileHandle PEIM's file handle
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@retval EFI_SUCCESS The function completed successfully
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
**/
EFI_STATUS
EFIAPI
PchInitEntryPointFsp (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() Start\n"));
PchInitEntryPointCommon ();
Status = PeiServicesNotifyPpi (mPchOnPciEnumCompleteNotifyList);
ASSERT_EFI_ERROR (Status);
Status = PeiServicesNotifyPpi (mReadyToBootNotifyList);
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() End\n"));
return Status;
}
/**
Fsp PCH initialization on PCI enumeration complete
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param[in] NotifyDescriptor Address of the notification descriptor data structure.
@param[in] Ppi Address of the PPI that was installed.
@retval EFI_SUCCESS The function completed successfully
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
**/
EFI_STATUS
EFIAPI
PchOnPciEnumCompleteFsp (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() Start\n"));
PchOnPciEnumCompleteCommon ();
DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() End\n"));
return EFI_SUCCESS;
}
/**
FSP PCH Ready to boot event handler
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param[in] NotifyDescriptor Address of the notification descriptor data structure.
@param[in] Ppi Address of the PPI that was installed.
@retval EFI_SUCCESS The function completed successfully
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
**/
EFI_STATUS
EFIAPI
PchReadyToBootEventFsp (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
UINTN XhciMmioBase;
UINTN XhciPciMmBase;
UINT16 XhciPciCommand;
BOOLEAN XhciPdoRestartNeeded;
DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() Start\n"));
// Check if USB PDO programming was skipped during PEI phase
if (mPchConfigHob->Usb.DelayPdoProgramming == TRUE) {
XhciPciMmBase = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_XHCI,
PCI_FUNCTION_NUMBER_PCH_XHCI
);
// Check if xHCI has memory access
XhciPciCommand = MmioRead16 (XhciPciMmBase + PCI_COMMAND_OFFSET);
if ((XhciPciCommand & EFI_PCI_COMMAND_MEMORY_SPACE) == 0x0) {
DEBUG ((DEBUG_ERROR, "xHCI Controller isn't configured properly\n"));
} else {
// Getting base MMIO address for xHCI
XhciMmioBase = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & (B_PCH_XHCI_MEM_ALIGN_MASK << N_PCH_XHCI_MEM_ALIGN);
XhciPdoRestartNeeded = UsbPdoProgramming (
XhciMmioBase,
mPchConfigHob->Usb.Usb2DisabledPorts,
mPchConfigHob->Usb.Usb3DisabledPorts
);
// If PDO registers are locked, reset platform to unlock them
if (XhciPdoRestartNeeded) {
(*PeiServices)->ResetSystem2 (EfiResetWarm, EFI_SUCCESS, 0, NULL);
}
}
} else {
DEBUG ((DEBUG_INFO, "PDO register already programmed\n"));
}
DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() End\n"));
return EFI_SUCCESS;
}