]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Usb / Common / Pei / UsbPei.c
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c
new file mode 100644 (file)
index 0000000..41fb544
--- /dev/null
@@ -0,0 +1,326 @@
+/** @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