10591696eff9962b52b3b0137e865198096353573Feng Tian/** @file
20591696eff9962b52b3b0137e865198096353573Feng Tian  UfsPciHcPei driver is used to provide platform-dependent info, mainly UFS host controller
30591696eff9962b52b3b0137e865198096353573Feng Tian  MMIO base, to upper layer UFS drivers.
40591696eff9962b52b3b0137e865198096353573Feng Tian
50591696eff9962b52b3b0137e865198096353573Feng Tian  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
60591696eff9962b52b3b0137e865198096353573Feng Tian  This program and the accompanying materials
70591696eff9962b52b3b0137e865198096353573Feng Tian  are licensed and made available under the terms and conditions of the BSD License
80591696eff9962b52b3b0137e865198096353573Feng Tian  which accompanies this distribution.  The full text of the license may be found at
90591696eff9962b52b3b0137e865198096353573Feng Tian  http://opensource.org/licenses/bsd-license.php.
100591696eff9962b52b3b0137e865198096353573Feng Tian
110591696eff9962b52b3b0137e865198096353573Feng Tian  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
120591696eff9962b52b3b0137e865198096353573Feng Tian  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
130591696eff9962b52b3b0137e865198096353573Feng Tian
140591696eff9962b52b3b0137e865198096353573Feng Tian**/
150591696eff9962b52b3b0137e865198096353573Feng Tian
160591696eff9962b52b3b0137e865198096353573Feng Tian#include "UfsPciHcPei.h"
170591696eff9962b52b3b0137e865198096353573Feng Tian
180591696eff9962b52b3b0137e865198096353573Feng TianEDKII_UFS_HOST_CONTROLLER_PPI  mUfsHostControllerPpi = { GetUfsHcMmioBar };
190591696eff9962b52b3b0137e865198096353573Feng Tian
200591696eff9962b52b3b0137e865198096353573Feng TianEFI_PEI_PPI_DESCRIPTOR   mPpiList = {
210591696eff9962b52b3b0137e865198096353573Feng Tian  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
220591696eff9962b52b3b0137e865198096353573Feng Tian  &gEdkiiPeiUfsHostControllerPpiGuid,
230591696eff9962b52b3b0137e865198096353573Feng Tian  &mUfsHostControllerPpi
240591696eff9962b52b3b0137e865198096353573Feng Tian};
250591696eff9962b52b3b0137e865198096353573Feng Tian
260591696eff9962b52b3b0137e865198096353573Feng Tian/**
270591696eff9962b52b3b0137e865198096353573Feng Tian  Get the MMIO base address of UFS host controller.
280591696eff9962b52b3b0137e865198096353573Feng Tian
290591696eff9962b52b3b0137e865198096353573Feng Tian  @param[in]  This               The protocol instance pointer.
300591696eff9962b52b3b0137e865198096353573Feng Tian  @param[in]  ControllerId       The ID of the UFS host controller.
310591696eff9962b52b3b0137e865198096353573Feng Tian  @param[out] MmioBar            Pointer to the UFS host controller MMIO base address.
320591696eff9962b52b3b0137e865198096353573Feng Tian
330591696eff9962b52b3b0137e865198096353573Feng Tian  @retval EFI_SUCCESS            The operation succeeds.
340591696eff9962b52b3b0137e865198096353573Feng Tian  @retval EFI_INVALID_PARAMETER  The parameters are invalid.
350591696eff9962b52b3b0137e865198096353573Feng Tian
360591696eff9962b52b3b0137e865198096353573Feng Tian**/
370591696eff9962b52b3b0137e865198096353573Feng TianEFI_STATUS
380591696eff9962b52b3b0137e865198096353573Feng TianEFIAPI
390591696eff9962b52b3b0137e865198096353573Feng TianGetUfsHcMmioBar (
400591696eff9962b52b3b0137e865198096353573Feng Tian  IN     EDKII_UFS_HOST_CONTROLLER_PPI *This,
410591696eff9962b52b3b0137e865198096353573Feng Tian  IN     UINT8                         ControllerId,
420591696eff9962b52b3b0137e865198096353573Feng Tian     OUT UINTN                         *MmioBar
430591696eff9962b52b3b0137e865198096353573Feng Tian  )
440591696eff9962b52b3b0137e865198096353573Feng Tian{
450591696eff9962b52b3b0137e865198096353573Feng Tian  UFS_HC_PEI_PRIVATE_DATA  *Private;
460591696eff9962b52b3b0137e865198096353573Feng Tian
470591696eff9962b52b3b0137e865198096353573Feng Tian  if ((This == NULL) || (MmioBar == NULL)) {
480591696eff9962b52b3b0137e865198096353573Feng Tian    return EFI_INVALID_PARAMETER;
490591696eff9962b52b3b0137e865198096353573Feng Tian  }
500591696eff9962b52b3b0137e865198096353573Feng Tian
510591696eff9962b52b3b0137e865198096353573Feng Tian  Private = UFS_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
520591696eff9962b52b3b0137e865198096353573Feng Tian
530591696eff9962b52b3b0137e865198096353573Feng Tian  if (ControllerId >= Private->TotalUfsHcs) {
540591696eff9962b52b3b0137e865198096353573Feng Tian    return EFI_INVALID_PARAMETER;
550591696eff9962b52b3b0137e865198096353573Feng Tian  }
560591696eff9962b52b3b0137e865198096353573Feng Tian
570591696eff9962b52b3b0137e865198096353573Feng Tian  *MmioBar = (UINTN)Private->UfsHcPciAddr[ControllerId];
580591696eff9962b52b3b0137e865198096353573Feng Tian
590591696eff9962b52b3b0137e865198096353573Feng Tian  return EFI_SUCCESS;
600591696eff9962b52b3b0137e865198096353573Feng Tian}
610591696eff9962b52b3b0137e865198096353573Feng Tian
620591696eff9962b52b3b0137e865198096353573Feng Tian/**
630591696eff9962b52b3b0137e865198096353573Feng Tian  The user code starts with this function.
640591696eff9962b52b3b0137e865198096353573Feng Tian
650591696eff9962b52b3b0137e865198096353573Feng Tian  @param  FileHandle             Handle of the file being invoked.
660591696eff9962b52b3b0137e865198096353573Feng Tian  @param  PeiServices            Describes the list of possible PEI Services.
670591696eff9962b52b3b0137e865198096353573Feng Tian
680591696eff9962b52b3b0137e865198096353573Feng Tian  @retval EFI_SUCCESS            The driver is successfully initialized.
690591696eff9962b52b3b0137e865198096353573Feng Tian  @retval Others                 Can't initialize the driver.
700591696eff9962b52b3b0137e865198096353573Feng Tian
710591696eff9962b52b3b0137e865198096353573Feng Tian**/
720591696eff9962b52b3b0137e865198096353573Feng TianEFI_STATUS
730591696eff9962b52b3b0137e865198096353573Feng TianEFIAPI
740591696eff9962b52b3b0137e865198096353573Feng TianInitializeUfsHcPeim (
750591696eff9962b52b3b0137e865198096353573Feng Tian  IN EFI_PEI_FILE_HANDLE       FileHandle,
760591696eff9962b52b3b0137e865198096353573Feng Tian  IN CONST EFI_PEI_SERVICES    **PeiServices
770591696eff9962b52b3b0137e865198096353573Feng Tian  )
780591696eff9962b52b3b0137e865198096353573Feng Tian{
790591696eff9962b52b3b0137e865198096353573Feng Tian  EFI_BOOT_MODE            BootMode;
800591696eff9962b52b3b0137e865198096353573Feng Tian  EFI_STATUS               Status;
810591696eff9962b52b3b0137e865198096353573Feng Tian  UINT16                   Bus;
820591696eff9962b52b3b0137e865198096353573Feng Tian  UINT16                   Device;
830591696eff9962b52b3b0137e865198096353573Feng Tian  UINT16                   Function;
840591696eff9962b52b3b0137e865198096353573Feng Tian  UINT32                   Size;
850591696eff9962b52b3b0137e865198096353573Feng Tian  UINT8                    SubClass;
860591696eff9962b52b3b0137e865198096353573Feng Tian  UINT8                    BaseClass;
870591696eff9962b52b3b0137e865198096353573Feng Tian  UFS_HC_PEI_PRIVATE_DATA  *Private;
880591696eff9962b52b3b0137e865198096353573Feng Tian
890591696eff9962b52b3b0137e865198096353573Feng Tian  //
900591696eff9962b52b3b0137e865198096353573Feng Tian  // Shadow this PEIM to run from memory
910591696eff9962b52b3b0137e865198096353573Feng Tian  //
920591696eff9962b52b3b0137e865198096353573Feng Tian  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
930591696eff9962b52b3b0137e865198096353573Feng Tian    return EFI_SUCCESS;
940591696eff9962b52b3b0137e865198096353573Feng Tian  }
950591696eff9962b52b3b0137e865198096353573Feng Tian
960591696eff9962b52b3b0137e865198096353573Feng Tian  Status = PeiServicesGetBootMode (&BootMode);
970591696eff9962b52b3b0137e865198096353573Feng Tian  ///
980591696eff9962b52b3b0137e865198096353573Feng Tian  /// We do not export this in S3 boot path, because it is only for recovery.
990591696eff9962b52b3b0137e865198096353573Feng Tian  ///
1000591696eff9962b52b3b0137e865198096353573Feng Tian  if (BootMode == BOOT_ON_S3_RESUME) {
1010591696eff9962b52b3b0137e865198096353573Feng Tian    return EFI_SUCCESS;
1020591696eff9962b52b3b0137e865198096353573Feng Tian  }
1030591696eff9962b52b3b0137e865198096353573Feng Tian
1040591696eff9962b52b3b0137e865198096353573Feng Tian  Private = (UFS_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (UFS_HC_PEI_PRIVATE_DATA));
1050591696eff9962b52b3b0137e865198096353573Feng Tian  if (Private == NULL) {
1060591696eff9962b52b3b0137e865198096353573Feng Tian    DEBUG ((EFI_D_ERROR, "Failed to allocate memory for UFS_HC_PEI_PRIVATE_DATA! \n"));
1070591696eff9962b52b3b0137e865198096353573Feng Tian    return EFI_OUT_OF_RESOURCES;
1080591696eff9962b52b3b0137e865198096353573Feng Tian  }
1090591696eff9962b52b3b0137e865198096353573Feng Tian
1100591696eff9962b52b3b0137e865198096353573Feng Tian  Private->Signature            = UFS_HC_PEI_SIGNATURE;
1110591696eff9962b52b3b0137e865198096353573Feng Tian  Private->UfsHostControllerPpi = mUfsHostControllerPpi;
1120591696eff9962b52b3b0137e865198096353573Feng Tian  Private->PpiList              = mPpiList;
1130591696eff9962b52b3b0137e865198096353573Feng Tian  Private->PpiList.Ppi          = &Private->UfsHostControllerPpi;
1140591696eff9962b52b3b0137e865198096353573Feng Tian
1150591696eff9962b52b3b0137e865198096353573Feng Tian  for (Bus = 0; Bus < 256; Bus++) {
1160591696eff9962b52b3b0137e865198096353573Feng Tian    for (Device = 0; Device < 32; Device++) {
1170591696eff9962b52b3b0137e865198096353573Feng Tian      for (Function = 0; Function < 8; Function++) {
1180591696eff9962b52b3b0137e865198096353573Feng Tian        SubClass  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
1190591696eff9962b52b3b0137e865198096353573Feng Tian        BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
1200591696eff9962b52b3b0137e865198096353573Feng Tian
1210591696eff9962b52b3b0137e865198096353573Feng Tian        if ((SubClass == 0x09) && (BaseClass == PCI_CLASS_MASS_STORAGE)) {
1220591696eff9962b52b3b0137e865198096353573Feng Tian          //
1230591696eff9962b52b3b0137e865198096353573Feng Tian          // Get the Ufs Pci host controller's MMIO region size.
1240591696eff9962b52b3b0137e865198096353573Feng Tian          //
1250591696eff9962b52b3b0137e865198096353573Feng Tian          PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
1260591696eff9962b52b3b0137e865198096353573Feng Tian          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
1270591696eff9962b52b3b0137e865198096353573Feng Tian          Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
1280591696eff9962b52b3b0137e865198096353573Feng Tian          //
1290591696eff9962b52b3b0137e865198096353573Feng Tian          // Assign resource to the Ufs Pci host controller's MMIO BAR.
1300591696eff9962b52b3b0137e865198096353573Feng Tian          // Enable the Ufs Pci host controller by setting BME and MSE bits of PCI_CMD register.
1310591696eff9962b52b3b0137e865198096353573Feng Tian          //
1320591696eff9962b52b3b0137e865198096353573Feng Tian          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)(PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs));
1330591696eff9962b52b3b0137e865198096353573Feng Tian          PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
1340591696eff9962b52b3b0137e865198096353573Feng Tian          //
1350591696eff9962b52b3b0137e865198096353573Feng Tian          // Record the allocated Mmio base address.
1360591696eff9962b52b3b0137e865198096353573Feng Tian          //
1370591696eff9962b52b3b0137e865198096353573Feng Tian          Private->UfsHcPciAddr[Private->TotalUfsHcs] = PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs;
1380591696eff9962b52b3b0137e865198096353573Feng Tian          Private->TotalUfsHcs++;
1390591696eff9962b52b3b0137e865198096353573Feng Tian          ASSERT (Private->TotalUfsHcs < MAX_UFS_HCS);
1400591696eff9962b52b3b0137e865198096353573Feng Tian        }
1410591696eff9962b52b3b0137e865198096353573Feng Tian      }
1420591696eff9962b52b3b0137e865198096353573Feng Tian    }
1430591696eff9962b52b3b0137e865198096353573Feng Tian  }
1440591696eff9962b52b3b0137e865198096353573Feng Tian
1450591696eff9962b52b3b0137e865198096353573Feng Tian  ///
1460591696eff9962b52b3b0137e865198096353573Feng Tian  /// Install Ufs Host Controller PPI
1470591696eff9962b52b3b0137e865198096353573Feng Tian  ///
1480591696eff9962b52b3b0137e865198096353573Feng Tian  Status = PeiServicesInstallPpi (&Private->PpiList);
1490591696eff9962b52b3b0137e865198096353573Feng Tian
1500591696eff9962b52b3b0137e865198096353573Feng Tian  ASSERT_EFI_ERROR (Status);
1510591696eff9962b52b3b0137e865198096353573Feng Tian  return Status;
1520591696eff9962b52b3b0137e865198096353573Feng Tian}
153