/** @file Implementation of Usb Controller PPI. Copyright (c) 2013-2015 Intel Corporation. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include "UsbPei.h" // // Globals // // EFI_PEI_PPI_DESCRIPTOR mPpiList = { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gPeiUsbControllerPpiGuid, NULL }; UINTN mIohOhciPciReg[IOH_MAX_OHCI_USB_CONTROLLERS] = { PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, 0) }; UINTN mIohEhciPciReg[IOH_MAX_EHCI_USB_CONTROLLERS] = { PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, 0), }; /** When EHCI get started in DXE, OHCI couldn't get the ownership of roothub after warm reset because CF@EHCI hasn't been cleared. We should clear that reg before UpdateBootMode. But Reg@EHCI is memory-mapped, so need assume a range of space without conflict in PCI memory space. @param[in] PeiServices The pointer of EFI_PEI_SERVICES **/ VOID SwitchConfigFlag ( IN EFI_PEI_SERVICES **PeiServices ) { UINT32 SavBaseAddr; UINT32 UsbBaseAddr; UINT16 SaveCmdData; UINT8 EhciCapLen; UINT8 Index; UsbBaseAddr = 0; for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++) { UsbBaseAddr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress); // // Manage EHCI on IOH, set UsbBaseAddr // SavBaseAddr = PciRead32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR); PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, UsbBaseAddr); // // Save Cmd register // SaveCmdData = PciRead16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND); // // Enable EHCI on IOH // PciOr16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, B_IOH_USB_COMMAND_BME | B_IOH_USB_COMMAND_MSE ); // // Clear CF register on EHCI // EhciCapLen = MmioRead8 (UsbBaseAddr + R_IOH_EHCI_CAPLENGTH); MmioWrite32 (UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS, 0); DEBUG ((EFI_D_INFO, "CF@EHCI = %x \n", UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS)); // // Restore EHCI UsbBaseAddr in PCI space // PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, SavBaseAddr); // // Restore EHCI Command register in PCI space // PciWrite16(mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, SaveCmdData); } } /** Retrieved specified the USB controller information. @param PeiServices The pointer of EFI_PEI_SERVICES. @param This This PEI_USB_CONTROLLER_PPI instance. @param UsbControllerId Indicate which usb controller information will be retrieved. @param ControllerType Indicate the controller is Ehci, Ohci, OHCI @param BaseAddress Indicate the memory bar of the controller @retval EFI_SUCCESS The reset operation succeeded. @retval EFI_INVALID_PARAMETER Attributes is not valid. **/ EFI_STATUS GetOhciController ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_CONTROLLER_PPI *This, IN UINT8 UsbControllerId, IN UINTN *ControllerType, IN UINTN *BaseAddress ) { IOH_OHCI_DEVICE *PeiIohOhciDev; PeiIohOhciDev = IOH_OHCI_DEVICE_FROM_THIS (This); if (UsbControllerId >= IOH_MAX_OHCI_USB_CONTROLLERS) { return EFI_INVALID_PARAMETER; } *ControllerType = PEI_OHCI_CONTROLLER; *BaseAddress = PeiIohOhciDev->MmioBase[UsbControllerId]; return EFI_SUCCESS; } /** Retrieved specified the USB controller information. @param PeiServices The pointer of EFI_PEI_SERVICES. @param This This PEI_USB_CONTROLLER_PPI instance. @param UsbControllerId Indicate which usb controller information will be retrieved. @param ControllerType Indicate the controller is Ehci, Ohci, OHCI @param BaseAddress Indicate the memory bar of the controller @retval EFI_SUCCESS The reset operation succeeded. @retval EFI_INVALID_PARAMETER Attributes is not valid. **/ EFI_STATUS GetEhciController ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_CONTROLLER_PPI *This, IN UINT8 UsbControllerId, IN UINTN *ControllerType, IN UINTN *BaseAddress ) { IOH_EHCI_DEVICE *PeiIohEhciDev; PeiIohEhciDev = IOH_EHCI_DEVICE_FROM_THIS (This); if (UsbControllerId >= IOH_MAX_EHCI_USB_CONTROLLERS) { return EFI_INVALID_PARAMETER; } *ControllerType = PEI_EHCI_CONTROLLER; *BaseAddress = PeiIohEhciDev->MmioBase[UsbControllerId]; return EFI_SUCCESS; } /** Retrieved specified the USB controller information. @param IohOhciPciReg Ohci device address list. @param OhciCount The count of the OHCI @param IohEhciPciReg Ehci device address list. @param EhciCount The count of the EHCI **/ VOID EnableBusMaster ( IN UINTN IohOhciPciReg[], IN UINT8 OhciCount, IN UINTN IohEhciPciReg[], IN UINT8 EhciCount ) { UINT8 Index; UINT16 CmdReg; for (Index = 0; Index < OhciCount; Index ++) { CmdReg = PciRead16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND); CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME ); PciWrite16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg); } for (Index = 0; Index < EhciCount; Index ++) { CmdReg = PciRead16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND); CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME ); PciWrite16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg); } } PEI_USB_CONTROLLER_PPI mUsbControllerPpi[2] = { {GetOhciController}, {GetEhciController}}; /** @param FileHandle Handle of the file being invoked. @param PeiServices Describes the list of possible PEI Services. @retval EFI_SUCCESS PPI successfully installed **/ EFI_STATUS PeimInitializeIchUsb ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; UINTN i; EFI_PHYSICAL_ADDRESS AllocateAddress; IOH_OHCI_DEVICE *PeiIohOhciDev; IOH_EHCI_DEVICE *PeiIohEhciDev; UINT16 CmdReg; Status = PeiServicesAllocatePages ( EfiBootServicesCode, 1, &AllocateAddress ); ASSERT_EFI_ERROR (Status); EnableBusMaster ( mIohOhciPciReg, IOH_MAX_OHCI_USB_CONTROLLERS, mIohEhciPciReg, IOH_MAX_EHCI_USB_CONTROLLERS ); if (FeaturePcdGet (PcdEhciRecoveryEnabled)) { DEBUG ((EFI_D_INFO, "UsbPei:EHCI is used for recovery\n")); // // EHCI recovery is enabled // PeiIohEhciDev = (IOH_EHCI_DEVICE *)((UINTN)AllocateAddress); ZeroMem (PeiIohEhciDev, sizeof(IOH_EHCI_DEVICE)); PeiIohEhciDev->Signature = PEI_IOH_EHCI_SIGNATURE; CopyMem(&(PeiIohEhciDev->UsbControllerPpi), &mUsbControllerPpi[1], sizeof(PEI_USB_CONTROLLER_PPI)); CopyMem(&(PeiIohEhciDev->PpiList), &mPpiList, sizeof(mPpiList)); PeiIohEhciDev->PpiList.Ppi = &PeiIohEhciDev->UsbControllerPpi; // // Assign resources and enable Ehci controllers // for (i = 0; i < IOH_MAX_EHCI_USB_CONTROLLERS; i++) { DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth EHCI controller for recovery\n", i)); PeiIohEhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i; // // Assign base address register, Enable Bus Master and Memory Io // PciWrite32 (mIohEhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohEhciDev->MmioBase[i]); CmdReg = PciRead16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND); CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME ); PciWrite16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg); } // // Install USB Controller PPI // Status = (**PeiServices).InstallPpi ( PeiServices, &PeiIohEhciDev->PpiList ); ASSERT_EFI_ERROR (Status); } else { DEBUG ((EFI_D_INFO, "UsbPei:OHCI is used for recovery\n")); // // OHCI recovery is enabled // SwitchConfigFlag ((EFI_PEI_SERVICES**)PeiServices); PeiIohOhciDev = (IOH_OHCI_DEVICE *)((UINTN)AllocateAddress); ZeroMem (PeiIohOhciDev, sizeof(IOH_OHCI_DEVICE)); PeiIohOhciDev->Signature = PEI_IOH_OHCI_SIGNATURE; CopyMem(&(PeiIohOhciDev->UsbControllerPpi), &mUsbControllerPpi[0], sizeof(PEI_USB_CONTROLLER_PPI)); CopyMem(&(PeiIohOhciDev->PpiList), &mPpiList, sizeof(mPpiList)); PeiIohOhciDev->PpiList.Ppi = &PeiIohOhciDev->UsbControllerPpi; // // Assign resources and enable OHCI controllers // for (i = 0; i < IOH_MAX_OHCI_USB_CONTROLLERS; i++) { DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth OHCI controller for recovery\n", i)); PeiIohOhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i; // // Assign base address register, Enable Bus Master and Memory Io // PciWrite32 (mIohOhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohOhciDev->MmioBase[i]); Status = PeiServicesAllocatePages ( EfiBootServicesCode, 1, &AllocateAddress ); ASSERT_EFI_ERROR (Status); MmioWrite32(PeiIohOhciDev->MmioBase[i] + R_IOH_USB_OHCI_HCCABAR, (UINT32)AllocateAddress); CmdReg = PciRead16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND); CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME ); PciWrite16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg); } // // Install USB Controller PPI // Status = (**PeiServices).InstallPpi ( PeiServices, &PeiIohOhciDev->PpiList ); ASSERT_EFI_ERROR (Status); } return Status; }