]> git.proxmox.com Git - mirror_edk2.git/blame - 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
48555339
FT
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
b5547b9c 7 Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
54228046 8 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
48555339
FT
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
e27ccaba
FT
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
b5547b9c
AS
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
e27ccaba
FT
51 DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));\r
52 DEBUG ((DEBUG_INFO, " SlotType "));\r
48555339 53 if (Capability->SlotType == 0x00) {\r
e27ccaba 54 DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot"));\r
48555339 55 } else if (Capability->SlotType == 0x01) {\r
e27ccaba 56 DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot"));\r
48555339 57 } else if (Capability->SlotType == 0x02) {\r
e27ccaba 58 DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot"));\r
48555339 59 } else {\r
e27ccaba 60 DEBUG ((DEBUG_INFO, "%a\n", "Reserved"));\r
48555339 61 }\r
e27ccaba
FT
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
48555339 69 if (Capability->TimerCount == 0) {\r
e27ccaba 70 DEBUG ((DEBUG_INFO, " Retuning TimerCnt Disabled\n", 2 * (Capability->TimerCount - 1)));\r
48555339 71 } else {\r
e27ccaba 72 DEBUG ((DEBUG_INFO, " Retuning TimerCnt %dseconds\n", 2 * (Capability->TimerCount - 1)));\r
48555339 73 }\r
e27ccaba
FT
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
48555339
FT
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
b5547b9c
AS
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
48555339
FT
451/**\r
452 Software reset the specified SD/MMC host controller and enable all interrupts.\r
453\r
b23fc39c 454 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
48555339
FT
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
b23fc39c 463 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
48555339
FT
464 IN UINT8 Slot\r
465 )\r
466{\r
467 EFI_STATUS Status;\r
468 UINT8 SwReset;\r
b23fc39c 469 EFI_PCI_IO_PROTOCOL *PciIo;\r
48555339 470\r
b23fc39c
AB
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
49c99534
MW
479 EdkiiSdMmcResetPre,\r
480 NULL);\r
b23fc39c
AB
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
064d301f
TM
490 SwReset = BIT0;\r
491 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);\r
48555339
FT
492\r
493 if (EFI_ERROR (Status)) {\r
064d301f 494 DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));\r
48555339
FT
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
064d301f 503 BIT0,\r
48555339
FT
504 0x00,\r
505 SD_MMC_HC_GENERIC_TIMEOUT\r
506 );\r
507 if (EFI_ERROR (Status)) {\r
e27ccaba 508 DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));\r
48555339
FT
509 return Status;\r
510 }\r
b23fc39c 511\r
48555339
FT
512 //\r
513 // Enable all interrupt after reset all.\r
514 //\r
515 Status = SdMmcHcEnableInterrupt (PciIo, Slot);\r
b23fc39c
AB
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
49c99534
MW
530 EdkiiSdMmcResetPost,\r
531 NULL);\r
b23fc39c
AB
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
48555339
FT
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
2e9107b8
FT
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
48555339
FT
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
48555339
FT
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
7f3b0bad 756 @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
b5547b9c 757 @param[in] ControllerVer The version of host controller.\r
48555339
FT
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
b5547b9c
AS
768 IN UINT32 BaseClkFreq,\r
769 IN UINT16 ControllerVer\r
48555339
FT
770 )\r
771{\r
772 EFI_STATUS Status;\r
48555339
FT
773 UINT32 SettingFreq;\r
774 UINT32 Divisor;\r
775 UINT32 Remainder;\r
48555339
FT
776 UINT16 ClockCtrl;\r
777\r
778 //\r
779 // Calculate a divisor for SD clock frequency\r
780 //\r
7f3b0bad 781 ASSERT (BaseClkFreq != 0);\r
48555339 782\r
cb9cb9e2 783 if (ClockFreq == 0) {\r
48555339
FT
784 return EFI_INVALID_PARAMETER;\r
785 }\r
cb9cb9e2
FT
786\r
787 if (ClockFreq > (BaseClkFreq * 1000)) {\r
788 ClockFreq = BaseClkFreq * 1000;\r
789 }\r
790\r
48555339
FT
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
e27ccaba 809 DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));\r
48555339 810\r
48555339
FT
811 //\r
812 // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.\r
813 //\r
b5547b9c
AS
814 if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&\r
815 (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {\r
48555339
FT
816 ASSERT (Divisor <= 0x3FF);\r
817 ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);\r
b5547b9c
AS
818 } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||\r
819 (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {\r
48555339
FT
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
e27ccaba 829 DEBUG ((DEBUG_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));\r
48555339
FT
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
e27ccaba 847 DEBUG ((DEBUG_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));\r
48555339
FT
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
b5547b9c
AS
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
48555339
FT
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
7f3b0bad 1021 @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
b5547b9c 1022 @param[in] ControllerVer The version of host controller.\r
48555339
FT
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
b5547b9c
AS
1032 IN UINT32 BaseClkFreq,\r
1033 IN UINT16 ControllerVer\r
48555339
FT
1034 )\r
1035{\r
1036 EFI_STATUS Status;\r
1037 UINT32 InitFreq;\r
1038\r
1039 //\r
7f3b0bad
MW
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
48555339 1044 //\r
7f3b0bad 1045 if (BaseClkFreq == 0) {\r
48555339
FT
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
b5547b9c 1055 Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);\r
48555339
FT
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
b23fc39c 1151 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
48555339 1152 @param[in] Slot The slot number of the SD card to send the command to.\r
48555339
FT
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
b23fc39c
AB
1160 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1161 IN UINT8 Slot\r
48555339
FT
1162 )\r
1163{\r
b23fc39c
AB
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
49c99534
MW
1176 EdkiiSdMmcInitHostPre,\r
1177 NULL);\r
b23fc39c
AB
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
48555339 1188\r
b5547b9c
AS
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
48555339
FT
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
b23fc39c
AB
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
49c99534
MW
1217 EdkiiSdMmcInitHostPost,\r
1218 NULL);\r
b23fc39c
AB
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
48555339
FT
1225 return Status;\r
1226}\r
1227\r
a4708009
TM
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
48555339
FT
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
b5547b9c 1352 Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.\r
48555339
FT
1353\r
1354 @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
b5547b9c 1355 @param[in] ControllerVer The version of host controller.\r
48555339
FT
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
b5547b9c
AS
1363 IN SD_MMC_HC_TRB *Trb,\r
1364 IN UINT16 ControllerVer\r
48555339
FT
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
b5547b9c 1372 UINT64 Address;\r
48555339
FT
1373 UINTN TableSize;\r
1374 EFI_PCI_IO_PROTOCOL *PciIo;\r
1375 EFI_STATUS Status;\r
1376 UINTN Bytes;\r
b5547b9c
AS
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
48555339
FT
1388\r
1389 Data = Trb->DataPhy;\r
1390 DataLen = Trb->DataLen;\r
1391 PciIo = Trb->Private->PciIo;\r
b5547b9c 1392\r
48555339 1393 //\r
b5547b9c 1394 // Detect whether 64bit addressing is supported.\r
48555339 1395 //\r
b5547b9c
AS
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
48555339
FT
1409 return EFI_INVALID_PARAMETER;\r
1410 }\r
1411 //\r
b5547b9c 1412 // Check address field alignment\r
48555339 1413 //\r
b5547b9c
AS
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
48555339
FT
1437 }\r
1438\r
b5547b9c
AS
1439 Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);\r
1440 TableSize = (UINTN)MultU64x32 (Entries, DescSize);\r
48555339
FT
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
b5547b9c 1447 (VOID **)&AdmaDesc,\r
48555339
FT
1448 0\r
1449 );\r
1450 if (EFI_ERROR (Status)) {\r
1451 return EFI_OUT_OF_RESOURCES;\r
1452 }\r
b5547b9c 1453 ZeroMem (AdmaDesc, TableSize);\r
48555339
FT
1454 Bytes = TableSize;\r
1455 Status = PciIo->Map (\r
1456 PciIo,\r
1457 EfiPciIoOperationBusMasterCommonBuffer,\r
b5547b9c 1458 AdmaDesc,\r
48555339
FT
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
b5547b9c 1471 AdmaDesc\r
48555339
FT
1472 );\r
1473 return EFI_OUT_OF_RESOURCES;\r
1474 }\r
1475\r
b5547b9c
AS
1476 if ((!AddressingMode64) &&\r
1477 (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {\r
48555339
FT
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
b5547b9c 1488 AdmaDesc\r
48555339
FT
1489 );\r
1490 return EFI_DEVICE_ERROR;\r
1491 }\r
1492\r
1493 Remaining = DataLen;\r
b5547b9c
AS
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
48555339 1502 for (Index = 0; Index < Entries; Index++) {\r
b5547b9c
AS
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
48555339 1522 } else {\r
b5547b9c
AS
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
48555339
FT
1543 }\r
1544\r
b5547b9c
AS
1545 Remaining -= AdmaMaxDataPerLine;\r
1546 Address += AdmaMaxDataPerLine;\r
48555339
FT
1547 }\r
1548\r
1549 //\r
1550 // Set the last descriptor line as end of descriptor table\r
1551 //\r
b5547b9c 1552 AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);\r
48555339
FT
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
54228046 1613 if ((Trb->DataLen != 0) && (Trb->DataLen < Trb->BlockSize)) {\r
e7e89b08
FT
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
48555339 1622 } else {\r
e7e89b08
FT
1623 if (Trb->Read) {\r
1624 Flag = EfiPciIoOperationBusMasterWrite;\r
1625 } else {\r
1626 Flag = EfiPciIoOperationBusMasterRead;\r
48555339 1627 }\r
48555339 1628\r
e7e89b08
FT
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
48555339 1644 }\r
48555339 1645\r
e7e89b08
FT
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
b5547b9c 1650 Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
e7e89b08
FT
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
48555339 1659 }\r
48555339
FT
1660 }\r
1661\r
1662 if (Event != NULL) {\r
3b1d8241 1663 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339
FT
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
b5547b9c
AS
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
48555339
FT
1704 PciIo->FreeBuffer (\r
1705 PciIo,\r
1706 Trb->AdmaPages,\r
b5547b9c 1707 Trb->Adma64Desc\r
48555339
FT
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
48555339
FT
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
b5547b9c 1847 UINT32 BlkCount;\r
48555339
FT
1848 UINT16 BlkSize;\r
1849 UINT16 TransMode;\r
1850 UINT8 HostCtrl1;\r
b5547b9c 1851 UINT64 SdmaAddr;\r
48555339 1852 UINT64 AdmaAddr;\r
b5547b9c
AS
1853 BOOLEAN AddressingMode64;\r
1854\r
1855 AddressingMode64 = FALSE;\r
48555339
FT
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
b5547b9c
AS
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
48555339 1896 if (Trb->Mode == SdMmcSdmaMode) {\r
b5547b9c
AS
1897 if ((!AddressingMode64) &&\r
1898 ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {\r
48555339
FT
1899 return EFI_INVALID_PARAMETER;\r
1900 }\r
1901\r
b5547b9c
AS
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
48555339
FT
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
e7e89b08
FT
1934 BlkCount = 0;\r
1935 if (Trb->Mode != SdMmcNoData) {\r
1936 //\r
1937 // Calcuate Block Count.\r
1938 //\r
b5547b9c
AS
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
e7e89b08 1945 }\r
48555339
FT
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
e7e89b08 1964 if (BlkCount > 1) {\r
48555339
FT
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
b5547b9c 2041 UINT64 SdmaAddr;\r
48555339
FT
2042 UINT8 Index;\r
2043 UINT8 SwReset;\r
e7e89b08 2044 UINT32 PioLength;\r
48555339
FT
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
b5547b9c
AS
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
48555339
FT
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
b5547b9c
AS
2185 }\r
2186\r
48555339
FT
2187 if (EFI_ERROR (Status)) {\r
2188 goto Done;\r
2189 }\r
b5547b9c 2190 Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
48555339
FT
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
e7e89b08
FT
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
48555339 2210 //\r
e7e89b08
FT
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
48555339
FT
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