2 SdMmcPciHcPei driver is used to provide platform-dependent info, mainly SD/MMC
3 host controller MMIO base, to upper layer SD/MMC drivers.
5 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SdMmcPciHcPei.h"
12 EDKII_SD_MMC_HOST_CONTROLLER_PPI mSdMmcHostControllerPpi
= { GetSdMmcHcMmioBar
};
14 EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
15 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
16 &gEdkiiPeiSdMmcHostControllerPpiGuid
,
17 &mSdMmcHostControllerPpi
21 Get the MMIO base address of SD/MMC host controller.
23 @param[in] This The protocol instance pointer.
24 @param[in] ControllerId The ID of the SD/MMC host controller.
25 @param[in,out] MmioBar The pointer to store the array of available
26 SD/MMC host controller slot MMIO base addresses.
27 The entry number of the array is specified by BarNum.
28 @param[out] BarNum The pointer to store the supported bar number.
30 @retval EFI_SUCCESS The operation succeeds.
31 @retval EFI_INVALID_PARAMETER The parameters are invalid.
37 IN EDKII_SD_MMC_HOST_CONTROLLER_PPI
*This
,
38 IN UINT8 ControllerId
,
39 IN OUT UINTN
**MmioBar
,
43 SD_MMC_HC_PEI_PRIVATE_DATA
*Private
;
45 if ((This
== NULL
) || (MmioBar
== NULL
) || (BarNum
== NULL
)) {
46 return EFI_INVALID_PARAMETER
;
49 Private
= SD_MMC_HC_PEI_PRIVATE_DATA_FROM_THIS (This
);
51 if (ControllerId
>= Private
->TotalSdMmcHcs
) {
52 return EFI_INVALID_PARAMETER
;
55 *MmioBar
= &Private
->MmioBar
[ControllerId
].MmioBarAddr
[0];
56 *BarNum
= (UINT8
)Private
->MmioBar
[ControllerId
].SlotNum
;
61 The user code starts with this function.
63 @param FileHandle Handle of the file being invoked.
64 @param PeiServices Describes the list of possible PEI Services.
66 @retval EFI_SUCCESS The driver is successfully initialized.
67 @retval Others Can't initialize the driver.
72 InitializeSdMmcHcPeim (
73 IN EFI_PEI_FILE_HANDLE FileHandle
,
74 IN CONST EFI_PEI_SERVICES
**PeiServices
77 EFI_BOOT_MODE BootMode
;
92 SD_MMC_HC_PEI_PRIVATE_DATA
*Private
;
95 // Shadow this PEIM to run from memory
97 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
101 Status
= PeiServicesGetBootMode (&BootMode
);
103 /// We do not expose this in S3 boot path, because it is only for recovery.
105 if (BootMode
== BOOT_ON_S3_RESUME
) {
109 Private
= (SD_MMC_HC_PEI_PRIVATE_DATA
*) AllocateZeroPool (sizeof (SD_MMC_HC_PEI_PRIVATE_DATA
));
110 if (Private
== NULL
) {
111 DEBUG ((DEBUG_ERROR
, "Failed to allocate memory for SD_MMC_HC_PEI_PRIVATE_DATA! \n"));
112 return EFI_OUT_OF_RESOURCES
;
115 Private
->Signature
= SD_MMC_HC_PEI_SIGNATURE
;
116 Private
->SdMmcHostControllerPpi
= mSdMmcHostControllerPpi
;
117 Private
->PpiList
= mPpiList
;
118 Private
->PpiList
.Ppi
= &Private
->SdMmcHostControllerPpi
;
120 BarAddr
= PcdGet32 (PcdSdMmcPciHostControllerMmioBase
);
121 for (Bus
= 0; Bus
< 256; Bus
++) {
122 for (Device
= 0; Device
< 32; Device
++) {
123 for (Function
= 0; Function
< 8; Function
++) {
124 SubClass
= PciRead8 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x0A));
125 BaseClass
= PciRead8 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x0B));
127 if ((SubClass
== PCI_SUBCLASS_SD_HOST_CONTROLLER
) && (BaseClass
== PCI_CLASS_SYSTEM_PERIPHERAL
)) {
129 // Get the SD/MMC Pci host controller's Slot Info.
131 SlotInfo
= PciRead8 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, SD_MMC_HC_PEI_SLOT_OFFSET
));
132 FirstBar
= (*(SD_MMC_HC_PEI_SLOT_INFO
*)&SlotInfo
).FirstBar
;
133 SlotNum
= (*(SD_MMC_HC_PEI_SLOT_INFO
*)&SlotInfo
).SlotNum
+ 1;
134 ASSERT ((FirstBar
+ SlotNum
) < MAX_SD_MMC_SLOTS
);
136 for (Index
= 0, Slot
= FirstBar
; Slot
< (FirstBar
+ SlotNum
); Index
++, Slot
++) {
138 // Get the SD/MMC Pci host controller's MMIO region size.
140 PciAnd16 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_COMMAND_OFFSET
), (UINT16
)~(EFI_PCI_COMMAND_BUS_MASTER
| EFI_PCI_COMMAND_MEMORY_SPACE
));
141 PciWrite32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4 * Slot
), 0xFFFFFFFF);
142 Size
= PciRead32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4 * Slot
));
144 switch (Size
& 0x07) {
147 // Memory space: anywhere in 32 bit address space
149 MmioSize
= (~(Size
& 0xFFFFFFF0)) + 1;
153 // Memory space: anywhere in 64 bit address space
155 MmioSize
= Size
& 0xFFFFFFF0;
156 PciWrite32 (PCI_LIB_ADDRESS(Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4), 0xFFFFFFFF);
157 Size
= PciRead32 (PCI_LIB_ADDRESS(Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4));
159 // Fix the length to support some spefic 64 bit BAR
161 Size
|= ((UINT32
)(-1) << HighBitSet32 (Size
));
163 // Calculate the size of 64bit bar
165 MmioSize
|= LShiftU64 ((UINT64
) Size
, 32);
166 MmioSize
= (~(MmioSize
)) + 1;
168 // Clean the high 32bits of this 64bit BAR to 0 as we only allow a 32bit BAR.
170 PciWrite32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4 * Slot
+ 4), 0);
180 // Assign resource to the SdMmc Pci host controller's MMIO BAR.
181 // Enable the SdMmc Pci host controller by setting BME and MSE bits of PCI_CMD register.
183 PciWrite32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4 * Slot
), BarAddr
);
184 PciOr16 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_COMMAND_OFFSET
), (EFI_PCI_COMMAND_BUS_MASTER
| EFI_PCI_COMMAND_MEMORY_SPACE
));
186 // Record the allocated Mmio base address.
188 Private
->MmioBar
[Private
->TotalSdMmcHcs
].SlotNum
++;
189 Private
->MmioBar
[Private
->TotalSdMmcHcs
].MmioBarAddr
[Index
] = BarAddr
;
190 BarAddr
+= (UINT32
)MmioSize
;
192 Private
->TotalSdMmcHcs
++;
193 ASSERT (Private
->TotalSdMmcHcs
< MAX_SD_MMC_HCS
);
200 /// Install SdMmc Host Controller PPI
202 Status
= PeiServicesInstallPpi (&Private
->PpiList
);
204 ASSERT_EFI_ERROR (Status
);