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, 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.
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.
16 #include "SdMmcPciHcPei.h"
18 EDKII_SD_MMC_HOST_CONTROLLER_PPI mSdMmcHostControllerPpi
= { GetSdMmcHcMmioBar
};
20 EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
21 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
22 &gEdkiiPeiSdMmcHostControllerPpiGuid
,
23 &mSdMmcHostControllerPpi
27 Get the MMIO base address of SD/MMC host controller.
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.
36 @retval EFI_SUCCESS The operation succeeds.
37 @retval EFI_INVALID_PARAMETER The parameters are invalid.
43 IN EDKII_SD_MMC_HOST_CONTROLLER_PPI
*This
,
44 IN UINT8 ControllerId
,
45 IN OUT UINTN
**MmioBar
,
49 SD_MMC_HC_PEI_PRIVATE_DATA
*Private
;
51 if ((This
== NULL
) || (MmioBar
== NULL
) || (BarNum
== NULL
)) {
52 return EFI_INVALID_PARAMETER
;
55 Private
= SD_MMC_HC_PEI_PRIVATE_DATA_FROM_THIS (This
);
57 if (ControllerId
>= Private
->TotalSdMmcHcs
) {
58 return EFI_INVALID_PARAMETER
;
61 *MmioBar
= &Private
->MmioBar
[ControllerId
].MmioBarAddr
[0];
62 *BarNum
= (UINT8
)Private
->MmioBar
[ControllerId
].SlotNum
;
67 The user code starts with this function.
69 @param FileHandle Handle of the file being invoked.
70 @param PeiServices Describes the list of possible PEI Services.
72 @retval EFI_SUCCESS The driver is successfully initialized.
73 @retval Others Can't initialize the driver.
78 InitializeSdMmcHcPeim (
79 IN EFI_PEI_FILE_HANDLE FileHandle
,
80 IN CONST EFI_PEI_SERVICES
**PeiServices
83 EFI_BOOT_MODE BootMode
;
98 SD_MMC_HC_PEI_PRIVATE_DATA
*Private
;
101 // Shadow this PEIM to run from memory
103 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
107 Status
= PeiServicesGetBootMode (&BootMode
);
109 /// We do not expose this in S3 boot path, because it is only for recovery.
111 if (BootMode
== BOOT_ON_S3_RESUME
) {
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
;
121 Private
->Signature
= SD_MMC_HC_PEI_SIGNATURE
;
122 Private
->SdMmcHostControllerPpi
= mSdMmcHostControllerPpi
;
123 Private
->PpiList
= mPpiList
;
124 Private
->PpiList
.Ppi
= &Private
->SdMmcHostControllerPpi
;
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));
133 if ((SubClass
== PCI_SUBCLASS_SD_HOST_CONTROLLER
) && (BaseClass
== PCI_CLASS_SYSTEM_PERIPHERAL
)) {
135 // Get the SD/MMC Pci host controller's Slot Info.
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
);
142 for (Index
= 0, Slot
= FirstBar
; Slot
< (FirstBar
+ SlotNum
); Index
++, Slot
++) {
144 // Get the SD/MMC Pci host controller's MMIO region size.
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
));
150 switch (Size
& 0x07) {
153 // Memory space: anywhere in 32 bit address space
155 MmioSize
= (~(Size
& 0xFFFFFFF0)) + 1;
159 // Memory space: anywhere in 64 bit address space
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));
165 // Fix the length to support some spefic 64 bit BAR
167 Size
|= ((UINT32
)(-1) << HighBitSet32 (Size
));
169 // Calculate the size of 64bit bar
171 MmioSize
|= LShiftU64 ((UINT64
) Size
, 32);
172 MmioSize
= (~(MmioSize
)) + 1;
174 // Clean the high 32bits of this 64bit BAR to 0 as we only allow a 32bit BAR.
176 PciWrite32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, PCI_BASE_ADDRESSREG_OFFSET
+ 4 * Slot
+ 4), 0);
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.
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
));
192 // Record the allocated Mmio base address.
194 Private
->MmioBar
[Private
->TotalSdMmcHcs
].SlotNum
++;
195 Private
->MmioBar
[Private
->TotalSdMmcHcs
].MmioBarAddr
[Index
] = BarAddr
;
196 BarAddr
+= (UINT32
)MmioSize
;
198 Private
->TotalSdMmcHcs
++;
199 ASSERT (Private
->TotalSdMmcHcs
< MAX_SD_MMC_HCS
);
206 /// Install SdMmc Host Controller PPI
208 Status
= PeiServicesInstallPpi (&Private
->PpiList
);
210 ASSERT_EFI_ERROR (Status
);