]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHci.c
... / ...
CommitLineData
1/** @file\r
2 This driver is used to manage SD/MMC PCI host controllers which are compliance\r
3 with SD Host Controller Simplified Specification version 3.00.\r
4\r
5 It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.\r
6\r
7 Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
8 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
9 This program and the accompanying materials\r
10 are licensed and made available under the terms and conditions of the BSD License\r
11 which accompanies this distribution. The full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include "SdMmcPciHcDxe.h"\r
20\r
21/**\r
22 Dump the content of SD/MMC host controller's Capability Register.\r
23\r
24 @param[in] Slot The slot number of the SD card to send the command to.\r
25 @param[in] Capability The buffer to store the capability data.\r
26\r
27**/\r
28VOID\r
29DumpCapabilityReg (\r
30 IN UINT8 Slot,\r
31 IN SD_MMC_HC_SLOT_CAP *Capability\r
32 )\r
33{\r
34 //\r
35 // Dump Capability Data\r
36 //\r
37 DEBUG ((DEBUG_INFO, " == Slot [%d] Capability is 0x%x ==\n", Slot, Capability));\r
38 DEBUG ((DEBUG_INFO, " Timeout Clk Freq %d%a\n", Capability->TimeoutFreq, (Capability->TimeoutUnit) ? "MHz" : "KHz"));\r
39 DEBUG ((DEBUG_INFO, " Base Clk Freq %dMHz\n", Capability->BaseClkFreq));\r
40 DEBUG ((DEBUG_INFO, " Max Blk Len %dbytes\n", 512 * (1 << Capability->MaxBlkLen)));\r
41 DEBUG ((DEBUG_INFO, " 8-bit Support %a\n", Capability->BusWidth8 ? "TRUE" : "FALSE"));\r
42 DEBUG ((DEBUG_INFO, " ADMA2 Support %a\n", Capability->Adma2 ? "TRUE" : "FALSE"));\r
43 DEBUG ((DEBUG_INFO, " HighSpeed Support %a\n", Capability->HighSpeed ? "TRUE" : "FALSE"));\r
44 DEBUG ((DEBUG_INFO, " SDMA Support %a\n", Capability->Sdma ? "TRUE" : "FALSE"));\r
45 DEBUG ((DEBUG_INFO, " Suspend/Resume %a\n", Capability->SuspRes ? "TRUE" : "FALSE"));\r
46 DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));\r
47 DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));\r
48 DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));\r
49 DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));\r
50 DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));\r
51 DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));\r
52 DEBUG ((DEBUG_INFO, " SlotType "));\r
53 if (Capability->SlotType == 0x00) {\r
54 DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot"));\r
55 } else if (Capability->SlotType == 0x01) {\r
56 DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot"));\r
57 } else if (Capability->SlotType == 0x02) {\r
58 DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot"));\r
59 } else {\r
60 DEBUG ((DEBUG_INFO, "%a\n", "Reserved"));\r
61 }\r
62 DEBUG ((DEBUG_INFO, " SDR50 Support %a\n", Capability->Sdr50 ? "TRUE" : "FALSE"));\r
63 DEBUG ((DEBUG_INFO, " SDR104 Support %a\n", Capability->Sdr104 ? "TRUE" : "FALSE"));\r
64 DEBUG ((DEBUG_INFO, " DDR50 Support %a\n", Capability->Ddr50 ? "TRUE" : "FALSE"));\r
65 DEBUG ((DEBUG_INFO, " Driver Type A %a\n", Capability->DriverTypeA ? "TRUE" : "FALSE"));\r
66 DEBUG ((DEBUG_INFO, " Driver Type C %a\n", Capability->DriverTypeC ? "TRUE" : "FALSE"));\r
67 DEBUG ((DEBUG_INFO, " Driver Type D %a\n", Capability->DriverTypeD ? "TRUE" : "FALSE"));\r
68 DEBUG ((DEBUG_INFO, " Driver Type 4 %a\n", Capability->DriverType4 ? "TRUE" : "FALSE"));\r
69 if (Capability->TimerCount == 0) {\r
70 DEBUG ((DEBUG_INFO, " Retuning TimerCnt Disabled\n", 2 * (Capability->TimerCount - 1)));\r
71 } else {\r
72 DEBUG ((DEBUG_INFO, " Retuning TimerCnt %dseconds\n", 2 * (Capability->TimerCount - 1)));\r
73 }\r
74 DEBUG ((DEBUG_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));\r
75 DEBUG ((DEBUG_INFO, " Retuning Mode Mode %d\n", Capability->RetuningMod + 1));\r
76 DEBUG ((DEBUG_INFO, " Clock Multiplier M = %d\n", Capability->ClkMultiplier + 1));\r
77 DEBUG ((DEBUG_INFO, " HS 400 %a\n", Capability->Hs400 ? "TRUE" : "FALSE"));\r
78 return;\r
79}\r
80\r
81/**\r
82 Read SlotInfo register from SD/MMC host controller pci config space.\r
83\r
84 @param[in] PciIo The PCI IO protocol instance.\r
85 @param[out] FirstBar The buffer to store the first BAR value.\r
86 @param[out] SlotNum The buffer to store the supported slot number.\r
87\r
88 @retval EFI_SUCCESS The operation succeeds.\r
89 @retval Others The operation fails.\r
90\r
91**/\r
92EFI_STATUS\r
93EFIAPI\r
94SdMmcHcGetSlotInfo (\r
95 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
96 OUT UINT8 *FirstBar,\r
97 OUT UINT8 *SlotNum\r
98 )\r
99{\r
100 EFI_STATUS Status;\r
101 SD_MMC_HC_SLOT_INFO SlotInfo;\r
102\r
103 Status = PciIo->Pci.Read (\r
104 PciIo,\r
105 EfiPciIoWidthUint8,\r
106 SD_MMC_HC_SLOT_OFFSET,\r
107 sizeof (SlotInfo),\r
108 &SlotInfo\r
109 );\r
110 if (EFI_ERROR (Status)) {\r
111 return Status;\r
112 }\r
113\r
114 *FirstBar = SlotInfo.FirstBar;\r
115 *SlotNum = SlotInfo.SlotNum + 1;\r
116 ASSERT ((*FirstBar + *SlotNum) < SD_MMC_HC_MAX_SLOT);\r
117 return EFI_SUCCESS;\r
118}\r
119\r
120/**\r
121 Read/Write specified SD/MMC host controller mmio register.\r
122\r
123 @param[in] PciIo The PCI IO protocol instance.\r
124 @param[in] BarIndex The BAR index of the standard PCI Configuration\r
125 header to use as the base address for the memory\r
126 operation to perform.\r
127 @param[in] Offset The offset within the selected BAR to start the\r
128 memory operation.\r
129 @param[in] Read A boolean to indicate it's read or write operation.\r
130 @param[in] Count The width of the mmio register in bytes.\r
131 Must be 1, 2 , 4 or 8 bytes.\r
132 @param[in, out] Data For read operations, the destination buffer to store\r
133 the results. For write operations, the source buffer\r
134 to write data from. The caller is responsible for\r
135 having ownership of the data buffer and ensuring its\r
136 size not less than Count bytes.\r
137\r
138 @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count is not valid.\r
139 @retval EFI_SUCCESS The read/write operation succeeds.\r
140 @retval Others The read/write operation fails.\r
141\r
142**/\r
143EFI_STATUS\r
144EFIAPI\r
145SdMmcHcRwMmio (\r
146 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
147 IN UINT8 BarIndex,\r
148 IN UINT32 Offset,\r
149 IN BOOLEAN Read,\r
150 IN UINT8 Count,\r
151 IN OUT VOID *Data\r
152 )\r
153{\r
154 EFI_STATUS Status;\r
155\r
156 if ((PciIo == NULL) || (Data == NULL)) {\r
157 return EFI_INVALID_PARAMETER;\r
158 }\r
159\r
160 if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {\r
161 return EFI_INVALID_PARAMETER;\r
162 }\r
163\r
164 if (Read) {\r
165 Status = PciIo->Mem.Read (\r
166 PciIo,\r
167 EfiPciIoWidthUint8,\r
168 BarIndex,\r
169 (UINT64) Offset,\r
170 Count,\r
171 Data\r
172 );\r
173 } else {\r
174 Status = PciIo->Mem.Write (\r
175 PciIo,\r
176 EfiPciIoWidthUint8,\r
177 BarIndex,\r
178 (UINT64) Offset,\r
179 Count,\r
180 Data\r
181 );\r
182 }\r
183\r
184 return Status;\r
185}\r
186\r
187/**\r
188 Do OR operation with the value of the specified SD/MMC host controller mmio register.\r
189\r
190 @param[in] PciIo The PCI IO protocol instance.\r
191 @param[in] BarIndex The BAR index of the standard PCI Configuration\r
192 header to use as the base address for the memory\r
193 operation to perform.\r
194 @param[in] Offset The offset within the selected BAR to start the\r
195 memory operation.\r
196 @param[in] Count The width of the mmio register in bytes.\r
197 Must be 1, 2 , 4 or 8 bytes.\r
198 @param[in] OrData The pointer to the data used to do OR operation.\r
199 The caller is responsible for having ownership of\r
200 the data buffer and ensuring its size not less than\r
201 Count bytes.\r
202\r
203 @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the Count is not valid.\r
204 @retval EFI_SUCCESS The OR operation succeeds.\r
205 @retval Others The OR operation fails.\r
206\r
207**/\r
208EFI_STATUS\r
209EFIAPI\r
210SdMmcHcOrMmio (\r
211 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
212 IN UINT8 BarIndex,\r
213 IN UINT32 Offset,\r
214 IN UINT8 Count,\r
215 IN VOID *OrData\r
216 )\r
217{\r
218 EFI_STATUS Status;\r
219 UINT64 Data;\r
220 UINT64 Or;\r
221\r
222 Status = SdMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);\r
223 if (EFI_ERROR (Status)) {\r
224 return Status;\r
225 }\r
226\r
227 if (Count == 1) {\r
228 Or = *(UINT8*) OrData;\r
229 } else if (Count == 2) {\r
230 Or = *(UINT16*) OrData;\r
231 } else if (Count == 4) {\r
232 Or = *(UINT32*) OrData;\r
233 } else if (Count == 8) {\r
234 Or = *(UINT64*) OrData;\r
235 } else {\r
236 return EFI_INVALID_PARAMETER;\r
237 }\r
238\r
239 Data |= Or;\r
240 Status = SdMmcHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);\r
241\r
242 return Status;\r
243}\r
244\r
245/**\r
246 Do AND operation with the value of the specified SD/MMC host controller mmio register.\r
247\r
248 @param[in] PciIo The PCI IO protocol instance.\r
249 @param[in] BarIndex The BAR index of the standard PCI Configuration\r
250 header to use as the base address for the memory\r
251 operation to perform.\r
252 @param[in] Offset The offset within the selected BAR to start the\r
253 memory operation.\r
254 @param[in] Count The width of the mmio register in bytes.\r
255 Must be 1, 2 , 4 or 8 bytes.\r
256 @param[in] AndData The pointer to the data used to do AND operation.\r
257 The caller is responsible for having ownership of\r
258 the data buffer and ensuring its size not less than\r
259 Count bytes.\r
260\r
261 @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the Count is not valid.\r
262 @retval EFI_SUCCESS The AND operation succeeds.\r
263 @retval Others The AND operation fails.\r
264\r
265**/\r
266EFI_STATUS\r
267EFIAPI\r
268SdMmcHcAndMmio (\r
269 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
270 IN UINT8 BarIndex,\r
271 IN UINT32 Offset,\r
272 IN UINT8 Count,\r
273 IN VOID *AndData\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 UINT64 Data;\r
278 UINT64 And;\r
279\r
280 Status = SdMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);\r
281 if (EFI_ERROR (Status)) {\r
282 return Status;\r
283 }\r
284\r
285 if (Count == 1) {\r
286 And = *(UINT8*) AndData;\r
287 } else if (Count == 2) {\r
288 And = *(UINT16*) AndData;\r
289 } else if (Count == 4) {\r
290 And = *(UINT32*) AndData;\r
291 } else if (Count == 8) {\r
292 And = *(UINT64*) AndData;\r
293 } else {\r
294 return EFI_INVALID_PARAMETER;\r
295 }\r
296\r
297 Data &= And;\r
298 Status = SdMmcHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);\r
299\r
300 return Status;\r
301}\r
302\r
303/**\r
304 Wait for the value of the specified MMIO register set to the test value.\r
305\r
306 @param[in] PciIo The PCI IO protocol instance.\r
307 @param[in] BarIndex The BAR index of the standard PCI Configuration\r
308 header to use as the base address for the memory\r
309 operation to perform.\r
310 @param[in] Offset The offset within the selected BAR to start the\r
311 memory operation.\r
312 @param[in] Count The width of the mmio register in bytes.\r
313 Must be 1, 2, 4 or 8 bytes.\r
314 @param[in] MaskValue The mask value of memory.\r
315 @param[in] TestValue The test value of memory.\r
316\r
317 @retval EFI_NOT_READY The MMIO register hasn't set to the expected value.\r
318 @retval EFI_SUCCESS The MMIO register has expected value.\r
319 @retval Others The MMIO operation fails.\r
320\r
321**/\r
322EFI_STATUS\r
323EFIAPI\r
324SdMmcHcCheckMmioSet (\r
325 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
326 IN UINT8 BarIndex,\r
327 IN UINT32 Offset,\r
328 IN UINT8 Count,\r
329 IN UINT64 MaskValue,\r
330 IN UINT64 TestValue\r
331 )\r
332{\r
333 EFI_STATUS Status;\r
334 UINT64 Value;\r
335\r
336 //\r
337 // Access PCI MMIO space to see if the value is the tested one.\r
338 //\r
339 Value = 0;\r
340 Status = SdMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Value);\r
341 if (EFI_ERROR (Status)) {\r
342 return Status;\r
343 }\r
344\r
345 Value &= MaskValue;\r
346\r
347 if (Value == TestValue) {\r
348 return EFI_SUCCESS;\r
349 }\r
350\r
351 return EFI_NOT_READY;\r
352}\r
353\r
354/**\r
355 Wait for the value of the specified MMIO register set to the test value.\r
356\r
357 @param[in] PciIo The PCI IO protocol instance.\r
358 @param[in] BarIndex The BAR index of the standard PCI Configuration\r
359 header to use as the base address for the memory\r
360 operation to perform.\r
361 @param[in] Offset The offset within the selected BAR to start the\r
362 memory operation.\r
363 @param[in] Count The width of the mmio register in bytes.\r
364 Must be 1, 2, 4 or 8 bytes.\r
365 @param[in] MaskValue The mask value of memory.\r
366 @param[in] TestValue The test value of memory.\r
367 @param[in] Timeout The time out value for wait memory set, uses 1\r
368 microsecond as a unit.\r
369\r
370 @retval EFI_TIMEOUT The MMIO register hasn't expected value in timeout\r
371 range.\r
372 @retval EFI_SUCCESS The MMIO register has expected value.\r
373 @retval Others The MMIO operation fails.\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378SdMmcHcWaitMmioSet (\r
379 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
380 IN UINT8 BarIndex,\r
381 IN UINT32 Offset,\r
382 IN UINT8 Count,\r
383 IN UINT64 MaskValue,\r
384 IN UINT64 TestValue,\r
385 IN UINT64 Timeout\r
386 )\r
387{\r
388 EFI_STATUS Status;\r
389 BOOLEAN InfiniteWait;\r
390\r
391 if (Timeout == 0) {\r
392 InfiniteWait = TRUE;\r
393 } else {\r
394 InfiniteWait = FALSE;\r
395 }\r
396\r
397 while (InfiniteWait || (Timeout > 0)) {\r
398 Status = SdMmcHcCheckMmioSet (\r
399 PciIo,\r
400 BarIndex,\r
401 Offset,\r
402 Count,\r
403 MaskValue,\r
404 TestValue\r
405 );\r
406 if (Status != EFI_NOT_READY) {\r
407 return Status;\r
408 }\r
409\r
410 //\r
411 // Stall for 1 microsecond.\r
412 //\r
413 gBS->Stall (1);\r
414\r
415 Timeout--;\r
416 }\r
417\r
418 return EFI_TIMEOUT;\r
419}\r
420\r
421/**\r
422 Get the controller version information from the specified slot.\r
423\r
424 @param[in] PciIo The PCI IO protocol instance.\r
425 @param[in] Slot The slot number of the SD card to send the command to.\r
426 @param[out] Version The buffer to store the version information.\r
427\r
428 @retval EFI_SUCCESS The operation executes successfully.\r
429 @retval Others The operation fails.\r
430\r
431**/\r
432EFI_STATUS\r
433SdMmcHcGetControllerVersion (\r
434 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
435 IN UINT8 Slot,\r
436 OUT UINT16 *Version\r
437 )\r
438{\r
439 EFI_STATUS Status;\r
440\r
441 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);\r
442 if (EFI_ERROR (Status)) {\r
443 return Status;\r
444 }\r
445\r
446 *Version &= 0xFF;\r
447\r
448 return EFI_SUCCESS;\r
449}\r
450\r
451/**\r
452 Software reset the specified SD/MMC host controller and enable all interrupts.\r
453\r
454 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
455 @param[in] Slot The slot number of the SD card to send the command to.\r
456\r
457 @retval EFI_SUCCESS The software reset executes successfully.\r
458 @retval Others The software reset fails.\r
459\r
460**/\r
461EFI_STATUS\r
462SdMmcHcReset (\r
463 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
464 IN UINT8 Slot\r
465 )\r
466{\r
467 EFI_STATUS Status;\r
468 UINT8 SwReset;\r
469 EFI_PCI_IO_PROTOCOL *PciIo;\r
470\r
471 //\r
472 // Notify the SD/MMC override protocol that we are about to reset\r
473 // the SD/MMC host controller.\r
474 //\r
475 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
476 Status = mOverride->NotifyPhase (\r
477 Private->ControllerHandle,\r
478 Slot,\r
479 EdkiiSdMmcResetPre,\r
480 NULL);\r
481 if (EFI_ERROR (Status)) {\r
482 DEBUG ((DEBUG_WARN,\r
483 "%a: SD/MMC pre reset notifier callback failed - %r\n",\r
484 __FUNCTION__, Status));\r
485 return Status;\r
486 }\r
487 }\r
488\r
489 PciIo = Private->PciIo;\r
490 SwReset = BIT0;\r
491 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);\r
492\r
493 if (EFI_ERROR (Status)) {\r
494 DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));\r
495 return Status;\r
496 }\r
497\r
498 Status = SdMmcHcWaitMmioSet (\r
499 PciIo,\r
500 Slot,\r
501 SD_MMC_HC_SW_RST,\r
502 sizeof (SwReset),\r
503 BIT0,\r
504 0x00,\r
505 SD_MMC_HC_GENERIC_TIMEOUT\r
506 );\r
507 if (EFI_ERROR (Status)) {\r
508 DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));\r
509 return Status;\r
510 }\r
511\r
512 //\r
513 // Enable all interrupt after reset all.\r
514 //\r
515 Status = SdMmcHcEnableInterrupt (PciIo, Slot);\r
516 if (EFI_ERROR (Status)) {\r
517 DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",\r
518 Status));\r
519 return Status;\r
520 }\r
521\r
522 //\r
523 // Notify the SD/MMC override protocol that we have just reset\r
524 // the SD/MMC host controller.\r
525 //\r
526 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
527 Status = mOverride->NotifyPhase (\r
528 Private->ControllerHandle,\r
529 Slot,\r
530 EdkiiSdMmcResetPost,\r
531 NULL);\r
532 if (EFI_ERROR (Status)) {\r
533 DEBUG ((DEBUG_WARN,\r
534 "%a: SD/MMC post reset notifier callback failed - %r\n",\r
535 __FUNCTION__, Status));\r
536 }\r
537 }\r
538\r
539 return Status;\r
540}\r
541\r
542/**\r
543 Set all interrupt status bits in Normal and Error Interrupt Status Enable\r
544 register.\r
545\r
546 @param[in] PciIo The PCI IO protocol instance.\r
547 @param[in] Slot The slot number of the SD card to send the command to.\r
548\r
549 @retval EFI_SUCCESS The operation executes successfully.\r
550 @retval Others The operation fails.\r
551\r
552**/\r
553EFI_STATUS\r
554SdMmcHcEnableInterrupt (\r
555 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
556 IN UINT8 Slot\r
557 )\r
558{\r
559 EFI_STATUS Status;\r
560 UINT16 IntStatus;\r
561\r
562 //\r
563 // Enable all bits in Error Interrupt Status Enable Register\r
564 //\r
565 IntStatus = 0xFFFF;\r
566 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_ERR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);\r
567 if (EFI_ERROR (Status)) {\r
568 return Status;\r
569 }\r
570 //\r
571 // Enable all bits in Normal Interrupt Status Enable Register\r
572 //\r
573 IntStatus = 0xFFFF;\r
574 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_NOR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);\r
575\r
576 return Status;\r
577}\r
578\r
579/**\r
580 Get the capability data from the specified slot.\r
581\r
582 @param[in] PciIo The PCI IO protocol instance.\r
583 @param[in] Slot The slot number of the SD card to send the command to.\r
584 @param[out] Capability The buffer to store the capability data.\r
585\r
586 @retval EFI_SUCCESS The operation executes successfully.\r
587 @retval Others The operation fails.\r
588\r
589**/\r
590EFI_STATUS\r
591SdMmcHcGetCapability (\r
592 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
593 IN UINT8 Slot,\r
594 OUT SD_MMC_HC_SLOT_CAP *Capability\r
595 )\r
596{\r
597 EFI_STATUS Status;\r
598 UINT64 Cap;\r
599\r
600 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CAP, TRUE, sizeof (Cap), &Cap);\r
601 if (EFI_ERROR (Status)) {\r
602 return Status;\r
603 }\r
604\r
605 CopyMem (Capability, &Cap, sizeof (Cap));\r
606\r
607 return EFI_SUCCESS;\r
608}\r
609\r
610/**\r
611 Get the maximum current capability data from the specified slot.\r
612\r
613 @param[in] PciIo The PCI IO protocol instance.\r
614 @param[in] Slot The slot number of the SD card to send the command to.\r
615 @param[out] MaxCurrent The buffer to store the maximum current capability data.\r
616\r
617 @retval EFI_SUCCESS The operation executes successfully.\r
618 @retval Others The operation fails.\r
619\r
620**/\r
621EFI_STATUS\r
622SdMmcHcGetMaxCurrent (\r
623 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
624 IN UINT8 Slot,\r
625 OUT UINT64 *MaxCurrent\r
626 )\r
627{\r
628 EFI_STATUS Status;\r
629\r
630 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_MAX_CURRENT_CAP, TRUE, sizeof (UINT64), MaxCurrent);\r
631\r
632 return Status;\r
633}\r
634\r
635/**\r
636 Detect whether there is a SD/MMC card attached at the specified SD/MMC host controller\r
637 slot.\r
638\r
639 Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.\r
640\r
641 @param[in] PciIo The PCI IO protocol instance.\r
642 @param[in] Slot The slot number of the SD card to send the command to.\r
643 @param[out] MediaPresent The pointer to the media present boolean value.\r
644\r
645 @retval EFI_SUCCESS There is no media change happened.\r
646 @retval EFI_MEDIA_CHANGED There is media change happened.\r
647 @retval Others The detection fails.\r
648\r
649**/\r
650EFI_STATUS\r
651SdMmcHcCardDetect (\r
652 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
653 IN UINT8 Slot,\r
654 OUT BOOLEAN *MediaPresent\r
655 )\r
656{\r
657 EFI_STATUS Status;\r
658 UINT16 Data;\r
659 UINT32 PresentState;\r
660\r
661 //\r
662 // Check Present State Register to see if there is a card presented.\r
663 //\r
664 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
665 if (EFI_ERROR (Status)) {\r
666 return Status;\r
667 }\r
668\r
669 if ((PresentState & BIT16) != 0) {\r
670 *MediaPresent = TRUE;\r
671 } else {\r
672 *MediaPresent = FALSE;\r
673 }\r
674\r
675 //\r
676 // Check Normal Interrupt Status Register\r
677 //\r
678 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_NOR_INT_STS, TRUE, sizeof (Data), &Data);\r
679 if (EFI_ERROR (Status)) {\r
680 return Status;\r
681 }\r
682\r
683 if ((Data & (BIT6 | BIT7)) != 0) {\r
684 //\r
685 // Clear BIT6 and BIT7 by writing 1 to these two bits if set.\r
686 //\r
687 Data &= BIT6 | BIT7;\r
688 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data), &Data);\r
689 if (EFI_ERROR (Status)) {\r
690 return Status;\r
691 }\r
692\r
693 return EFI_MEDIA_CHANGED;\r
694 }\r
695\r
696 return EFI_SUCCESS;\r
697}\r
698\r
699/**\r
700 Stop SD/MMC card clock.\r
701\r
702 Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for details.\r
703\r
704 @param[in] PciIo The PCI IO protocol instance.\r
705 @param[in] Slot The slot number of the SD card to send the command to.\r
706\r
707 @retval EFI_SUCCESS Succeed to stop SD/MMC clock.\r
708 @retval Others Fail to stop SD/MMC clock.\r
709\r
710**/\r
711EFI_STATUS\r
712SdMmcHcStopClock (\r
713 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
714 IN UINT8 Slot\r
715 )\r
716{\r
717 EFI_STATUS Status;\r
718 UINT32 PresentState;\r
719 UINT16 ClockCtrl;\r
720\r
721 //\r
722 // Ensure no SD transactions are occurring on the SD Bus by\r
723 // waiting for Command Inhibit (DAT) and Command Inhibit (CMD)\r
724 // in the Present State register to be 0.\r
725 //\r
726 Status = SdMmcHcWaitMmioSet (\r
727 PciIo,\r
728 Slot,\r
729 SD_MMC_HC_PRESENT_STATE,\r
730 sizeof (PresentState),\r
731 BIT0 | BIT1,\r
732 0,\r
733 SD_MMC_HC_GENERIC_TIMEOUT\r
734 );\r
735 if (EFI_ERROR (Status)) {\r
736 return Status;\r
737 }\r
738\r
739 //\r
740 // Set SD Clock Enable in the Clock Control register to 0\r
741 //\r
742 ClockCtrl = (UINT16)~BIT2;\r
743 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
744\r
745 return Status;\r
746}\r
747\r
748/**\r
749 SD/MMC card clock supply.\r
750\r
751 Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\r
752\r
753 @param[in] PciIo The PCI IO protocol instance.\r
754 @param[in] Slot The slot number of the SD card to send the command to.\r
755 @param[in] ClockFreq The max clock frequency to be set. The unit is KHz.\r
756 @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
757 @param[in] ControllerVer The version of host controller.\r
758\r
759 @retval EFI_SUCCESS The clock is supplied successfully.\r
760 @retval Others The clock isn't supplied successfully.\r
761\r
762**/\r
763EFI_STATUS\r
764SdMmcHcClockSupply (\r
765 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
766 IN UINT8 Slot,\r
767 IN UINT64 ClockFreq,\r
768 IN UINT32 BaseClkFreq,\r
769 IN UINT16 ControllerVer\r
770 )\r
771{\r
772 EFI_STATUS Status;\r
773 UINT32 SettingFreq;\r
774 UINT32 Divisor;\r
775 UINT32 Remainder;\r
776 UINT16 ClockCtrl;\r
777\r
778 //\r
779 // Calculate a divisor for SD clock frequency\r
780 //\r
781 ASSERT (BaseClkFreq != 0);\r
782\r
783 if (ClockFreq == 0) {\r
784 return EFI_INVALID_PARAMETER;\r
785 }\r
786\r
787 if (ClockFreq > (BaseClkFreq * 1000)) {\r
788 ClockFreq = BaseClkFreq * 1000;\r
789 }\r
790\r
791 //\r
792 // Calculate the divisor of base frequency.\r
793 //\r
794 Divisor = 0;\r
795 SettingFreq = BaseClkFreq * 1000;\r
796 while (ClockFreq < SettingFreq) {\r
797 Divisor++;\r
798\r
799 SettingFreq = (BaseClkFreq * 1000) / (2 * Divisor);\r
800 Remainder = (BaseClkFreq * 1000) % (2 * Divisor);\r
801 if ((ClockFreq == SettingFreq) && (Remainder == 0)) {\r
802 break;\r
803 }\r
804 if ((ClockFreq == SettingFreq) && (Remainder != 0)) {\r
805 SettingFreq ++;\r
806 }\r
807 }\r
808\r
809 DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));\r
810\r
811 //\r
812 // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.\r
813 //\r
814 if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&\r
815 (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {\r
816 ASSERT (Divisor <= 0x3FF);\r
817 ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);\r
818 } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||\r
819 (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {\r
820 //\r
821 // Only the most significant bit can be used as divisor.\r
822 //\r
823 if (((Divisor - 1) & Divisor) != 0) {\r
824 Divisor = 1 << (HighBitSet32 (Divisor) + 1);\r
825 }\r
826 ASSERT (Divisor <= 0x80);\r
827 ClockCtrl = (Divisor & 0xFF) << 8;\r
828 } else {\r
829 DEBUG ((DEBUG_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));\r
830 return EFI_UNSUPPORTED;\r
831 }\r
832\r
833 //\r
834 // Stop bus clock at first\r
835 //\r
836 Status = SdMmcHcStopClock (PciIo, Slot);\r
837 if (EFI_ERROR (Status)) {\r
838 return Status;\r
839 }\r
840\r
841 //\r
842 // Supply clock frequency with specified divisor\r
843 //\r
844 ClockCtrl |= BIT0;\r
845 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, FALSE, sizeof (ClockCtrl), &ClockCtrl);\r
846 if (EFI_ERROR (Status)) {\r
847 DEBUG ((DEBUG_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));\r
848 return Status;\r
849 }\r
850\r
851 //\r
852 // Wait Internal Clock Stable in the Clock Control register to be 1\r
853 //\r
854 Status = SdMmcHcWaitMmioSet (\r
855 PciIo,\r
856 Slot,\r
857 SD_MMC_HC_CLOCK_CTRL,\r
858 sizeof (ClockCtrl),\r
859 BIT1,\r
860 BIT1,\r
861 SD_MMC_HC_GENERIC_TIMEOUT\r
862 );\r
863 if (EFI_ERROR (Status)) {\r
864 return Status;\r
865 }\r
866\r
867 //\r
868 // Set SD Clock Enable in the Clock Control register to 1\r
869 //\r
870 ClockCtrl = BIT2;\r
871 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
872\r
873 return Status;\r
874}\r
875\r
876/**\r
877 SD/MMC bus power control.\r
878\r
879 Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.\r
880\r
881 @param[in] PciIo The PCI IO protocol instance.\r
882 @param[in] Slot The slot number of the SD card to send the command to.\r
883 @param[in] PowerCtrl The value setting to the power control register.\r
884\r
885 @retval TRUE There is a SD/MMC card attached.\r
886 @retval FALSE There is no a SD/MMC card attached.\r
887\r
888**/\r
889EFI_STATUS\r
890SdMmcHcPowerControl (\r
891 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
892 IN UINT8 Slot,\r
893 IN UINT8 PowerCtrl\r
894 )\r
895{\r
896 EFI_STATUS Status;\r
897\r
898 //\r
899 // Clr SD Bus Power\r
900 //\r
901 PowerCtrl &= (UINT8)~BIT0;\r
902 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);\r
903 if (EFI_ERROR (Status)) {\r
904 return Status;\r
905 }\r
906\r
907 //\r
908 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register\r
909 //\r
910 PowerCtrl |= BIT0;\r
911 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);\r
912\r
913 return Status;\r
914}\r
915\r
916/**\r
917 Set the SD/MMC bus width.\r
918\r
919 Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for details.\r
920\r
921 @param[in] PciIo The PCI IO protocol instance.\r
922 @param[in] Slot The slot number of the SD card to send the command to.\r
923 @param[in] BusWidth The bus width used by the SD/MMC device, it must be 1, 4 or 8.\r
924\r
925 @retval EFI_SUCCESS The bus width is set successfully.\r
926 @retval Others The bus width isn't set successfully.\r
927\r
928**/\r
929EFI_STATUS\r
930SdMmcHcSetBusWidth (\r
931 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
932 IN UINT8 Slot,\r
933 IN UINT16 BusWidth\r
934 )\r
935{\r
936 EFI_STATUS Status;\r
937 UINT8 HostCtrl1;\r
938\r
939 if (BusWidth == 1) {\r
940 HostCtrl1 = (UINT8)~(BIT5 | BIT1);\r
941 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
942 } else if (BusWidth == 4) {\r
943 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);\r
944 if (EFI_ERROR (Status)) {\r
945 return Status;\r
946 }\r
947 HostCtrl1 |= BIT1;\r
948 HostCtrl1 &= (UINT8)~BIT5;\r
949 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);\r
950 } else if (BusWidth == 8) {\r
951 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);\r
952 if (EFI_ERROR (Status)) {\r
953 return Status;\r
954 }\r
955 HostCtrl1 &= (UINT8)~BIT1;\r
956 HostCtrl1 |= BIT5;\r
957 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);\r
958 } else {\r
959 ASSERT (FALSE);\r
960 return EFI_INVALID_PARAMETER;\r
961 }\r
962\r
963 return Status;\r
964}\r
965\r
966/**\r
967 Configure V4 controller enhancements at initialization.\r
968\r
969 @param[in] PciIo The PCI IO protocol instance.\r
970 @param[in] Slot The slot number of the SD card to send the command to.\r
971 @param[in] Capability The capability of the slot.\r
972 @param[in] ControllerVer The version of host controller.\r
973\r
974 @retval EFI_SUCCESS The clock is supplied successfully.\r
975\r
976**/\r
977EFI_STATUS\r
978SdMmcHcInitV4Enhancements (\r
979 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
980 IN UINT8 Slot,\r
981 IN SD_MMC_HC_SLOT_CAP Capability,\r
982 IN UINT16 ControllerVer\r
983 )\r
984{\r
985 EFI_STATUS Status;\r
986 UINT16 HostCtrl2;\r
987\r
988 //\r
989 // Check if controller version V4 or higher\r
990 //\r
991 if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
992 HostCtrl2 = SD_MMC_HC_V4_EN;\r
993 //\r
994 // Check if V4 64bit support is available\r
995 //\r
996 if (Capability.SysBus64V4 != 0) {\r
997 HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
998 DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
999 }\r
1000 //\r
1001 // Check if controller version V4.10 or higher\r
1002 //\r
1003 if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {\r
1004 HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;\r
1005 DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));\r
1006 }\r
1007 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1008 if (EFI_ERROR (Status)) {\r
1009 return Status;\r
1010 }\r
1011 }\r
1012\r
1013 return EFI_SUCCESS;\r
1014}\r
1015\r
1016/**\r
1017 Supply SD/MMC card with lowest clock frequency at initialization.\r
1018\r
1019 @param[in] PciIo The PCI IO protocol instance.\r
1020 @param[in] Slot The slot number of the SD card to send the command to.\r
1021 @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
1022 @param[in] ControllerVer The version of host controller.\r
1023\r
1024 @retval EFI_SUCCESS The clock is supplied successfully.\r
1025 @retval Others The clock isn't supplied successfully.\r
1026\r
1027**/\r
1028EFI_STATUS\r
1029SdMmcHcInitClockFreq (\r
1030 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1031 IN UINT8 Slot,\r
1032 IN UINT32 BaseClkFreq,\r
1033 IN UINT16 ControllerVer\r
1034 )\r
1035{\r
1036 EFI_STATUS Status;\r
1037 UINT32 InitFreq;\r
1038\r
1039 //\r
1040 // According to SDHCI specification ver. 4.2, BaseClkFreq field value of\r
1041 // the Capability Register 1 can be zero, which means a need for obtaining\r
1042 // the clock frequency via another method. Fail in case it is not updated\r
1043 // by SW at this point.\r
1044 //\r
1045 if (BaseClkFreq == 0) {\r
1046 //\r
1047 // Don't support get Base Clock Frequency information via another method\r
1048 //\r
1049 return EFI_UNSUPPORTED;\r
1050 }\r
1051 //\r
1052 // Supply 400KHz clock frequency at initialization phase.\r
1053 //\r
1054 InitFreq = 400;\r
1055 Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);\r
1056 return Status;\r
1057}\r
1058\r
1059/**\r
1060 Supply SD/MMC card with maximum voltage at initialization.\r
1061\r
1062 Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.\r
1063\r
1064 @param[in] PciIo The PCI IO protocol instance.\r
1065 @param[in] Slot The slot number of the SD card to send the command to.\r
1066 @param[in] Capability The capability of the slot.\r
1067\r
1068 @retval EFI_SUCCESS The voltage is supplied successfully.\r
1069 @retval Others The voltage isn't supplied successfully.\r
1070\r
1071**/\r
1072EFI_STATUS\r
1073SdMmcHcInitPowerVoltage (\r
1074 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1075 IN UINT8 Slot,\r
1076 IN SD_MMC_HC_SLOT_CAP Capability\r
1077 )\r
1078{\r
1079 EFI_STATUS Status;\r
1080 UINT8 MaxVoltage;\r
1081 UINT8 HostCtrl2;\r
1082\r
1083 //\r
1084 // Calculate supported maximum voltage according to SD Bus Voltage Select\r
1085 //\r
1086 if (Capability.Voltage33 != 0) {\r
1087 //\r
1088 // Support 3.3V\r
1089 //\r
1090 MaxVoltage = 0x0E;\r
1091 } else if (Capability.Voltage30 != 0) {\r
1092 //\r
1093 // Support 3.0V\r
1094 //\r
1095 MaxVoltage = 0x0C;\r
1096 } else if (Capability.Voltage18 != 0) {\r
1097 //\r
1098 // Support 1.8V\r
1099 //\r
1100 MaxVoltage = 0x0A;\r
1101 HostCtrl2 = BIT3;\r
1102 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1103 gBS->Stall (5000);\r
1104 if (EFI_ERROR (Status)) {\r
1105 return Status;\r
1106 }\r
1107 } else {\r
1108 ASSERT (FALSE);\r
1109 return EFI_DEVICE_ERROR;\r
1110 }\r
1111\r
1112 //\r
1113 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register\r
1114 //\r
1115 Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);\r
1116\r
1117 return Status;\r
1118}\r
1119\r
1120/**\r
1121 Initialize the Timeout Control register with most conservative value at initialization.\r
1122\r
1123 Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for details.\r
1124\r
1125 @param[in] PciIo The PCI IO protocol instance.\r
1126 @param[in] Slot The slot number of the SD card to send the command to.\r
1127\r
1128 @retval EFI_SUCCESS The timeout control register is configured successfully.\r
1129 @retval Others The timeout control register isn't configured successfully.\r
1130\r
1131**/\r
1132EFI_STATUS\r
1133SdMmcHcInitTimeoutCtrl (\r
1134 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1135 IN UINT8 Slot\r
1136 )\r
1137{\r
1138 EFI_STATUS Status;\r
1139 UINT8 Timeout;\r
1140\r
1141 Timeout = 0x0E;\r
1142 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_TIMEOUT_CTRL, FALSE, sizeof (Timeout), &Timeout);\r
1143\r
1144 return Status;\r
1145}\r
1146\r
1147/**\r
1148 Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value\r
1149 at initialization.\r
1150\r
1151 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1152 @param[in] Slot The slot number of the SD card to send the command to.\r
1153\r
1154 @retval EFI_SUCCESS The host controller is initialized successfully.\r
1155 @retval Others The host controller isn't initialized successfully.\r
1156\r
1157**/\r
1158EFI_STATUS\r
1159SdMmcHcInitHost (\r
1160 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1161 IN UINT8 Slot\r
1162 )\r
1163{\r
1164 EFI_STATUS Status;\r
1165 EFI_PCI_IO_PROTOCOL *PciIo;\r
1166 SD_MMC_HC_SLOT_CAP Capability;\r
1167\r
1168 //\r
1169 // Notify the SD/MMC override protocol that we are about to initialize\r
1170 // the SD/MMC host controller.\r
1171 //\r
1172 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
1173 Status = mOverride->NotifyPhase (\r
1174 Private->ControllerHandle,\r
1175 Slot,\r
1176 EdkiiSdMmcInitHostPre,\r
1177 NULL);\r
1178 if (EFI_ERROR (Status)) {\r
1179 DEBUG ((DEBUG_WARN,\r
1180 "%a: SD/MMC pre init notifier callback failed - %r\n",\r
1181 __FUNCTION__, Status));\r
1182 return Status;\r
1183 }\r
1184 }\r
1185\r
1186 PciIo = Private->PciIo;\r
1187 Capability = Private->Capability[Slot];\r
1188\r
1189 Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);\r
1190 if (EFI_ERROR (Status)) {\r
1191 return Status;\r
1192 }\r
1193\r
1194 Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
1195 if (EFI_ERROR (Status)) {\r
1196 return Status;\r
1197 }\r
1198\r
1199 Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);\r
1200 if (EFI_ERROR (Status)) {\r
1201 return Status;\r
1202 }\r
1203\r
1204 Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);\r
1205 if (EFI_ERROR (Status)) {\r
1206 return Status;\r
1207 }\r
1208\r
1209 //\r
1210 // Notify the SD/MMC override protocol that we are have just initialized\r
1211 // the SD/MMC host controller.\r
1212 //\r
1213 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
1214 Status = mOverride->NotifyPhase (\r
1215 Private->ControllerHandle,\r
1216 Slot,\r
1217 EdkiiSdMmcInitHostPost,\r
1218 NULL);\r
1219 if (EFI_ERROR (Status)) {\r
1220 DEBUG ((DEBUG_WARN,\r
1221 "%a: SD/MMC post init notifier callback failed - %r\n",\r
1222 __FUNCTION__, Status));\r
1223 }\r
1224 }\r
1225 return Status;\r
1226}\r
1227\r
1228/**\r
1229 Set SD Host Controler control 2 registry according to selected speed.\r
1230\r
1231 @param[in] ControllerHandle The handle of the controller.\r
1232 @param[in] PciIo The PCI IO protocol instance.\r
1233 @param[in] Slot The slot number of the SD card to send the command to.\r
1234 @param[in] Timing The timing to select.\r
1235\r
1236 @retval EFI_SUCCESS The timing is set successfully.\r
1237 @retval Others The timing isn't set successfully.\r
1238**/\r
1239EFI_STATUS\r
1240SdMmcHcUhsSignaling (\r
1241 IN EFI_HANDLE ControllerHandle,\r
1242 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1243 IN UINT8 Slot,\r
1244 IN SD_MMC_BUS_MODE Timing\r
1245 )\r
1246{\r
1247 EFI_STATUS Status;\r
1248 UINT8 HostCtrl2;\r
1249\r
1250 HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;\r
1251 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255\r
1256 switch (Timing) {\r
1257 case SdMmcUhsSdr12:\r
1258 HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;\r
1259 break;\r
1260 case SdMmcUhsSdr25:\r
1261 HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;\r
1262 break;\r
1263 case SdMmcUhsSdr50:\r
1264 HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;\r
1265 break;\r
1266 case SdMmcUhsSdr104:\r
1267 HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;\r
1268 break;\r
1269 case SdMmcUhsDdr50:\r
1270 HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;\r
1271 break;\r
1272 case SdMmcMmcLegacy:\r
1273 HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;\r
1274 break;\r
1275 case SdMmcMmcHsSdr:\r
1276 HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;\r
1277 break;\r
1278 case SdMmcMmcHsDdr:\r
1279 HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;\r
1280 break;\r
1281 case SdMmcMmcHs200:\r
1282 HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;\r
1283 break;\r
1284 case SdMmcMmcHs400:\r
1285 HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;\r
1286 break;\r
1287 default:\r
1288 HostCtrl2 = 0;\r
1289 break;\r
1290 }\r
1291 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1292 if (EFI_ERROR (Status)) {\r
1293 return Status;\r
1294 }\r
1295\r
1296 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
1297 Status = mOverride->NotifyPhase (\r
1298 ControllerHandle,\r
1299 Slot,\r
1300 EdkiiSdMmcUhsSignaling,\r
1301 &Timing\r
1302 );\r
1303 if (EFI_ERROR (Status)) {\r
1304 DEBUG ((\r
1305 DEBUG_ERROR,\r
1306 "%a: SD/MMC uhs signaling notifier callback failed - %r\n",\r
1307 __FUNCTION__,\r
1308 Status\r
1309 ));\r
1310 return Status;\r
1311 }\r
1312 }\r
1313\r
1314 return EFI_SUCCESS;\r
1315}\r
1316\r
1317/**\r
1318 Turn on/off LED.\r
1319\r
1320 @param[in] PciIo The PCI IO protocol instance.\r
1321 @param[in] Slot The slot number of the SD card to send the command to.\r
1322 @param[in] On The boolean to turn on/off LED.\r
1323\r
1324 @retval EFI_SUCCESS The LED is turned on/off successfully.\r
1325 @retval Others The LED isn't turned on/off successfully.\r
1326\r
1327**/\r
1328EFI_STATUS\r
1329SdMmcHcLedOnOff (\r
1330 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1331 IN UINT8 Slot,\r
1332 IN BOOLEAN On\r
1333 )\r
1334{\r
1335 EFI_STATUS Status;\r
1336 UINT8 HostCtrl1;\r
1337\r
1338 if (On) {\r
1339 HostCtrl1 = BIT0;\r
1340 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
1341 } else {\r
1342 HostCtrl1 = (UINT8)~BIT0;\r
1343 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
1344 }\r
1345\r
1346 return Status;\r
1347}\r
1348\r
1349/**\r
1350 Build ADMA descriptor table for transfer.\r
1351\r
1352 Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.\r
1353\r
1354 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
1355 @param[in] ControllerVer The version of host controller.\r
1356\r
1357 @retval EFI_SUCCESS The ADMA descriptor table is created successfully.\r
1358 @retval Others The ADMA descriptor table isn't created successfully.\r
1359\r
1360**/\r
1361EFI_STATUS\r
1362BuildAdmaDescTable (\r
1363 IN SD_MMC_HC_TRB *Trb,\r
1364 IN UINT16 ControllerVer\r
1365 )\r
1366{\r
1367 EFI_PHYSICAL_ADDRESS Data;\r
1368 UINT64 DataLen;\r
1369 UINT64 Entries;\r
1370 UINT32 Index;\r
1371 UINT64 Remaining;\r
1372 UINT64 Address;\r
1373 UINTN TableSize;\r
1374 EFI_PCI_IO_PROTOCOL *PciIo;\r
1375 EFI_STATUS Status;\r
1376 UINTN Bytes;\r
1377 BOOLEAN AddressingMode64;\r
1378 BOOLEAN DataLength26;\r
1379 UINT32 AdmaMaxDataPerLine;\r
1380 UINT32 DescSize;\r
1381 VOID *AdmaDesc;\r
1382\r
1383 AddressingMode64 = FALSE;\r
1384 DataLength26 = FALSE;\r
1385 AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;\r
1386 DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);\r
1387 AdmaDesc = NULL;\r
1388\r
1389 Data = Trb->DataPhy;\r
1390 DataLen = Trb->DataLen;\r
1391 PciIo = Trb->Private->PciIo;\r
1392\r
1393 //\r
1394 // Detect whether 64bit addressing is supported.\r
1395 //\r
1396 if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
1397 Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
1398 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
1399 if (!EFI_ERROR (Status)) {\r
1400 AddressingMode64 = TRUE;\r
1401 DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);\r
1402 }\r
1403 }\r
1404 //\r
1405 // Check for valid ranges in 32bit ADMA Descriptor Table\r
1406 //\r
1407 if (!AddressingMode64 &&\r
1408 ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {\r
1409 return EFI_INVALID_PARAMETER;\r
1410 }\r
1411 //\r
1412 // Check address field alignment\r
1413 //\r
1414 if (AddressingMode64) {\r
1415 //\r
1416 // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)\r
1417 //\r
1418 if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {\r
1419 DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));\r
1420 }\r
1421 } else {\r
1422 //\r
1423 // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)\r
1424 //\r
1425 if ((Data & (BIT0 | BIT1)) != 0) {\r
1426 DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
1427 }\r
1428 }\r
1429 //\r
1430 // Detect whether 26bit data length is supported.\r
1431 //\r
1432 Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
1433 SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);\r
1434 if (!EFI_ERROR (Status)) {\r
1435 DataLength26 = TRUE;\r
1436 AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;\r
1437 }\r
1438\r
1439 Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);\r
1440 TableSize = (UINTN)MultU64x32 (Entries, DescSize);\r
1441 Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);\r
1442 Status = PciIo->AllocateBuffer (\r
1443 PciIo,\r
1444 AllocateAnyPages,\r
1445 EfiBootServicesData,\r
1446 EFI_SIZE_TO_PAGES (TableSize),\r
1447 (VOID **)&AdmaDesc,\r
1448 0\r
1449 );\r
1450 if (EFI_ERROR (Status)) {\r
1451 return EFI_OUT_OF_RESOURCES;\r
1452 }\r
1453 ZeroMem (AdmaDesc, TableSize);\r
1454 Bytes = TableSize;\r
1455 Status = PciIo->Map (\r
1456 PciIo,\r
1457 EfiPciIoOperationBusMasterCommonBuffer,\r
1458 AdmaDesc,\r
1459 &Bytes,\r
1460 &Trb->AdmaDescPhy,\r
1461 &Trb->AdmaMap\r
1462 );\r
1463\r
1464 if (EFI_ERROR (Status) || (Bytes != TableSize)) {\r
1465 //\r
1466 // Map error or unable to map the whole RFis buffer into a contiguous region.\r
1467 //\r
1468 PciIo->FreeBuffer (\r
1469 PciIo,\r
1470 EFI_SIZE_TO_PAGES (TableSize),\r
1471 AdmaDesc\r
1472 );\r
1473 return EFI_OUT_OF_RESOURCES;\r
1474 }\r
1475\r
1476 if ((!AddressingMode64) &&\r
1477 (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {\r
1478 //\r
1479 // The ADMA doesn't support 64bit addressing.\r
1480 //\r
1481 PciIo->Unmap (\r
1482 PciIo,\r
1483 Trb->AdmaMap\r
1484 );\r
1485 PciIo->FreeBuffer (\r
1486 PciIo,\r
1487 EFI_SIZE_TO_PAGES (TableSize),\r
1488 AdmaDesc\r
1489 );\r
1490 return EFI_DEVICE_ERROR;\r
1491 }\r
1492\r
1493 Remaining = DataLen;\r
1494 Address = Data;\r
1495 if (!AddressingMode64) {\r
1496 Trb->Adma32Desc = AdmaDesc;\r
1497 Trb->Adma64Desc = NULL;\r
1498 } else {\r
1499 Trb->Adma64Desc = AdmaDesc;\r
1500 Trb->Adma32Desc = NULL;\r
1501 }\r
1502 for (Index = 0; Index < Entries; Index++) {\r
1503 if (!AddressingMode64) {\r
1504 if (Remaining <= AdmaMaxDataPerLine) {\r
1505 Trb->Adma32Desc[Index].Valid = 1;\r
1506 Trb->Adma32Desc[Index].Act = 2;\r
1507 if (DataLength26) {\r
1508 Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);\r
1509 }\r
1510 Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
1511 Trb->Adma32Desc[Index].Address = (UINT32)Address;\r
1512 break;\r
1513 } else {\r
1514 Trb->Adma32Desc[Index].Valid = 1;\r
1515 Trb->Adma32Desc[Index].Act = 2;\r
1516 if (DataLength26) {\r
1517 Trb->Adma32Desc[Index].UpperLength = 0;\r
1518 }\r
1519 Trb->Adma32Desc[Index].LowerLength = 0;\r
1520 Trb->Adma32Desc[Index].Address = (UINT32)Address;\r
1521 }\r
1522 } else {\r
1523 if (Remaining <= AdmaMaxDataPerLine) {\r
1524 Trb->Adma64Desc[Index].Valid = 1;\r
1525 Trb->Adma64Desc[Index].Act = 2;\r
1526 if (DataLength26) {\r
1527 Trb->Adma64Desc[Index].UpperLength = (UINT16)(Remaining >> 16);\r
1528 }\r
1529 Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
1530 Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
1531 Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);\r
1532 break;\r
1533 } else {\r
1534 Trb->Adma64Desc[Index].Valid = 1;\r
1535 Trb->Adma64Desc[Index].Act = 2;\r
1536 if (DataLength26) {\r
1537 Trb->Adma64Desc[Index].UpperLength = 0;\r
1538 }\r
1539 Trb->Adma64Desc[Index].LowerLength = 0;\r
1540 Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
1541 Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);\r
1542 }\r
1543 }\r
1544\r
1545 Remaining -= AdmaMaxDataPerLine;\r
1546 Address += AdmaMaxDataPerLine;\r
1547 }\r
1548\r
1549 //\r
1550 // Set the last descriptor line as end of descriptor table\r
1551 //\r
1552 AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);\r
1553 return EFI_SUCCESS;\r
1554}\r
1555\r
1556/**\r
1557 Create a new TRB for the SD/MMC cmd request.\r
1558\r
1559 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1560 @param[in] Slot The slot number of the SD card to send the command to.\r
1561 @param[in] Packet A pointer to the SD command data structure.\r
1562 @param[in] Event If Event is NULL, blocking I/O is performed. If Event is\r
1563 not NULL, then nonblocking I/O is performed, and Event\r
1564 will be signaled when the Packet completes.\r
1565\r
1566 @return Created Trb or NULL.\r
1567\r
1568**/\r
1569SD_MMC_HC_TRB *\r
1570SdMmcCreateTrb (\r
1571 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1572 IN UINT8 Slot,\r
1573 IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,\r
1574 IN EFI_EVENT Event\r
1575 )\r
1576{\r
1577 SD_MMC_HC_TRB *Trb;\r
1578 EFI_STATUS Status;\r
1579 EFI_TPL OldTpl;\r
1580 EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
1581 EFI_PCI_IO_PROTOCOL *PciIo;\r
1582 UINTN MapLength;\r
1583\r
1584 Trb = AllocateZeroPool (sizeof (SD_MMC_HC_TRB));\r
1585 if (Trb == NULL) {\r
1586 return NULL;\r
1587 }\r
1588\r
1589 Trb->Signature = SD_MMC_HC_TRB_SIG;\r
1590 Trb->Slot = Slot;\r
1591 Trb->BlockSize = 0x200;\r
1592 Trb->Packet = Packet;\r
1593 Trb->Event = Event;\r
1594 Trb->Started = FALSE;\r
1595 Trb->Timeout = Packet->Timeout;\r
1596 Trb->Private = Private;\r
1597\r
1598 if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {\r
1599 Trb->Data = Packet->InDataBuffer;\r
1600 Trb->DataLen = Packet->InTransferLength;\r
1601 Trb->Read = TRUE;\r
1602 } else if ((Packet->OutTransferLength != 0) && (Packet->OutDataBuffer != NULL)) {\r
1603 Trb->Data = Packet->OutDataBuffer;\r
1604 Trb->DataLen = Packet->OutTransferLength;\r
1605 Trb->Read = FALSE;\r
1606 } else if ((Packet->InTransferLength == 0) && (Packet->OutTransferLength == 0)) {\r
1607 Trb->Data = NULL;\r
1608 Trb->DataLen = 0;\r
1609 } else {\r
1610 goto Error;\r
1611 }\r
1612\r
1613 if ((Trb->DataLen != 0) && (Trb->DataLen < Trb->BlockSize)) {\r
1614 Trb->BlockSize = (UINT16)Trb->DataLen;\r
1615 }\r
1616\r
1617 if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
1618 (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
1619 ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
1620 (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
1621 Trb->Mode = SdMmcPioMode;\r
1622 } else {\r
1623 if (Trb->Read) {\r
1624 Flag = EfiPciIoOperationBusMasterWrite;\r
1625 } else {\r
1626 Flag = EfiPciIoOperationBusMasterRead;\r
1627 }\r
1628\r
1629 PciIo = Private->PciIo;\r
1630 if (Trb->DataLen != 0) {\r
1631 MapLength = Trb->DataLen;\r
1632 Status = PciIo->Map (\r
1633 PciIo,\r
1634 Flag,\r
1635 Trb->Data,\r
1636 &MapLength,\r
1637 &Trb->DataPhy,\r
1638 &Trb->DataMap\r
1639 );\r
1640 if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
1641 Status = EFI_BAD_BUFFER_SIZE;\r
1642 goto Error;\r
1643 }\r
1644 }\r
1645\r
1646 if (Trb->DataLen == 0) {\r
1647 Trb->Mode = SdMmcNoData;\r
1648 } else if (Private->Capability[Slot].Adma2 != 0) {\r
1649 Trb->Mode = SdMmcAdmaMode;\r
1650 Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
1651 if (EFI_ERROR (Status)) {\r
1652 PciIo->Unmap (PciIo, Trb->DataMap);\r
1653 goto Error;\r
1654 }\r
1655 } else if (Private->Capability[Slot].Sdma != 0) {\r
1656 Trb->Mode = SdMmcSdmaMode;\r
1657 } else {\r
1658 Trb->Mode = SdMmcPioMode;\r
1659 }\r
1660 }\r
1661\r
1662 if (Event != NULL) {\r
1663 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1664 InsertTailList (&Private->Queue, &Trb->TrbList);\r
1665 gBS->RestoreTPL (OldTpl);\r
1666 }\r
1667\r
1668 return Trb;\r
1669\r
1670Error:\r
1671 SdMmcFreeTrb (Trb);\r
1672 return NULL;\r
1673}\r
1674\r
1675/**\r
1676 Free the resource used by the TRB.\r
1677\r
1678 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
1679\r
1680**/\r
1681VOID\r
1682SdMmcFreeTrb (\r
1683 IN SD_MMC_HC_TRB *Trb\r
1684 )\r
1685{\r
1686 EFI_PCI_IO_PROTOCOL *PciIo;\r
1687\r
1688 PciIo = Trb->Private->PciIo;\r
1689\r
1690 if (Trb->AdmaMap != NULL) {\r
1691 PciIo->Unmap (\r
1692 PciIo,\r
1693 Trb->AdmaMap\r
1694 );\r
1695 }\r
1696 if (Trb->Adma32Desc != NULL) {\r
1697 PciIo->FreeBuffer (\r
1698 PciIo,\r
1699 Trb->AdmaPages,\r
1700 Trb->Adma32Desc\r
1701 );\r
1702 }\r
1703 if (Trb->Adma64Desc != NULL) {\r
1704 PciIo->FreeBuffer (\r
1705 PciIo,\r
1706 Trb->AdmaPages,\r
1707 Trb->Adma64Desc\r
1708 );\r
1709 }\r
1710 if (Trb->DataMap != NULL) {\r
1711 PciIo->Unmap (\r
1712 PciIo,\r
1713 Trb->DataMap\r
1714 );\r
1715 }\r
1716 FreePool (Trb);\r
1717 return;\r
1718}\r
1719\r
1720/**\r
1721 Check if the env is ready for execute specified TRB.\r
1722\r
1723 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1724 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
1725\r
1726 @retval EFI_SUCCESS The env is ready for TRB execution.\r
1727 @retval EFI_NOT_READY The env is not ready for TRB execution.\r
1728 @retval Others Some erros happen.\r
1729\r
1730**/\r
1731EFI_STATUS\r
1732SdMmcCheckTrbEnv (\r
1733 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1734 IN SD_MMC_HC_TRB *Trb\r
1735 )\r
1736{\r
1737 EFI_STATUS Status;\r
1738 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
1739 EFI_PCI_IO_PROTOCOL *PciIo;\r
1740 UINT32 PresentState;\r
1741\r
1742 Packet = Trb->Packet;\r
1743\r
1744 if ((Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc) ||\r
1745 (Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR1b) ||\r
1746 (Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR5b)) {\r
1747 //\r
1748 // Wait Command Inhibit (CMD) and Command Inhibit (DAT) in\r
1749 // the Present State register to be 0\r
1750 //\r
1751 PresentState = BIT0 | BIT1;\r
1752 } else {\r
1753 //\r
1754 // Wait Command Inhibit (CMD) in the Present State register\r
1755 // to be 0\r
1756 //\r
1757 PresentState = BIT0;\r
1758 }\r
1759\r
1760 PciIo = Private->PciIo;\r
1761 Status = SdMmcHcCheckMmioSet (\r
1762 PciIo,\r
1763 Trb->Slot,\r
1764 SD_MMC_HC_PRESENT_STATE,\r
1765 sizeof (PresentState),\r
1766 PresentState,\r
1767 0\r
1768 );\r
1769\r
1770 return Status;\r
1771}\r
1772\r
1773/**\r
1774 Wait for the env to be ready for execute specified TRB.\r
1775\r
1776 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1777 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
1778\r
1779 @retval EFI_SUCCESS The env is ready for TRB execution.\r
1780 @retval EFI_TIMEOUT The env is not ready for TRB execution in time.\r
1781 @retval Others Some erros happen.\r
1782\r
1783**/\r
1784EFI_STATUS\r
1785SdMmcWaitTrbEnv (\r
1786 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1787 IN SD_MMC_HC_TRB *Trb\r
1788 )\r
1789{\r
1790 EFI_STATUS Status;\r
1791 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
1792 UINT64 Timeout;\r
1793 BOOLEAN InfiniteWait;\r
1794\r
1795 //\r
1796 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register\r
1797 //\r
1798 Packet = Trb->Packet;\r
1799 Timeout = Packet->Timeout;\r
1800 if (Timeout == 0) {\r
1801 InfiniteWait = TRUE;\r
1802 } else {\r
1803 InfiniteWait = FALSE;\r
1804 }\r
1805\r
1806 while (InfiniteWait || (Timeout > 0)) {\r
1807 //\r
1808 // Check Trb execution result by reading Normal Interrupt Status register.\r
1809 //\r
1810 Status = SdMmcCheckTrbEnv (Private, Trb);\r
1811 if (Status != EFI_NOT_READY) {\r
1812 return Status;\r
1813 }\r
1814 //\r
1815 // Stall for 1 microsecond.\r
1816 //\r
1817 gBS->Stall (1);\r
1818\r
1819 Timeout--;\r
1820 }\r
1821\r
1822 return EFI_TIMEOUT;\r
1823}\r
1824\r
1825/**\r
1826 Execute the specified TRB.\r
1827\r
1828 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1829 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
1830\r
1831 @retval EFI_SUCCESS The TRB is sent to host controller successfully.\r
1832 @retval Others Some erros happen when sending this request to the host controller.\r
1833\r
1834**/\r
1835EFI_STATUS\r
1836SdMmcExecTrb (\r
1837 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1838 IN SD_MMC_HC_TRB *Trb\r
1839 )\r
1840{\r
1841 EFI_STATUS Status;\r
1842 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
1843 EFI_PCI_IO_PROTOCOL *PciIo;\r
1844 UINT16 Cmd;\r
1845 UINT16 IntStatus;\r
1846 UINT32 Argument;\r
1847 UINT32 BlkCount;\r
1848 UINT16 BlkSize;\r
1849 UINT16 TransMode;\r
1850 UINT8 HostCtrl1;\r
1851 UINT64 SdmaAddr;\r
1852 UINT64 AdmaAddr;\r
1853 BOOLEAN AddressingMode64;\r
1854\r
1855 AddressingMode64 = FALSE;\r
1856\r
1857 Packet = Trb->Packet;\r
1858 PciIo = Trb->Private->PciIo;\r
1859 //\r
1860 // Clear all bits in Error Interrupt Status Register\r
1861 //\r
1862 IntStatus = 0xFFFF;\r
1863 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ERR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1864 if (EFI_ERROR (Status)) {\r
1865 return Status;\r
1866 }\r
1867 //\r
1868 // Clear all bits in Normal Interrupt Status Register excepts for Card Removal & Card Insertion bits.\r
1869 //\r
1870 IntStatus = 0xFF3F;\r
1871 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1872 if (EFI_ERROR (Status)) {\r
1873 return Status;\r
1874 }\r
1875 //\r
1876 // Set Host Control 1 register DMA Select field\r
1877 //\r
1878 if (Trb->Mode == SdMmcAdmaMode) {\r
1879 HostCtrl1 = BIT4;\r
1880 Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
1881 if (EFI_ERROR (Status)) {\r
1882 return Status;\r
1883 }\r
1884 }\r
1885\r
1886 SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);\r
1887\r
1888 if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
1889 Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
1890 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
1891 if (!EFI_ERROR (Status)) {\r
1892 AddressingMode64 = TRUE;\r
1893 }\r
1894 }\r
1895\r
1896 if (Trb->Mode == SdMmcSdmaMode) {\r
1897 if ((!AddressingMode64) &&\r
1898 ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {\r
1899 return EFI_INVALID_PARAMETER;\r
1900 }\r
1901\r
1902 SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;\r
1903\r
1904 if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
1905 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);\r
1906 } else {\r
1907 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);\r
1908 }\r
1909\r
1910 if (EFI_ERROR (Status)) {\r
1911 return Status;\r
1912 }\r
1913 } else if (Trb->Mode == SdMmcAdmaMode) {\r
1914 AdmaAddr = (UINT64)(UINTN)Trb->AdmaDescPhy;\r
1915 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);\r
1916 if (EFI_ERROR (Status)) {\r
1917 return Status;\r
1918 }\r
1919 }\r
1920\r
1921 BlkSize = Trb->BlockSize;\r
1922 if (Trb->Mode == SdMmcSdmaMode) {\r
1923 //\r
1924 // Set SDMA boundary to be 512K bytes.\r
1925 //\r
1926 BlkSize |= 0x7000;\r
1927 }\r
1928\r
1929 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_SIZE, FALSE, sizeof (BlkSize), &BlkSize);\r
1930 if (EFI_ERROR (Status)) {\r
1931 return Status;\r
1932 }\r
1933\r
1934 BlkCount = 0;\r
1935 if (Trb->Mode != SdMmcNoData) {\r
1936 //\r
1937 // Calcuate Block Count.\r
1938 //\r
1939 BlkCount = (Trb->DataLen / Trb->BlockSize);\r
1940 }\r
1941 if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
1942 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);\r
1943 } else {\r
1944 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);\r
1945 }\r
1946 if (EFI_ERROR (Status)) {\r
1947 return Status;\r
1948 }\r
1949\r
1950 Argument = Packet->SdMmcCmdBlk->CommandArgument;\r
1951 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ARG1, FALSE, sizeof (Argument), &Argument);\r
1952 if (EFI_ERROR (Status)) {\r
1953 return Status;\r
1954 }\r
1955\r
1956 TransMode = 0;\r
1957 if (Trb->Mode != SdMmcNoData) {\r
1958 if (Trb->Mode != SdMmcPioMode) {\r
1959 TransMode |= BIT0;\r
1960 }\r
1961 if (Trb->Read) {\r
1962 TransMode |= BIT4;\r
1963 }\r
1964 if (BlkCount > 1) {\r
1965 TransMode |= BIT5 | BIT1;\r
1966 }\r
1967 //\r
1968 // Only SD memory card needs to use AUTO CMD12 feature.\r
1969 //\r
1970 if (Private->Slot[Trb->Slot].CardType == SdCardType) {\r
1971 if (BlkCount > 1) {\r
1972 TransMode |= BIT2;\r
1973 }\r
1974 }\r
1975 }\r
1976\r
1977 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_TRANS_MOD, FALSE, sizeof (TransMode), &TransMode);\r
1978 if (EFI_ERROR (Status)) {\r
1979 return Status;\r
1980 }\r
1981\r
1982 Cmd = (UINT16)LShiftU64(Packet->SdMmcCmdBlk->CommandIndex, 8);\r
1983 if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc) {\r
1984 Cmd |= BIT5;\r
1985 }\r
1986 //\r
1987 // Convert ResponseType to value\r
1988 //\r
1989 if (Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeBc) {\r
1990 switch (Packet->SdMmcCmdBlk->ResponseType) {\r
1991 case SdMmcResponseTypeR1:\r
1992 case SdMmcResponseTypeR5:\r
1993 case SdMmcResponseTypeR6:\r
1994 case SdMmcResponseTypeR7:\r
1995 Cmd |= (BIT1 | BIT3 | BIT4);\r
1996 break;\r
1997 case SdMmcResponseTypeR2:\r
1998 Cmd |= (BIT0 | BIT3);\r
1999 break;\r
2000 case SdMmcResponseTypeR3:\r
2001 case SdMmcResponseTypeR4:\r
2002 Cmd |= BIT1;\r
2003 break;\r
2004 case SdMmcResponseTypeR1b:\r
2005 case SdMmcResponseTypeR5b:\r
2006 Cmd |= (BIT0 | BIT1 | BIT3 | BIT4);\r
2007 break;\r
2008 default:\r
2009 ASSERT (FALSE);\r
2010 break;\r
2011 }\r
2012 }\r
2013 //\r
2014 // Execute cmd\r
2015 //\r
2016 Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_COMMAND, FALSE, sizeof (Cmd), &Cmd);\r
2017 return Status;\r
2018}\r
2019\r
2020/**\r
2021 Check the TRB execution result.\r
2022\r
2023 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
2024 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
2025\r
2026 @retval EFI_SUCCESS The TRB is executed successfully.\r
2027 @retval EFI_NOT_READY The TRB is not completed for execution.\r
2028 @retval Others Some erros happen when executing this request.\r
2029\r
2030**/\r
2031EFI_STATUS\r
2032SdMmcCheckTrbResult (\r
2033 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
2034 IN SD_MMC_HC_TRB *Trb\r
2035 )\r
2036{\r
2037 EFI_STATUS Status;\r
2038 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
2039 UINT16 IntStatus;\r
2040 UINT32 Response[4];\r
2041 UINT64 SdmaAddr;\r
2042 UINT8 Index;\r
2043 UINT8 SwReset;\r
2044 UINT32 PioLength;\r
2045\r
2046 SwReset = 0;\r
2047 Packet = Trb->Packet;\r
2048 //\r
2049 // Check Trb execution result by reading Normal Interrupt Status register.\r
2050 //\r
2051 Status = SdMmcHcRwMmio (\r
2052 Private->PciIo,\r
2053 Trb->Slot,\r
2054 SD_MMC_HC_NOR_INT_STS,\r
2055 TRUE,\r
2056 sizeof (IntStatus),\r
2057 &IntStatus\r
2058 );\r
2059 if (EFI_ERROR (Status)) {\r
2060 goto Done;\r
2061 }\r
2062 //\r
2063 // Check Transfer Complete bit is set or not.\r
2064 //\r
2065 if ((IntStatus & BIT1) == BIT1) {\r
2066 if ((IntStatus & BIT15) == BIT15) {\r
2067 //\r
2068 // Read Error Interrupt Status register to check if the error is\r
2069 // Data Timeout Error.\r
2070 // If yes, treat it as success as Transfer Complete has higher\r
2071 // priority than Data Timeout Error.\r
2072 //\r
2073 Status = SdMmcHcRwMmio (\r
2074 Private->PciIo,\r
2075 Trb->Slot,\r
2076 SD_MMC_HC_ERR_INT_STS,\r
2077 TRUE,\r
2078 sizeof (IntStatus),\r
2079 &IntStatus\r
2080 );\r
2081 if (!EFI_ERROR (Status)) {\r
2082 if ((IntStatus & BIT4) == BIT4) {\r
2083 Status = EFI_SUCCESS;\r
2084 } else {\r
2085 Status = EFI_DEVICE_ERROR;\r
2086 }\r
2087 }\r
2088 }\r
2089\r
2090 goto Done;\r
2091 }\r
2092 //\r
2093 // Check if there is a error happened during cmd execution.\r
2094 // If yes, then do error recovery procedure to follow SD Host Controller\r
2095 // Simplified Spec 3.0 section 3.10.1.\r
2096 //\r
2097 if ((IntStatus & BIT15) == BIT15) {\r
2098 Status = SdMmcHcRwMmio (\r
2099 Private->PciIo,\r
2100 Trb->Slot,\r
2101 SD_MMC_HC_ERR_INT_STS,\r
2102 TRUE,\r
2103 sizeof (IntStatus),\r
2104 &IntStatus\r
2105 );\r
2106 if (EFI_ERROR (Status)) {\r
2107 goto Done;\r
2108 }\r
2109 if ((IntStatus & 0x0F) != 0) {\r
2110 SwReset |= BIT1;\r
2111 }\r
2112 if ((IntStatus & 0xF0) != 0) {\r
2113 SwReset |= BIT2;\r
2114 }\r
2115\r
2116 Status = SdMmcHcRwMmio (\r
2117 Private->PciIo,\r
2118 Trb->Slot,\r
2119 SD_MMC_HC_SW_RST,\r
2120 FALSE,\r
2121 sizeof (SwReset),\r
2122 &SwReset\r
2123 );\r
2124 if (EFI_ERROR (Status)) {\r
2125 goto Done;\r
2126 }\r
2127 Status = SdMmcHcWaitMmioSet (\r
2128 Private->PciIo,\r
2129 Trb->Slot,\r
2130 SD_MMC_HC_SW_RST,\r
2131 sizeof (SwReset),\r
2132 0xFF,\r
2133 0,\r
2134 SD_MMC_HC_GENERIC_TIMEOUT\r
2135 );\r
2136 if (EFI_ERROR (Status)) {\r
2137 goto Done;\r
2138 }\r
2139\r
2140 Status = EFI_DEVICE_ERROR;\r
2141 goto Done;\r
2142 }\r
2143 //\r
2144 // Check if DMA interrupt is signalled for the SDMA transfer.\r
2145 //\r
2146 if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) == BIT3)) {\r
2147 //\r
2148 // Clear DMA interrupt bit.\r
2149 //\r
2150 IntStatus = BIT3;\r
2151 Status = SdMmcHcRwMmio (\r
2152 Private->PciIo,\r
2153 Trb->Slot,\r
2154 SD_MMC_HC_NOR_INT_STS,\r
2155 FALSE,\r
2156 sizeof (IntStatus),\r
2157 &IntStatus\r
2158 );\r
2159 if (EFI_ERROR (Status)) {\r
2160 goto Done;\r
2161 }\r
2162 //\r
2163 // Update SDMA Address register.\r
2164 //\r
2165 SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
2166\r
2167 if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
2168 Status = SdMmcHcRwMmio (\r
2169 Private->PciIo,\r
2170 Trb->Slot,\r
2171 SD_MMC_HC_ADMA_SYS_ADDR,\r
2172 FALSE,\r
2173 sizeof (UINT64),\r
2174 &SdmaAddr\r
2175 );\r
2176 } else {\r
2177 Status = SdMmcHcRwMmio (\r
2178 Private->PciIo,\r
2179 Trb->Slot,\r
2180 SD_MMC_HC_SDMA_ADDR,\r
2181 FALSE,\r
2182 sizeof (UINT32),\r
2183 &SdmaAddr\r
2184 );\r
2185 }\r
2186\r
2187 if (EFI_ERROR (Status)) {\r
2188 goto Done;\r
2189 }\r
2190 Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
2191 }\r
2192\r
2193 if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
2194 (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
2195 (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
2196 if ((IntStatus & BIT0) == BIT0) {\r
2197 Status = EFI_SUCCESS;\r
2198 goto Done;\r
2199 }\r
2200 }\r
2201\r
2202 if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
2203 (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
2204 ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
2205 (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
2206 //\r
2207 // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
2208 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
2209 // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
2210 //\r
2211 if ((IntStatus & BIT5) == BIT5) {\r
2212 //\r
2213 // Clear Buffer Read Ready interrupt at first.\r
2214 //\r
2215 IntStatus = BIT5;\r
2216 SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
2217 //\r
2218 // Read data out from Buffer Port register\r
2219 //\r
2220 for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
2221 SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
2222 }\r
2223 Status = EFI_SUCCESS;\r
2224 goto Done;\r
2225 }\r
2226 }\r
2227\r
2228 Status = EFI_NOT_READY;\r
2229Done:\r
2230 //\r
2231 // Get response data when the cmd is executed successfully.\r
2232 //\r
2233 if (!EFI_ERROR (Status)) {\r
2234 if (Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeBc) {\r
2235 for (Index = 0; Index < 4; Index++) {\r
2236 Status = SdMmcHcRwMmio (\r
2237 Private->PciIo,\r
2238 Trb->Slot,\r
2239 SD_MMC_HC_RESPONSE + Index * 4,\r
2240 TRUE,\r
2241 sizeof (UINT32),\r
2242 &Response[Index]\r
2243 );\r
2244 if (EFI_ERROR (Status)) {\r
2245 SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
2246 return Status;\r
2247 }\r
2248 }\r
2249 CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
2250 }\r
2251 }\r
2252\r
2253 if (Status != EFI_NOT_READY) {\r
2254 SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
2255 }\r
2256\r
2257 return Status;\r
2258}\r
2259\r
2260/**\r
2261 Wait for the TRB execution result.\r
2262\r
2263 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
2264 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
2265\r
2266 @retval EFI_SUCCESS The TRB is executed successfully.\r
2267 @retval Others Some erros happen when executing this request.\r
2268\r
2269**/\r
2270EFI_STATUS\r
2271SdMmcWaitTrbResult (\r
2272 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
2273 IN SD_MMC_HC_TRB *Trb\r
2274 )\r
2275{\r
2276 EFI_STATUS Status;\r
2277 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
2278 UINT64 Timeout;\r
2279 BOOLEAN InfiniteWait;\r
2280\r
2281 Packet = Trb->Packet;\r
2282 //\r
2283 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register\r
2284 //\r
2285 Timeout = Packet->Timeout;\r
2286 if (Timeout == 0) {\r
2287 InfiniteWait = TRUE;\r
2288 } else {\r
2289 InfiniteWait = FALSE;\r
2290 }\r
2291\r
2292 while (InfiniteWait || (Timeout > 0)) {\r
2293 //\r
2294 // Check Trb execution result by reading Normal Interrupt Status register.\r
2295 //\r
2296 Status = SdMmcCheckTrbResult (Private, Trb);\r
2297 if (Status != EFI_NOT_READY) {\r
2298 return Status;\r
2299 }\r
2300 //\r
2301 // Stall for 1 microsecond.\r
2302 //\r
2303 gBS->Stall (1);\r
2304\r
2305 Timeout--;\r
2306 }\r
2307\r
2308 return EFI_TIMEOUT;\r
2309}\r
2310\r