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