/** @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; }