1 /** @file 2 SdMmcPciHcPei driver is used to provide platform-dependent info, mainly SD/MMC 3 host controller MMIO base, to upper layer SD/MMC drivers. 4 5 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "SdMmcPciHcPei.h" 17 18 EDKII_SD_MMC_HOST_CONTROLLER_PPI mSdMmcHostControllerPpi = { GetSdMmcHcMmioBar }; 19 20 EFI_PEI_PPI_DESCRIPTOR mPpiList = { 21 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 22 &gEdkiiPeiSdMmcHostControllerPpiGuid, 23 &mSdMmcHostControllerPpi 24 }; 25 26 /** 27 Get the MMIO base address of SD/MMC host controller. 28 29 @param[in] This The protocol instance pointer. 30 @param[in] ControllerId The ID of the SD/MMC host controller. 31 @param[in,out] MmioBar The pointer to store the array of available 32 SD/MMC host controller slot MMIO base addresses. 33 The entry number of the array is specified by BarNum. 34 @param[out] BarNum The pointer to store the supported bar number. 35 36 @retval EFI_SUCCESS The operation succeeds. 37 @retval EFI_INVALID_PARAMETER The parameters are invalid. 38 39 **/ 40 EFI_STATUS 41 EFIAPI 42 GetSdMmcHcMmioBar ( 43 IN EDKII_SD_MMC_HOST_CONTROLLER_PPI *This, 44 IN UINT8 ControllerId, 45 IN OUT UINTN **MmioBar, 46 OUT UINT8 *BarNum 47 ) 48 { 49 SD_MMC_HC_PEI_PRIVATE_DATA *Private; 50 51 if ((This == NULL) || (MmioBar == NULL) || (BarNum == NULL)) { 52 return EFI_INVALID_PARAMETER; 53 } 54 55 Private = SD_MMC_HC_PEI_PRIVATE_DATA_FROM_THIS (This); 56 57 if (ControllerId >= Private->TotalSdMmcHcs) { 58 return EFI_INVALID_PARAMETER; 59 } 60 61 *MmioBar = &Private->MmioBar[ControllerId].MmioBarAddr[0]; 62 *BarNum = (UINT8)Private->MmioBar[ControllerId].SlotNum; 63 return EFI_SUCCESS; 64 } 65 66 /** 67 The user code starts with this function. 68 69 @param FileHandle Handle of the file being invoked. 70 @param PeiServices Describes the list of possible PEI Services. 71 72 @retval EFI_SUCCESS The driver is successfully initialized. 73 @retval Others Can't initialize the driver. 74 75 **/ 76 EFI_STATUS 77 EFIAPI 78 InitializeSdMmcHcPeim ( 79 IN EFI_PEI_FILE_HANDLE FileHandle, 80 IN CONST EFI_PEI_SERVICES **PeiServices 81 ) 82 { 83 EFI_BOOT_MODE BootMode; 84 EFI_STATUS Status; 85 UINT16 Bus; 86 UINT16 Device; 87 UINT16 Function; 88 UINT32 Size; 89 UINT64 MmioSize; 90 UINT8 SubClass; 91 UINT8 BaseClass; 92 UINT8 SlotInfo; 93 UINT8 SlotNum; 94 UINT8 FirstBar; 95 UINT8 Index; 96 UINT8 Slot; 97 UINT32 BarAddr; 98 SD_MMC_HC_PEI_PRIVATE_DATA *Private; 99 100 // 101 // Shadow this PEIM to run from memory 102 // 103 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) { 104 return EFI_SUCCESS; 105 } 106 107 Status = PeiServicesGetBootMode (&BootMode); 108 /// 109 /// We do not expose this in S3 boot path, because it is only for recovery. 110 /// 111 if (BootMode == BOOT_ON_S3_RESUME) { 112 return EFI_SUCCESS; 113 } 114 115 Private = (SD_MMC_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (SD_MMC_HC_PEI_PRIVATE_DATA)); 116 if (Private == NULL) { 117 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for SD_MMC_HC_PEI_PRIVATE_DATA! \n")); 118 return EFI_OUT_OF_RESOURCES; 119 } 120 121 Private->Signature = SD_MMC_HC_PEI_SIGNATURE; 122 Private->SdMmcHostControllerPpi = mSdMmcHostControllerPpi; 123 Private->PpiList = mPpiList; 124 Private->PpiList.Ppi = &Private->SdMmcHostControllerPpi; 125 126 BarAddr = PcdGet32 (PcdSdMmcPciHostControllerMmioBase); 127 for (Bus = 0; Bus < 256; Bus++) { 128 for (Device = 0; Device < 32; Device++) { 129 for (Function = 0; Function < 8; Function++) { 130 SubClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A)); 131 BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B)); 132 133 if ((SubClass == PCI_SUBCLASS_SD_HOST_CONTROLLER) && (BaseClass == PCI_CLASS_SYSTEM_PERIPHERAL)) { 134 // 135 // Get the SD/MMC Pci host controller's Slot Info. 136 // 137 SlotInfo = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, SD_MMC_HC_PEI_SLOT_OFFSET)); 138 FirstBar = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).FirstBar; 139 SlotNum = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).SlotNum + 1; 140 ASSERT ((FirstBar + SlotNum) < MAX_SD_MMC_SLOTS); 141 142 for (Index = 0, Slot = FirstBar; Slot < (FirstBar + SlotNum); Index++, Slot++) { 143 // 144 // Get the SD/MMC Pci host controller's MMIO region size. 145 // 146 PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE)); 147 PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot), 0xFFFFFFFF); 148 Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot)); 149 150 switch (Size & 0x07) { 151 case 0x0: 152 // 153 // Memory space: anywhere in 32 bit address space 154 // 155 MmioSize = (~(Size & 0xFFFFFFF0)) + 1; 156 break; 157 case 0x4: 158 // 159 // Memory space: anywhere in 64 bit address space 160 // 161 MmioSize = Size & 0xFFFFFFF0; 162 PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0xFFFFFFFF); 163 Size = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4)); 164 // 165 // Fix the length to support some spefic 64 bit BAR 166 // 167 Size |= ((UINT32)(-1) << HighBitSet32 (Size)); 168 // 169 // Calculate the size of 64bit bar 170 // 171 MmioSize |= LShiftU64 ((UINT64) Size, 32); 172 MmioSize = (~(MmioSize)) + 1; 173 // 174 // Clean the high 32bits of this 64bit BAR to 0 as we only allow a 32bit BAR. 175 // 176 PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot + 4), 0); 177 break; 178 default: 179 // 180 // Unknown BAR type 181 // 182 ASSERT (FALSE); 183 continue; 184 }; 185 // 186 // Assign resource to the SdMmc Pci host controller's MMIO BAR. 187 // Enable the SdMmc Pci host controller by setting BME and MSE bits of PCI_CMD register. 188 // 189 PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot), BarAddr); 190 PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE)); 191 // 192 // Record the allocated Mmio base address. 193 // 194 Private->MmioBar[Private->TotalSdMmcHcs].SlotNum++; 195 Private->MmioBar[Private->TotalSdMmcHcs].MmioBarAddr[Index] = BarAddr; 196 BarAddr += (UINT32)MmioSize; 197 } 198 Private->TotalSdMmcHcs++; 199 ASSERT (Private->TotalSdMmcHcs < MAX_SD_MMC_HCS); 200 } 201 } 202 } 203 } 204 205 /// 206 /// Install SdMmc Host Controller PPI 207 /// 208 Status = PeiServicesInstallPpi (&Private->PpiList); 209 210 ASSERT_EFI_ERROR (Status); 211 return Status; 212 } 213