/** @file This is the FSP driver that initializes the Intel PCH. Copyright (c) 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #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; }