]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Mmc.c
EmbeddedPkg: rename gEfiMmcHostProtocolGuid to gEmbeddedMmcHostProtocolGuid
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / Mmc.c
CommitLineData
1bfda055 1/** @file\r
2 Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.\r
3\r
4ca3c688 4 Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
1bfda055 5\r
878b807a 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1bfda055 7\r
8**/\r
9\r
10#include <Protocol/DevicePath.h>\r
1bfda055 11\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/MemoryAllocationLib.h>\r
15#include <Library/UefiBootServicesTableLib.h>\r
16#include <Library/DevicePathLib.h>\r
1bfda055 17\r
18#include "Mmc.h"\r
19\r
20EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
21 SIGNATURE_32('m','m','c','o'), // MediaId\r
22 TRUE, // RemovableMedia\r
23 FALSE, // MediaPresent\r
24 FALSE, // LogicalPartition\r
25 FALSE, // ReadOnly\r
26 FALSE, // WriteCaching\r
27 512, // BlockSize\r
28 4, // IoAlign\r
29 0, // Pad\r
30 0 // LastBlock\r
31};\r
32\r
33//\r
34// This device structure is serviced as a header.\r
35// Its next field points to the first root bridge device node.\r
36//\r
37LIST_ENTRY mMmcHostPool;\r
38\r
3de99375 39/**\r
40 Event triggered by the timer to check if any cards have been removed\r
41 or if new ones have been plugged in\r
42**/\r
43\r
44EFI_EVENT gCheckCardsEvent;\r
45\r
1bfda055 46/**\r
47 Initialize the MMC Host Pool to support multiple MMC devices\r
48**/\r
49VOID\r
50InitializeMmcHostPool (\r
51 VOID\r
52 )\r
53{\r
e8e95df4 54 InitializeListHead (&mMmcHostPool);\r
1bfda055 55}\r
56\r
57/**\r
58 Insert a new Mmc Host controller to the pool\r
59**/\r
60VOID\r
61InsertMmcHost (\r
62 IN MMC_HOST_INSTANCE *MmcHostInstance\r
63 )\r
64{\r
e8e95df4 65 InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
1bfda055 66}\r
67\r
68/*\r
69 Remove a new Mmc Host controller to the pool\r
70*/\r
71VOID\r
72RemoveMmcHost (\r
73 IN MMC_HOST_INSTANCE *MmcHostInstance\r
74 )\r
75{\r
e8e95df4 76 RemoveEntryList (&(MmcHostInstance->Link));\r
1bfda055 77}\r
78\r
e8e95df4 79MMC_HOST_INSTANCE* CreateMmcHostInstance (\r
1bfda055 80 IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
81 )\r
82{\r
e8e95df4 83 EFI_STATUS Status;\r
84 MMC_HOST_INSTANCE* MmcHostInstance;\r
85 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
86 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1bfda055 87\r
e8e95df4 88 MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
89 if (MmcHostInstance == NULL) {\r
90 return NULL;\r
91 }\r
1bfda055 92\r
e8e95df4 93 MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
1bfda055 94\r
e8e95df4 95 MmcHostInstance->State = MmcHwInitializationState;\r
1bfda055 96\r
e8e95df4 97 MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
98 if (MmcHostInstance->BlockIo.Media == NULL) {\r
99 goto FREE_INSTANCE;\r
100 }\r
1bfda055 101\r
e8e95df4 102 MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
103 MmcHostInstance->BlockIo.Reset = MmcReset;\r
104 MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
105 MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
106 MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
1bfda055 107\r
e8e95df4 108 MmcHostInstance->MmcHost = MmcHost;\r
109\r
110 // Create DevicePath for the new MMC Host\r
16d88c2d 111 Status = MmcHost->BuildDevicePath (MmcHost, &NewDevicePathNode);\r
e8e95df4 112 if (EFI_ERROR (Status)) {\r
113 goto FREE_MEDIA;\r
114 }\r
1bfda055 115\r
e8e95df4 116 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
117 if (DevicePath == NULL) {\r
118 goto FREE_MEDIA;\r
119 }\r
120\r
121 SetDevicePathEndNode (DevicePath);\r
122 MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
123\r
124 // Publish BlockIO protocol interface\r
125 Status = gBS->InstallMultipleProtocolInterfaces (\r
126 &MmcHostInstance->MmcHandle,\r
3de99375 127 &gEfiBlockIoProtocolGuid,&MmcHostInstance->BlockIo,\r
e8e95df4 128 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
129 NULL\r
130 );\r
131 if (EFI_ERROR(Status)) {\r
132 goto FREE_DEVICE_PATH;\r
133 }\r
134\r
135 return MmcHostInstance;\r
1bfda055 136\r
137FREE_DEVICE_PATH:\r
e8e95df4 138 FreePool(DevicePath);\r
1bfda055 139\r
140FREE_MEDIA:\r
e8e95df4 141 FreePool(MmcHostInstance->BlockIo.Media);\r
1bfda055 142\r
143FREE_INSTANCE:\r
e8e95df4 144 FreePool(MmcHostInstance);\r
1bfda055 145\r
e8e95df4 146 return NULL;\r
1bfda055 147}\r
148\r
e8e95df4 149EFI_STATUS DestroyMmcHostInstance (\r
1bfda055 150 IN MMC_HOST_INSTANCE* MmcHostInstance\r
151 )\r
152{\r
e8e95df4 153 EFI_STATUS Status;\r
1bfda055 154\r
e8e95df4 155 // Uninstall Protocol Interfaces\r
156 Status = gBS->UninstallMultipleProtocolInterfaces (\r
6102636a 157 MmcHostInstance->MmcHandle,\r
e8e95df4 158 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
6102636a 159 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
e8e95df4 160 NULL\r
161 );\r
162 ASSERT_EFI_ERROR (Status);\r
1bfda055 163\r
e8e95df4 164 // Free Memory allocated for the instance\r
165 if (MmcHostInstance->BlockIo.Media) {\r
166 FreePool(MmcHostInstance->BlockIo.Media);\r
167 }\r
7bb5fad5
JN
168 if (MmcHostInstance->CardInfo.ECSDData) {\r
169 FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));\r
170 }\r
e8e95df4 171 FreePool (MmcHostInstance);\r
172\r
173 return Status;\r
1bfda055 174}\r
175\r
176/**\r
177 This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
178**/\r
179EFI_STATUS\r
180EFIAPI\r
181MmcDriverBindingSupported (\r
182 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
183 IN EFI_HANDLE Controller,\r
184 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
185 )\r
186{\r
e8e95df4 187 EFI_STATUS Status;\r
188 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
189 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
190 EFI_DEV_PATH_PTR Node;\r
191\r
192 //\r
193 // Check RemainingDevicePath validation\r
194 //\r
195 if (RemainingDevicePath != NULL) {\r
1bfda055 196 //\r
e8e95df4 197 // Check if RemainingDevicePath is the End of Device Path Node,\r
198 // if yes, go on checking other conditions\r
1bfda055 199 //\r
e8e95df4 200 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
201 //\r
202 // If RemainingDevicePath isn't the End of Device Path Node,\r
203 // check its validation\r
204 //\r
205 Node.DevPath = RemainingDevicePath;\r
206 if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
207 Node.DevPath->SubType != HW_VENDOR_DP ||\r
208 DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
209 return EFI_UNSUPPORTED;\r
210 }\r
1bfda055 211 }\r
e8e95df4 212 }\r
213\r
214 //\r
215 // Check if Mmc Host protocol is installed by platform\r
216 //\r
217 Status = gBS->OpenProtocol (\r
218 Controller,\r
2a7a1223 219 &gEmbeddedMmcHostProtocolGuid,\r
e8e95df4 220 (VOID **) &MmcHost,\r
221 This->DriverBindingHandle,\r
222 Controller,\r
223 EFI_OPEN_PROTOCOL_BY_DRIVER\r
224 );\r
225 if (Status == EFI_ALREADY_STARTED) {\r
1bfda055 226 return EFI_SUCCESS;\r
e8e95df4 227 }\r
228 if (EFI_ERROR (Status)) {\r
229 return Status;\r
230 }\r
231\r
232 //\r
233 // Close the Mmc Host used to perform the supported test\r
234 //\r
235 gBS->CloseProtocol (\r
236 Controller,\r
2a7a1223 237 &gEmbeddedMmcHostProtocolGuid,\r
e8e95df4 238 This->DriverBindingHandle,\r
239 Controller\r
240 );\r
241\r
242 return EFI_SUCCESS;\r
1bfda055 243}\r
244\r
245/**\r
3402aac7 246\r
1bfda055 247**/\r
248EFI_STATUS\r
249EFIAPI\r
250MmcDriverBindingStart (\r
251 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
252 IN EFI_HANDLE Controller,\r
253 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
254 )\r
255{\r
e8e95df4 256 EFI_STATUS Status;\r
257 MMC_HOST_INSTANCE *MmcHostInstance;\r
258 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
259\r
260 //\r
261 // Check RemainingDevicePath validation\r
262 //\r
263 if (RemainingDevicePath != NULL) {\r
1bfda055 264 //\r
e8e95df4 265 // Check if RemainingDevicePath is the End of Device Path Node,\r
266 // if yes, return EFI_SUCCESS\r
1bfda055 267 //\r
e8e95df4 268 if (IsDevicePathEnd (RemainingDevicePath)) {\r
269 return EFI_SUCCESS;\r
1bfda055 270 }\r
e8e95df4 271 }\r
272\r
273 //\r
274 // Get the Mmc Host protocol\r
275 //\r
276 Status = gBS->OpenProtocol (\r
277 Controller,\r
2a7a1223 278 &gEmbeddedMmcHostProtocolGuid,\r
e8e95df4 279 (VOID **) &MmcHost,\r
280 This->DriverBindingHandle,\r
281 Controller,\r
282 EFI_OPEN_PROTOCOL_BY_DRIVER\r
283 );\r
284 if (EFI_ERROR (Status)) {\r
285 if (Status == EFI_ALREADY_STARTED) {\r
286 return EFI_SUCCESS;\r
1bfda055 287 }\r
e8e95df4 288 return Status;\r
289 }\r
1bfda055 290\r
e8e95df4 291 MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
292 if (MmcHostInstance != NULL) {\r
293 // Add the handle to the pool\r
294 InsertMmcHost (MmcHostInstance);\r
3de99375 295\r
296 MmcHostInstance->Initialized = FALSE;\r
40842a5e 297\r
298 // Detect card presence now\r
299 CheckCardsCallback (NULL, NULL);\r
e8e95df4 300 }\r
1bfda055 301\r
e8e95df4 302 return EFI_SUCCESS;\r
1bfda055 303}\r
304\r
305/**\r
3402aac7 306\r
1bfda055 307**/\r
308EFI_STATUS\r
309EFIAPI\r
310MmcDriverBindingStop (\r
311 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
312 IN EFI_HANDLE Controller,\r
313 IN UINTN NumberOfChildren,\r
314 IN EFI_HANDLE *ChildHandleBuffer\r
315 )\r
316{\r
e8e95df4 317 EFI_STATUS Status = EFI_SUCCESS;\r
318 LIST_ENTRY *CurrentLink;\r
319 MMC_HOST_INSTANCE *MmcHostInstance;\r
1bfda055 320\r
e8e95df4 321 MMC_TRACE("MmcDriverBindingStop()");\r
322\r
323 // For each MMC instance\r
324 CurrentLink = mMmcHostPool.ForwardLink;\r
325 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
326 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
327 ASSERT(MmcHostInstance != NULL);\r
328\r
2a7a1223 329 // Close gEmbeddedMmcHostProtocolGuid\r
e8e95df4 330 Status = gBS->CloseProtocol (\r
331 Controller,\r
2a7a1223 332 &gEmbeddedMmcHostProtocolGuid,\r
e1b59e08
LE
333 This->DriverBindingHandle,\r
334 Controller\r
e8e95df4 335 );\r
336\r
337 // Remove MMC Host Instance from the pool\r
338 RemoveMmcHost (MmcHostInstance);\r
339\r
340 // Destroy MmcHostInstance\r
341 DestroyMmcHostInstance (MmcHostInstance);\r
342 }\r
343\r
344 return Status;\r
1bfda055 345}\r
346\r
3de99375 347VOID\r
348EFIAPI\r
349CheckCardsCallback (\r
350 IN EFI_EVENT Event,\r
351 IN VOID *Context\r
352 )\r
353{\r
354 LIST_ENTRY *CurrentLink;\r
355 MMC_HOST_INSTANCE *MmcHostInstance;\r
356 EFI_STATUS Status;\r
357\r
358 CurrentLink = mMmcHostPool.ForwardLink;\r
359 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) {\r
360 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
361 ASSERT(MmcHostInstance != NULL);\r
362\r
16d88c2d 363 if (MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost) == !MmcHostInstance->Initialized) {\r
3de99375 364 MmcHostInstance->State = MmcHwInitializationState;\r
365 MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
366 MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
367\r
16d88c2d 368 if (MmcHostInstance->BlockIo.Media->MediaPresent) {\r
369 InitializeMmcDevice (MmcHostInstance);\r
40842a5e 370 }\r
371\r
3de99375 372 Status = gBS->ReinstallProtocolInterface (\r
373 (MmcHostInstance->MmcHandle),\r
374 &gEfiBlockIoProtocolGuid,\r
375 &(MmcHostInstance->BlockIo),\r
376 &(MmcHostInstance->BlockIo)\r
377 );\r
378\r
379 if (EFI_ERROR(Status)) {\r
380 Print(L"MMC Card: Error reinstalling BlockIo interface\n");\r
381 }\r
382 }\r
383\r
384 CurrentLink = CurrentLink->ForwardLink;\r
385 }\r
386}\r
387\r
40842a5e 388\r
1bfda055 389EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
390 MmcDriverBindingSupported,\r
391 MmcDriverBindingStart,\r
392 MmcDriverBindingStop,\r
393 0xa,\r
394 NULL,\r
395 NULL\r
396};\r
397\r
398/**\r
3402aac7 399\r
1bfda055 400**/\r
401EFI_STATUS\r
402EFIAPI\r
403MmcDxeInitialize (\r
404 IN EFI_HANDLE ImageHandle,\r
405 IN EFI_SYSTEM_TABLE *SystemTable\r
406 )\r
407{\r
e8e95df4 408 EFI_STATUS Status;\r
409\r
410 //\r
411 // Initializes MMC Host pool\r
412 //\r
413 InitializeMmcHostPool ();\r
414\r
415 //\r
416 // Install driver model protocol(s).\r
417 //\r
418 Status = EfiLibInstallDriverBindingComponentName2 (\r
419 ImageHandle,\r
420 SystemTable,\r
421 &gMmcDriverBinding,\r
422 ImageHandle,\r
423 &gMmcComponentName,\r
424 &gMmcComponentName2\r
425 );\r
426 ASSERT_EFI_ERROR (Status);\r
427\r
428 // Install driver diagnostics\r
429 Status = gBS->InstallMultipleProtocolInterfaces (\r
430 &ImageHandle,\r
431 &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
432 NULL\r
433 );\r
434 ASSERT_EFI_ERROR (Status);\r
435\r
3de99375 436 // Use a timer to detect if a card has been plugged in or removed\r
437 Status = gBS->CreateEvent (\r
438 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
439 TPL_CALLBACK,\r
440 CheckCardsCallback,\r
441 NULL,\r
442 &gCheckCardsEvent);\r
3402aac7
RC
443 ASSERT_EFI_ERROR (Status);\r
444\r
3de99375 445 Status = gBS->SetTimer(\r
446 gCheckCardsEvent,\r
447 TimerPeriodic,\r
448 (UINT64)(10*1000*200)); // 200 ms\r
449 ASSERT_EFI_ERROR (Status);\r
450\r
e8e95df4 451 return Status;\r
1bfda055 452}\r