]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
MdeModulePkg: Add UFS (Universal Flash Storage) Stack
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UfsPciHcPei / UfsPciHcPei.c
diff --git a/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c b/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
new file mode 100644 (file)
index 0000000..3632564
--- /dev/null
@@ -0,0 +1,152 @@
+/** @file\r
+  UfsPciHcPei driver is used to provide platform-dependent info, mainly UFS host controller\r
+  MMIO base, to upper layer UFS drivers.\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\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 "UfsPciHcPei.h"\r
+\r
+EDKII_UFS_HOST_CONTROLLER_PPI  mUfsHostControllerPpi = { GetUfsHcMmioBar };\r
+\r
+EFI_PEI_PPI_DESCRIPTOR   mPpiList = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEdkiiPeiUfsHostControllerPpiGuid,\r
+  &mUfsHostControllerPpi\r
+};\r
+\r
+/**\r
+  Get the MMIO base address of UFS host controller.\r
+\r
+  @param[in]  This               The protocol instance pointer.\r
+  @param[in]  ControllerId       The ID of the UFS host controller.\r
+  @param[out] MmioBar            Pointer to the UFS host controller MMIO base address.\r
+\r
+  @retval EFI_SUCCESS            The operation succeeds.\r
+  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetUfsHcMmioBar (\r
+  IN     EDKII_UFS_HOST_CONTROLLER_PPI *This,\r
+  IN     UINT8                         ControllerId,\r
+     OUT UINTN                         *MmioBar\r
+  )\r
+{\r
+  UFS_HC_PEI_PRIVATE_DATA  *Private;\r
+\r
+  if ((This == NULL) || (MmioBar == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = UFS_HC_PEI_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (ControllerId >= Private->TotalUfsHcs) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  *MmioBar = (UINTN)Private->UfsHcPciAddr[ControllerId];\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  The user code starts with this function.\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            The driver is successfully initialized.\r
+  @retval Others                 Can't initialize the driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeUfsHcPeim (\r
+  IN EFI_PEI_FILE_HANDLE       FileHandle,\r
+  IN CONST EFI_PEI_SERVICES    **PeiServices\r
+  )\r
+{\r
+  EFI_BOOT_MODE            BootMode;\r
+  EFI_STATUS               Status;\r
+  UINT16                   Bus;\r
+  UINT16                   Device;\r
+  UINT16                   Function;\r
+  UINT32                   Size;\r
+  UINT8                    SubClass;\r
+  UINT8                    BaseClass;\r
+  UFS_HC_PEI_PRIVATE_DATA  *Private;\r
+\r
+  //\r
+  // Shadow this PEIM to run from memory\r
+  //\r
+  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = PeiServicesGetBootMode (&BootMode);\r
+  ///\r
+  /// We do not export this in S3 boot path, because it is only for recovery.\r
+  ///\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Private = (UFS_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (UFS_HC_PEI_PRIVATE_DATA));\r
+  if (Private == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "Failed to allocate memory for UFS_HC_PEI_PRIVATE_DATA! \n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->Signature            = UFS_HC_PEI_SIGNATURE;\r
+  Private->UfsHostControllerPpi = mUfsHostControllerPpi;\r
+  Private->PpiList              = mPpiList;\r
+  Private->PpiList.Ppi          = &Private->UfsHostControllerPpi;\r
+\r
+  for (Bus = 0; Bus < 256; Bus++) {\r
+    for (Device = 0; Device < 32; Device++) {\r
+      for (Function = 0; Function < 8; Function++) {\r
+        SubClass  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));\r
+        BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));\r
+\r
+        if ((SubClass == 0x09) && (BaseClass == PCI_CLASS_MASS_STORAGE)) {\r
+          //\r
+          // Get the Ufs Pci host controller's MMIO region size.\r
+          //\r
+          PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));\r
+          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);\r
+          Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));\r
+          //\r
+          // Assign resource to the Ufs Pci host controller's MMIO BAR.\r
+          // Enable the Ufs Pci host controller by setting BME and MSE bits of PCI_CMD register.\r
+          //\r
+          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)(PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs));\r
+          PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));\r
+          //\r
+          // Record the allocated Mmio base address.\r
+          //\r
+          Private->UfsHcPciAddr[Private->TotalUfsHcs] = PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs;\r
+          Private->TotalUfsHcs++;\r
+          ASSERT (Private->TotalUfsHcs < MAX_UFS_HCS);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  ///\r
+  /// Install Ufs Host Controller PPI\r
+  ///\r
+  Status = PeiServicesInstallPpi (&Private->PpiList);\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+  return Status;\r
+}\r