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