mirror of https://github.com/acidanthera/audk.git
327 lines
11 KiB
C
327 lines
11 KiB
C
|
/** @file
|
||
|
Implementation of Usb Controller PPI.
|
||
|
|
||
|
Copyright (c) 2013-2015 Intel Corporation.
|
||
|
|
||
|
This program and the accompanying materials
|
||
|
are licensed and made available under the terms and conditions of the BSD License
|
||
|
which 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 <PiPei.h>
|
||
|
#include <Ppi/UsbController.h>
|
||
|
#include <Library/DebugLib.h>
|
||
|
#include <Library/PeimEntryPoint.h>
|
||
|
#include <Library/PeiServicesLib.h>
|
||
|
#include <Library/BaseMemoryLib.h>
|
||
|
#include <Library/PcdLib.h>
|
||
|
#include <Library/PciLib.h>
|
||
|
#include <Library/IoLib.h>
|
||
|
|
||
|
#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;
|
||
|
}
|
||
|
|