1 /** @file
2   This driver is used to manage Designware SD/MMC PCI host controllers.
3 
4   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
5 
6   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
7   Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
8 
9   This program and the accompanying materials
10   are licensed and made available under the terms and conditions of the BSD License
11   which accompanies this distribution.  The full text of the license may be found at
12   http://opensource.org/licenses/bsd-license.php
13 
14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 
17 **/
18 
19 #include "DwMmcHcDxe.h"
20 
21 /**
22   Dump the content of SD/MMC host controller's Capability Register.
23 
24   @param[in]  Slot            The slot number of the SD card to send the command to.
25   @param[in]  Capability      The buffer to store the capability data.
26 
27 **/
28 VOID
DumpCapabilityReg(IN UINT8 Slot,IN DW_MMC_HC_SLOT_CAP * Capability)29 DumpCapabilityReg (
30   IN UINT8                Slot,
31   IN DW_MMC_HC_SLOT_CAP   *Capability
32   )
33 {
34   //
35   // Dump Capability Data
36   //
37   DEBUG ((DEBUG_INFO, " == Slot [%d] Capability is 0x%x ==\n", Slot, Capability));
38   DEBUG ((DEBUG_INFO, "   Base Clk Freq     %dKHz\n", Capability->BaseClkFreq));
39   DEBUG ((DEBUG_INFO, "   BusWidth          %d\n", Capability->BusWidth));
40   DEBUG ((DEBUG_INFO, "   HighSpeed Support %a\n", Capability->HighSpeed ? "TRUE" : "FALSE"));
41   DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
42   DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
43   DEBUG ((DEBUG_INFO, "   SlotType          "));
44   if (Capability->SlotType == 0x00) {
45     DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot"));
46   } else if (Capability->SlotType == 0x01) {
47     DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot"));
48   } else if (Capability->SlotType == 0x02) {
49     DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot"));
50   } else {
51     DEBUG ((DEBUG_INFO, "%a\n", "Reserved"));
52   }
53   DEBUG ((DEBUG_INFO, "   SDR50  Support    %a\n", Capability->Sdr50 ? "TRUE" : "FALSE"));
54   DEBUG ((DEBUG_INFO, "   SDR104 Support    %a\n", Capability->Sdr104 ? "TRUE" : "FALSE"));
55   DEBUG ((DEBUG_INFO, "   DDR50  Support    %a\n", Capability->Ddr50 ? "TRUE" : "FALSE"));
56   return;
57 }
58 
59 /**
60   Read SlotInfo register from SD/MMC host controller pci config space.
61 
62   @param[in]  PciIo        The PCI IO protocol instance.
63   @param[out] FirstBar     The buffer to store the first BAR value.
64   @param[out] SlotNum      The buffer to store the supported slot number.
65 
66   @retval EFI_SUCCESS      The operation succeeds.
67   @retval Others           The operation fails.
68 
69 **/
70 EFI_STATUS
71 EFIAPI
DwMmcHcGetSlotInfo(IN EFI_PCI_IO_PROTOCOL * PciIo,OUT UINT8 * FirstBar,OUT UINT8 * SlotNum)72 DwMmcHcGetSlotInfo (
73   IN     EFI_PCI_IO_PROTOCOL   *PciIo,
74      OUT UINT8                 *FirstBar,
75      OUT UINT8                 *SlotNum
76   )
77 {
78   EFI_STATUS                   Status;
79   DW_MMC_HC_SLOT_INFO          SlotInfo;
80 
81   Status = PciIo->Pci.Read (
82                         PciIo,
83                         EfiPciIoWidthUint8,
84                         DW_MMC_HC_SLOT_OFFSET,
85                         sizeof (SlotInfo),
86                         &SlotInfo
87                         );
88   if (EFI_ERROR (Status)) {
89     return Status;
90   }
91 
92   *FirstBar = SlotInfo.FirstBar;
93   *SlotNum  = SlotInfo.SlotNum + 1;
94   ASSERT ((*FirstBar + *SlotNum) < DW_MMC_HC_MAX_SLOT);
95   return EFI_SUCCESS;
96 }
97 
98 /**
99   Read/Write specified SD/MMC host controller mmio register.
100 
101   @param[in]      PciIo        The PCI IO protocol instance.
102   @param[in]      BarIndex     The BAR index of the standard PCI Configuration
103                                header to use as the base address for the memory
104                                operation to perform.
105   @param[in]      Offset       The offset within the selected BAR to start the
106                                memory operation.
107   @param[in]      Read         A boolean to indicate it's read or write operation.
108   @param[in]      Count        The width of the mmio register in bytes.
109                                Must be 1, 2 , 4 or 8 bytes.
110   @param[in, out] Data         For read operations, the destination buffer to store
111                                the results. For write operations, the source buffer
112                                to write data from. The caller is responsible for
113                                having ownership of the data buffer and ensuring its
114                                size not less than Count bytes.
115 
116   @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count is not valid.
117   @retval EFI_SUCCESS           The read/write operation succeeds.
118   @retval Others                The read/write operation fails.
119 
120 **/
121 EFI_STATUS
122 EFIAPI
DwMmcHcRwMmio(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 BarIndex,IN UINT32 Offset,IN BOOLEAN Read,IN UINT8 Count,IN OUT VOID * Data)123 DwMmcHcRwMmio (
124   IN     EFI_PCI_IO_PROTOCOL   *PciIo,
125   IN     UINT8                 BarIndex,
126   IN     UINT32                Offset,
127   IN     BOOLEAN               Read,
128   IN     UINT8                 Count,
129   IN OUT VOID                  *Data
130   )
131 {
132   EFI_STATUS                   Status;
133 
134   if ((PciIo == NULL) || (Data == NULL))  {
135     return EFI_INVALID_PARAMETER;
136   }
137 
138   if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {
139     return EFI_INVALID_PARAMETER;
140   }
141 
142   if (Read) {
143     Status = PciIo->Mem.Read (
144                           PciIo,
145                           EfiPciIoWidthUint8,
146                           BarIndex,
147                           (UINT64) Offset,
148                           Count,
149                           Data
150                           );
151   } else {
152     Status = PciIo->Mem.Write (
153                           PciIo,
154                           EfiPciIoWidthUint8,
155                           BarIndex,
156                           (UINT64) Offset,
157                           Count,
158                           Data
159                           );
160   }
161 
162   return Status;
163 }
164 
165 /**
166   Do OR operation with the value of the specified SD/MMC host controller mmio register.
167 
168   @param[in] PciIo             The PCI IO protocol instance.
169   @param[in] BarIndex          The BAR index of the standard PCI Configuration
170                                header to use as the base address for the memory
171                                operation to perform.
172   @param[in] Offset            The offset within the selected BAR to start the
173                                memory operation.
174   @param[in] Count             The width of the mmio register in bytes.
175                                Must be 1, 2 , 4 or 8 bytes.
176   @param[in] OrData            The pointer to the data used to do OR operation.
177                                The caller is responsible for having ownership of
178                                the data buffer and ensuring its size not less than
179                                Count bytes.
180 
181   @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the Count is not valid.
182   @retval EFI_SUCCESS           The OR operation succeeds.
183   @retval Others                The OR operation fails.
184 
185 **/
186 EFI_STATUS
187 EFIAPI
DwMmcHcOrMmio(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 BarIndex,IN UINT32 Offset,IN UINT8 Count,IN VOID * OrData)188 DwMmcHcOrMmio (
189   IN  EFI_PCI_IO_PROTOCOL      *PciIo,
190   IN  UINT8                    BarIndex,
191   IN  UINT32                   Offset,
192   IN  UINT8                    Count,
193   IN  VOID                     *OrData
194   )
195 {
196   EFI_STATUS                   Status;
197   UINT64                       Data;
198   UINT64                       Or;
199 
200   Status = DwMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);
201   if (EFI_ERROR (Status)) {
202     return Status;
203   }
204 
205   if (Count == 1) {
206     Or = *(UINT8*) OrData;
207   } else if (Count == 2) {
208     Or = *(UINT16*) OrData;
209   } else if (Count == 4) {
210     Or = *(UINT32*) OrData;
211   } else if (Count == 8) {
212     Or = *(UINT64*) OrData;
213   } else {
214     return EFI_INVALID_PARAMETER;
215   }
216 
217   Data  |= Or;
218   Status = DwMmcHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);
219 
220   return Status;
221 }
222 
223 /**
224   Do AND operation with the value of the specified SD/MMC host controller mmio register.
225 
226   @param[in] PciIo             The PCI IO protocol instance.
227   @param[in] BarIndex          The BAR index of the standard PCI Configuration
228                                header to use as the base address for the memory
229                                operation to perform.
230   @param[in] Offset            The offset within the selected BAR to start the
231                                memory operation.
232   @param[in] Count             The width of the mmio register in bytes.
233                                Must be 1, 2 , 4 or 8 bytes.
234   @param[in] AndData           The pointer to the data used to do AND operation.
235                                The caller is responsible for having ownership of
236                                the data buffer and ensuring its size not less than
237                                Count bytes.
238 
239   @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the Count is not valid.
240   @retval EFI_SUCCESS           The AND operation succeeds.
241   @retval Others                The AND operation fails.
242 
243 **/
244 EFI_STATUS
245 EFIAPI
DwMmcHcAndMmio(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 BarIndex,IN UINT32 Offset,IN UINT8 Count,IN VOID * AndData)246 DwMmcHcAndMmio (
247   IN  EFI_PCI_IO_PROTOCOL      *PciIo,
248   IN  UINT8                    BarIndex,
249   IN  UINT32                   Offset,
250   IN  UINT8                    Count,
251   IN  VOID                     *AndData
252   )
253 {
254   EFI_STATUS                   Status;
255   UINT64                       Data;
256   UINT64                       And;
257 
258   Status = DwMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);
259   if (EFI_ERROR (Status)) {
260     return Status;
261   }
262 
263   if (Count == 1) {
264     And = *(UINT8*) AndData;
265   } else if (Count == 2) {
266     And = *(UINT16*) AndData;
267   } else if (Count == 4) {
268     And = *(UINT32*) AndData;
269   } else if (Count == 8) {
270     And = *(UINT64*) AndData;
271   } else {
272     return EFI_INVALID_PARAMETER;
273   }
274 
275   Data  &= And;
276   Status = DwMmcHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);
277 
278   return Status;
279 }
280 
281 /**
282   Wait for the value of the specified MMIO register set to the test value.
283 
284   @param[in]  PciIo         The PCI IO protocol instance.
285   @param[in]  BarIndex      The BAR index of the standard PCI Configuration
286                             header to use as the base address for the memory
287                             operation to perform.
288   @param[in]  Offset        The offset within the selected BAR to start the
289                             memory operation.
290   @param[in]  Count         The width of the mmio register in bytes.
291                             Must be 1, 2, 4 or 8 bytes.
292   @param[in]  MaskValue     The mask value of memory.
293   @param[in]  TestValue     The test value of memory.
294 
295   @retval EFI_NOT_READY     The MMIO register hasn't set to the expected value.
296   @retval EFI_SUCCESS       The MMIO register has expected value.
297   @retval Others            The MMIO operation fails.
298 
299 **/
300 EFI_STATUS
301 EFIAPI
DwMmcHcCheckMmioSet(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 BarIndex,IN UINT32 Offset,IN UINT8 Count,IN UINT64 MaskValue,IN UINT64 TestValue)302 DwMmcHcCheckMmioSet (
303   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
304   IN  UINT8                     BarIndex,
305   IN  UINT32                    Offset,
306   IN  UINT8                     Count,
307   IN  UINT64                    MaskValue,
308   IN  UINT64                    TestValue
309   )
310 {
311   EFI_STATUS            Status;
312   UINT64                Value;
313 
314   //
315   // Access PCI MMIO space to see if the value is the tested one.
316   //
317   Value  = 0;
318   Status = DwMmcHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Value);
319   if (EFI_ERROR (Status)) {
320     return Status;
321   }
322 
323   Value &= MaskValue;
324 
325   if (Value == TestValue) {
326     return EFI_SUCCESS;
327   }
328 
329   return EFI_NOT_READY;
330 }
331 
332 /**
333   Wait for the value of the specified MMIO register set to the test value.
334 
335   @param[in]  PciIo         The PCI IO protocol instance.
336   @param[in]  BarIndex      The BAR index of the standard PCI Configuration
337                             header to use as the base address for the memory
338                             operation to perform.
339   @param[in]  Offset        The offset within the selected BAR to start the
340                             memory operation.
341   @param[in]  Count         The width of the mmio register in bytes.
342                             Must be 1, 2, 4 or 8 bytes.
343   @param[in]  MaskValue     The mask value of memory.
344   @param[in]  TestValue     The test value of memory.
345   @param[in]  Timeout       The time out value for wait memory set, uses 1
346                             microsecond as a unit.
347 
348   @retval EFI_TIMEOUT       The MMIO register hasn't expected value in timeout
349                             range.
350   @retval EFI_SUCCESS       The MMIO register has expected value.
351   @retval Others            The MMIO operation fails.
352 
353 **/
354 EFI_STATUS
355 EFIAPI
DwMmcHcWaitMmioSet(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 BarIndex,IN UINT32 Offset,IN UINT8 Count,IN UINT64 MaskValue,IN UINT64 TestValue,IN UINT64 Timeout)356 DwMmcHcWaitMmioSet (
357   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
358   IN  UINT8                     BarIndex,
359   IN  UINT32                    Offset,
360   IN  UINT8                     Count,
361   IN  UINT64                    MaskValue,
362   IN  UINT64                    TestValue,
363   IN  UINT64                    Timeout
364   )
365 {
366   EFI_STATUS            Status;
367   BOOLEAN               InfiniteWait;
368 
369   if (Timeout == 0) {
370     InfiniteWait = TRUE;
371   } else {
372     InfiniteWait = FALSE;
373   }
374 
375   while (InfiniteWait || (Timeout > 0)) {
376     Status = DwMmcHcCheckMmioSet (
377                PciIo,
378                BarIndex,
379                Offset,
380                Count,
381                MaskValue,
382                TestValue
383                );
384     if (Status != EFI_NOT_READY) {
385       return Status;
386     }
387 
388     //
389     // Stall for 1 microsecond.
390     //
391     gBS->Stall (1);
392 
393     Timeout--;
394   }
395 
396   return EFI_TIMEOUT;
397 }
398 
399 /**
400   Set all interrupt status bits in Normal and Error Interrupt Status Enable
401   register.
402 
403   @param[in] PciIo          The PCI IO protocol instance.
404   @param[in] Slot           The slot number of the SD card to send the command to.
405 
406   @retval EFI_SUCCESS       The operation executes successfully.
407   @retval Others            The operation fails.
408 
409 **/
410 EFI_STATUS
DwMmcHcEnableInterrupt(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot)411 DwMmcHcEnableInterrupt (
412   IN EFI_PCI_IO_PROTOCOL    *PciIo,
413   IN UINT8                  Slot
414   )
415 {
416   EFI_STATUS                Status;
417   UINT32                    IntStatus;
418   UINT32                    IdIntEn;
419   UINT32                    IdSts;
420 
421   //
422   // Enable all bits in Interrupt Mask Register
423   //
424   IntStatus = 0;
425   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_INTMASK, FALSE, sizeof (IntStatus), &IntStatus);
426   if (EFI_ERROR (Status)) {
427     return Status;
428   }
429 
430   //
431   // Clear status in Interrupt Status Register
432   //
433   IntStatus = ~0;
434   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_RINTSTS, FALSE, sizeof (IntStatus), &IntStatus);
435   if (EFI_ERROR (Status)) {
436     return Status;
437   }
438 
439   IdIntEn = ~0;
440   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_IDINTEN, FALSE, sizeof (IdIntEn), &IdIntEn);
441   if (EFI_ERROR (Status)) {
442     DEBUG ((DEBUG_ERROR, "DwMmcHcReset: init dma interrupts fail: %r\n", Status));
443     return Status;
444   }
445 
446   IdSts = ~0;
447   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_IDSTS, FALSE, sizeof (IdSts), &IdSts);
448   return Status;
449 }
450 
451 /**
452   Get the capability data from the specified slot.
453 
454   @param[in]  PciIo           The PCI IO protocol instance.
455   @param[in]  Slot            The slot number of the SD card to send the command to.
456   @param[out] Capability      The buffer to store the capability data.
457 
458   @retval EFI_SUCCESS         The operation executes successfully.
459   @retval Others              The operation fails.
460 
461 **/
462 EFI_STATUS
DwMmcHcGetCapability(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_HANDLE Controller,IN UINT8 Slot,OUT DW_MMC_HC_SLOT_CAP * Capacity)463 DwMmcHcGetCapability (
464   IN     EFI_PCI_IO_PROTOCOL  *PciIo,
465   IN     EFI_HANDLE           Controller,
466   IN     UINT8                Slot,
467      OUT DW_MMC_HC_SLOT_CAP   *Capacity
468   )
469 {
470   PLATFORM_DW_MMC_PROTOCOL    *PlatformDwMmc;
471   EFI_STATUS                Status;
472 
473   if (Capacity == NULL) {
474     return EFI_INVALID_PARAMETER;
475   }
476   Status = gBS->LocateProtocol (
477                   &gPlatformDwMmcProtocolGuid,
478                   NULL,
479                   (VOID **) &PlatformDwMmc
480                   );
481   if (EFI_ERROR (Status)) {
482     return Status;
483   }
484   Status = PlatformDwMmc->GetCapability (Controller, Slot, Capacity);
485   return Status;
486 }
487 
488 /**
489   Get the maximum current capability data from the specified slot.
490 
491   @param[in]  PciIo           The PCI IO protocol instance.
492   @param[in]  Slot            The slot number of the SD card to send the command to.
493   @param[out] MaxCurrent      The buffer to store the maximum current capability data.
494 
495   @retval EFI_SUCCESS         The operation executes successfully.
496   @retval Others              The operation fails.
497 
498 **/
499 EFI_STATUS
DwMmcHcGetMaxCurrent(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,OUT UINT64 * MaxCurrent)500 DwMmcHcGetMaxCurrent (
501   IN     EFI_PCI_IO_PROTOCOL  *PciIo,
502   IN     UINT8                Slot,
503      OUT UINT64               *MaxCurrent
504   )
505 {
506   return EFI_SUCCESS;
507 }
508 
509 /**
510   Detect whether there is a SD/MMC card attached at the specified SD/MMC host controller
511   slot.
512 
513   Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.
514 
515   @param[in]  PciIo         The PCI IO protocol instance.
516   @param[in]  Slot          The slot number of the SD card to send the command to.
517   @param[out] MediaPresent  The pointer to the media present boolean value.
518 
519   @retval EFI_SUCCESS       There is no media change happened.
520   @retval EFI_MEDIA_CHANGED There is media change happened.
521   @retval Others            The detection fails.
522 
523 **/
524 EFI_STATUS
DwMmcHcCardDetect(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_HANDLE Controller,IN UINT8 Slot,OUT BOOLEAN * MediaPresent)525 DwMmcHcCardDetect (
526   IN EFI_PCI_IO_PROTOCOL    *PciIo,
527   IN EFI_HANDLE             Controller,
528   IN UINT8                  Slot,
529      OUT BOOLEAN            *MediaPresent
530   )
531 {
532   PLATFORM_DW_MMC_PROTOCOL  *PlatformDwMmc;
533   EFI_STATUS                Status;
534 
535   if (MediaPresent == NULL) {
536     return EFI_INVALID_PARAMETER;
537   }
538   Status = gBS->LocateProtocol (
539                   &gPlatformDwMmcProtocolGuid,
540                   NULL,
541                   (VOID **) &PlatformDwMmc
542                   );
543   if (EFI_ERROR (Status)) {
544     return Status;
545   }
546   *MediaPresent = PlatformDwMmc->CardDetect (Controller, Slot);
547   return EFI_SUCCESS;
548 }
549 
550 STATIC
551 EFI_STATUS
DwMmcHcUpdateClock(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot)552 DwMmcHcUpdateClock (
553   IN EFI_PCI_IO_PROTOCOL    *PciIo,
554   IN UINT8                  Slot
555   )
556 {
557   EFI_STATUS                Status;
558   UINT32                    Cmd;
559   UINT32                    IntStatus;
560 
561   Cmd = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
562         BIT_CMD_START;
563   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CMD, FALSE, sizeof (Cmd), &Cmd);
564   if (EFI_ERROR (Status)) {
565     return Status;
566   }
567   while (1) {
568     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CMD, TRUE, sizeof (Cmd), &Cmd);
569     if (EFI_ERROR (Status)) {
570       return Status;
571     }
572     if (!(Cmd & CMD_START_BIT)) {
573       break;
574     }
575     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_RINTSTS, TRUE, sizeof (IntStatus), &IntStatus);
576     if (EFI_ERROR (Status)) {
577       return Status;
578     }
579     if (IntStatus & DW_MMC_INT_HLE) {
580       DEBUG ((DEBUG_ERROR, "DwMmcHcUpdateClock: failed to update mmc clock frequency\n"));
581       return EFI_DEVICE_ERROR;
582     }
583   }
584   return EFI_SUCCESS;
585 
586 }
587 
588 /**
589   Stop SD/MMC card clock.
590 
591   @param[in] PciIo          The PCI IO protocol instance.
592   @param[in] Slot           The slot number of the SD card to send the command to.
593 
594   @retval EFI_SUCCESS       Succeed to stop SD/MMC clock.
595   @retval Others            Fail to stop SD/MMC clock.
596 
597 **/
598 EFI_STATUS
DwMmcHcStopClock(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot)599 DwMmcHcStopClock (
600   IN EFI_PCI_IO_PROTOCOL    *PciIo,
601   IN UINT8                  Slot
602   )
603 {
604   EFI_STATUS                Status;
605   UINT32                    ClkEna;
606 
607   // Disable MMC clock first
608   ClkEna = 0;
609   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CLKENA, FALSE, sizeof (ClkEna), &ClkEna);
610   if (EFI_ERROR (Status)) {
611     return Status;
612   }
613   Status = DwMmcHcUpdateClock (PciIo, Slot);
614   if (EFI_ERROR (Status)) {
615     return Status;
616   }
617   return Status;
618 }
619 
620 /**
621   SD/MMC card clock supply.
622 
623   @param[in] PciIo          The PCI IO protocol instance.
624   @param[in] Slot           The slot number of the SD card to send the command to.
625   @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
626   @param[in] Capability     The capability of the slot.
627 
628   @retval EFI_SUCCESS       The clock is supplied successfully.
629   @retval Others            The clock isn't supplied successfully.
630 
631 **/
632 EFI_STATUS
DwMmcHcClockSupply(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN UINT64 ClockFreq,IN DW_MMC_HC_SLOT_CAP Capability)633 DwMmcHcClockSupply (
634   IN EFI_PCI_IO_PROTOCOL    *PciIo,
635   IN UINT8                  Slot,
636   IN UINT64                 ClockFreq,
637   IN DW_MMC_HC_SLOT_CAP     Capability
638   )
639 {
640   EFI_STATUS                Status;
641   UINT32                    BaseClkFreq;
642   UINT32                    SettingFreq;
643   UINT32                    Divisor;
644   UINT32                    Remainder;
645   UINT32                    MmcStatus;
646   UINT32                    ClkEna;
647   UINT32                    ClkSrc;
648 
649   //
650   // Calculate a divisor for SD clock frequency
651   //
652   ASSERT (Capability.BaseClkFreq != 0);
653 
654   BaseClkFreq = Capability.BaseClkFreq;
655   if (ClockFreq == 0) {
656     return EFI_INVALID_PARAMETER;
657   }
658 
659   if (ClockFreq > BaseClkFreq) {
660     ClockFreq = BaseClkFreq;
661   }
662 
663   //
664   // Calculate the divisor of base frequency.
665   //
666   Divisor     = 0;
667   SettingFreq = BaseClkFreq;
668   while (ClockFreq < SettingFreq) {
669     Divisor++;
670 
671     SettingFreq = BaseClkFreq / (2 * Divisor);
672     Remainder   = BaseClkFreq % (2 * Divisor);
673     if ((ClockFreq == SettingFreq) && (Remainder == 0)) {
674       break;
675     }
676     if ((ClockFreq == SettingFreq) && (Remainder != 0)) {
677       SettingFreq ++;
678     }
679   }
680 
681   DEBUG ((DEBUG_INFO, "BaseClkFreq %dKHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
682 
683   // Wait until MMC is idle
684   do {
685     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_STATUS, TRUE, sizeof (MmcStatus), &MmcStatus);
686     if (EFI_ERROR (Status)) {
687       return Status;
688     }
689   } while (MmcStatus & DW_MMC_STS_DATA_BUSY);
690 
691   do {
692     Status = DwMmcHcStopClock (PciIo, Slot);
693   } while (EFI_ERROR (Status));
694 
695   do {
696     ClkSrc = 0;
697     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CLKSRC, FALSE, sizeof (ClkSrc), &ClkSrc);
698     if (EFI_ERROR (Status)) {
699       continue;
700     }
701     // Set clock divisor
702     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CLKDIV, FALSE, sizeof (Divisor), &Divisor);
703     if (EFI_ERROR (Status)) {
704       continue;
705     }
706     // Enable MMC clock
707     ClkEna = 1;
708     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CLKENA, FALSE, sizeof (ClkEna), &ClkEna);
709     if (EFI_ERROR (Status)) {
710       continue;
711     }
712     Status = DwMmcHcUpdateClock (PciIo, Slot);
713   } while (EFI_ERROR (Status));
714 
715   return EFI_SUCCESS;
716 }
717 
718 /**
719   SD/MMC bus power control.
720 
721   Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.
722 
723   @param[in] PciIo          The PCI IO protocol instance.
724   @param[in] Slot           The slot number of the SD card to send the command to.
725   @param[in] PowerCtrl      The value setting to the power control register.
726 
727   @retval TRUE              There is a SD/MMC card attached.
728   @retval FALSE             There is no a SD/MMC card attached.
729 
730 **/
731 EFI_STATUS
DwMmcHcPowerControl(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN UINT8 PowerCtrl)732 DwMmcHcPowerControl (
733   IN EFI_PCI_IO_PROTOCOL    *PciIo,
734   IN UINT8                  Slot,
735   IN UINT8                  PowerCtrl
736   )
737 {
738   return EFI_SUCCESS;
739 }
740 
741 /**
742   Set the SD/MMC bus width.
743 
744   Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for details.
745 
746   @param[in] PciIo          The PCI IO protocol instance.
747   @param[in] Slot           The slot number of the SD card to send the command to.
748   @param[in] BusWidth       The bus width used by the SD/MMC device, it must be 1, 4 or 8.
749 
750   @retval EFI_SUCCESS       The bus width is set successfully.
751   @retval Others            The bus width isn't set successfully.
752 
753 **/
754 EFI_STATUS
DwMmcHcSetBusWidth(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN BOOLEAN IsDdr,IN UINT16 BusWidth)755 DwMmcHcSetBusWidth (
756   IN EFI_PCI_IO_PROTOCOL    *PciIo,
757   IN UINT8                  Slot,
758   IN BOOLEAN                IsDdr,
759   IN UINT16                 BusWidth
760   )
761 {
762   EFI_STATUS                Status;
763   UINT32                    Ctype;
764   UINT32                    Uhs;
765 
766   switch (BusWidth) {
767   case 1:
768     Ctype = MMC_1BIT_MODE;
769     break;
770   case 4:
771     Ctype = MMC_4BIT_MODE;
772     break;
773   case 8:
774     Ctype = MMC_8BIT_MODE;
775     break;
776   default:
777     return EFI_INVALID_PARAMETER;
778   }
779   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CTYPE, FALSE, sizeof (Ctype), &Ctype);
780   if (EFI_ERROR (Status)) {
781     return Status;
782   }
783   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_UHSREG, TRUE, sizeof (Uhs), &Uhs);
784   if (EFI_ERROR (Status)) {
785     return Status;
786   }
787   if (IsDdr) {
788     Uhs |= UHS_DDR_MODE;
789   } else {
790     Uhs &= ~(UHS_DDR_MODE);
791   }
792   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_UHSREG, FALSE, sizeof (Uhs), &Uhs);
793   return Status;
794 }
795 
796 /**
797   Supply SD/MMC card with lowest clock frequency at initialization.
798 
799   @param[in] PciIo          The PCI IO protocol instance.
800   @param[in] Slot           The slot number of the SD card to send the command to.
801   @param[in] Capability     The capability of the slot.
802 
803   @retval EFI_SUCCESS       The clock is supplied successfully.
804   @retval Others            The clock isn't supplied successfully.
805 
806 **/
807 EFI_STATUS
DwMmcHcInitClockFreq(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN DW_MMC_HC_SLOT_CAP Capability)808 DwMmcHcInitClockFreq (
809   IN EFI_PCI_IO_PROTOCOL    *PciIo,
810   IN UINT8                  Slot,
811   IN DW_MMC_HC_SLOT_CAP     Capability
812   )
813 {
814   EFI_STATUS                Status;
815   UINT32                    InitFreq;
816 
817   //
818   // Calculate a divisor for SD clock frequency
819   //
820   if (Capability.BaseClkFreq == 0) {
821     //
822     // Don't support get Base Clock Frequency information via another method
823     //
824     return EFI_UNSUPPORTED;
825   }
826   //
827   // Supply 400KHz clock frequency at initialization phase.
828   //
829   InitFreq = DWMMC_INIT_CLOCK_FREQ;
830   Status = DwMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);
831   if (EFI_ERROR (Status)) {
832     return Status;
833   }
834   MicroSecondDelay (100);
835   return Status;
836 }
837 
838 /**
839   Supply SD/MMC card with maximum voltage at initialization.
840 
841   Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.
842 
843   @param[in] PciIo          The PCI IO protocol instance.
844   @param[in] Slot           The slot number of the SD card to send the command to.
845   @param[in] Capability     The capability of the slot.
846 
847   @retval EFI_SUCCESS       The voltage is supplied successfully.
848   @retval Others            The voltage isn't supplied successfully.
849 
850 **/
851 EFI_STATUS
DwMmcHcInitPowerVoltage(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN DW_MMC_HC_SLOT_CAP Capability)852 DwMmcHcInitPowerVoltage (
853   IN EFI_PCI_IO_PROTOCOL    *PciIo,
854   IN UINT8                  Slot,
855   IN DW_MMC_HC_SLOT_CAP     Capability
856   )
857 {
858   EFI_STATUS                Status;
859   UINT32                    Data;
860 
861   Data = 0x1;
862   Status  = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_PWREN, FALSE, sizeof (Data), &Data);
863 
864   if (EFI_ERROR (Status)) {
865     DEBUG ((DEBUG_ERROR, "DwMmcHcInitPowerVoltage: enable power fails: %r\n", Status));
866     return Status;
867   }
868 
869   Data = DW_MMC_CTRL_RESET_ALL;
870   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CTRL, FALSE, sizeof (Data), &Data);
871   if (EFI_ERROR (Status)) {
872     DEBUG ((DEBUG_ERROR, "DwMmcHcInitPowerVoltage: reset fails: %r\n", Status));
873     return Status;
874   }
875   Status = DwMmcHcWaitMmioSet (
876              PciIo,
877              Slot,
878              DW_MMC_CTRL,
879              sizeof (Data),
880              DW_MMC_CTRL_RESET_ALL,
881              0x00,
882              DW_MMC_HC_GENERIC_TIMEOUT
883              );
884   if (EFI_ERROR (Status)) {
885     DEBUG ((DEBUG_INFO, "DwMmcHcInitPowerVoltage: reset done with %r\n", Status));
886     return Status;
887   }
888 
889   Data = DW_MMC_CTRL_INT_EN;
890   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_CTRL, FALSE, sizeof (Data), &Data);
891   return Status;
892 }
893 
894 /**
895   Initialize the Timeout Control register with most conservative value at initialization.
896 
897   Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for details.
898 
899   @param[in] PciIo          The PCI IO protocol instance.
900   @param[in] Slot           The slot number of the SD card to send the command to.
901 
902   @retval EFI_SUCCESS       The timeout control register is configured successfully.
903   @retval Others            The timeout control register isn't configured successfully.
904 
905 **/
906 EFI_STATUS
DwMmcHcInitTimeoutCtrl(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot)907 DwMmcHcInitTimeoutCtrl (
908   IN EFI_PCI_IO_PROTOCOL    *PciIo,
909   IN UINT8                  Slot
910   )
911 {
912   EFI_STATUS                Status;
913   UINT32                    Data;
914 
915   Data = ~0;
916   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_TMOUT, FALSE, sizeof (Data), &Data);
917   if (EFI_ERROR (Status)) {
918     DEBUG ((DEBUG_ERROR, "DwMmcHcInitTimeoutCtrl: set timeout fails: %r\n", Status));
919     return Status;
920   }
921 
922   Data = 0x00FFFFFF;
923   Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_DEBNCE, FALSE, sizeof (Data), &Data);
924   return Status;
925 }
926 
927 /**
928   Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
929   at initialization.
930 
931   @param[in] PciIo          The PCI IO protocol instance.
932   @param[in] Slot           The slot number of the SD card to send the command to.
933   @param[in] Capability     The capability of the slot.
934 
935   @retval EFI_SUCCESS       The host controller is initialized successfully.
936   @retval Others            The host controller isn't initialized successfully.
937 
938 **/
939 EFI_STATUS
DwMmcHcInitHost(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN DW_MMC_HC_SLOT_CAP Capability)940 DwMmcHcInitHost (
941   IN EFI_PCI_IO_PROTOCOL    *PciIo,
942   IN UINT8                  Slot,
943   IN DW_MMC_HC_SLOT_CAP     Capability
944   )
945 {
946   EFI_STATUS       Status;
947 
948   Status = DwMmcHcInitPowerVoltage (PciIo, Slot, Capability);
949   if (EFI_ERROR (Status)) {
950     return Status;
951   }
952   return Status;
953 }
954 
955 EFI_STATUS
DwMmcHcStartDma(IN DW_MMC_HC_PRIVATE_DATA * Private,IN DW_MMC_HC_TRB * Trb)956 DwMmcHcStartDma (
957   IN DW_MMC_HC_PRIVATE_DATA           *Private,
958   IN DW_MMC_HC_TRB                    *Trb
959   )
960 {
961   EFI_STATUS                          Status;
962   EFI_PCI_IO_PROTOCOL                 *PciIo;
963   UINT32                              Ctrl;
964   UINT32                              Bmod;
965 
966   PciIo  = Trb->Private->PciIo;
967 
968   // Reset DMA
969   Ctrl = DW_MMC_CTRL_DMA_RESET;
970   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CTRL, FALSE, sizeof (Ctrl), &Ctrl);
971   if (EFI_ERROR (Status)) {
972     DEBUG ((DEBUG_ERROR, "DwMmcHcStartDma: reset fails: %r\n", Status));
973     return Status;
974   }
975   Status = DwMmcHcWaitMmioSet (
976              PciIo,
977              Trb->Slot,
978              DW_MMC_CTRL,
979              sizeof (Ctrl),
980              DW_MMC_CTRL_DMA_RESET,
981              0x00,
982              DW_MMC_HC_GENERIC_TIMEOUT
983              );
984   if (EFI_ERROR (Status)) {
985     DEBUG ((DEBUG_INFO, "DwMmcHcStartDma: reset done with %r\n", Status));
986     return Status;
987   }
988   Bmod = DW_MMC_IDMAC_SWRESET;
989   Status = DwMmcHcOrMmio (PciIo, Trb->Slot, DW_MMC_BMOD, sizeof (Bmod), &Bmod);
990   if (EFI_ERROR (Status)) {
991     DEBUG ((DEBUG_ERROR, "DwMmcHcStartDma: set BMOD fail: %r\n", Status));
992     return Status;
993   }
994 
995   // Select IDMAC
996   Ctrl = DW_MMC_CTRL_IDMAC_EN;
997   Status = DwMmcHcOrMmio (PciIo, Trb->Slot, DW_MMC_CTRL, sizeof (Ctrl), &Ctrl);
998   if (EFI_ERROR (Status)) {
999     DEBUG ((DEBUG_ERROR, "DwMmcHcStartDma: init IDMAC fail: %r\n", Status));
1000     return Status;
1001   }
1002 
1003   // Enable IDMAC
1004   Bmod = DW_MMC_IDMAC_ENABLE | DW_MMC_IDMAC_FB;
1005   Status = DwMmcHcOrMmio (PciIo, Trb->Slot, DW_MMC_BMOD, sizeof (Bmod), &Bmod);
1006   if (EFI_ERROR (Status)) {
1007     DEBUG ((DEBUG_ERROR, "DwMmcHcReset: set BMOD failure: %r\n", Status));
1008     return Status;
1009   }
1010   return Status;
1011 }
1012 
1013 EFI_STATUS
DwMmcHcStopDma(IN DW_MMC_HC_PRIVATE_DATA * Private,IN DW_MMC_HC_TRB * Trb)1014 DwMmcHcStopDma (
1015   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1016   IN DW_MMC_HC_TRB                    *Trb
1017   )
1018 {
1019   EFI_STATUS                          Status;
1020   EFI_PCI_IO_PROTOCOL                 *PciIo;
1021   UINT32                              Ctrl;
1022   UINT32                              Bmod;
1023 
1024   PciIo  = Trb->Private->PciIo;
1025 
1026   // Disable and reset IDMAC
1027   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CTRL, TRUE, sizeof (Ctrl), &Ctrl);
1028   if (EFI_ERROR (Status)) {
1029     return Status;
1030   }
1031   Ctrl &= ~DW_MMC_CTRL_IDMAC_EN;
1032   Ctrl |= DW_MMC_CTRL_DMA_RESET;
1033   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CTRL, FALSE, sizeof (Ctrl), &Ctrl);
1034   if (EFI_ERROR (Status)) {
1035     return Status;
1036   }
1037   // Stop IDMAC
1038   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BMOD, TRUE, sizeof (Bmod), &Bmod);
1039   if (EFI_ERROR (Status)) {
1040     return Status;
1041   }
1042   Bmod &= ~(DW_MMC_BMOD_FB | DW_MMC_BMOD_DE);
1043   Bmod |= DW_MMC_BMOD_SWR;
1044   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BMOD, FALSE, sizeof (Bmod), &Bmod);
1045   if (EFI_ERROR (Status)) {
1046     return Status;
1047   }
1048   return Status;
1049 }
1050 
1051 /**
1052   Build DMA descriptor table for transfer.
1053 
1054   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1055 
1056   @retval EFI_SUCCESS       The DMA descriptor table is created successfully.
1057   @retval Others            The DMA descriptor table isn't created successfully.
1058 
1059 **/
1060 EFI_STATUS
BuildDmaDescTable(IN DW_MMC_HC_TRB * Trb)1061 BuildDmaDescTable (
1062   IN DW_MMC_HC_TRB          *Trb
1063   )
1064 {
1065   EFI_PHYSICAL_ADDRESS      Data;
1066   UINT64                    DataLen;
1067   UINT64                    Entries;
1068   UINT32                    Index;
1069   UINT64                    Remaining;
1070   UINTN                     TableSize;
1071   EFI_PCI_IO_PROTOCOL       *PciIo;
1072   EFI_STATUS                Status;
1073   UINTN                     Bytes;
1074   UINTN                     Blocks;
1075   DW_MMC_HC_DMA_DESC_LINE   *DmaDesc;
1076   UINT32                    DmaDescPhy;
1077   UINT32                    Idsts;
1078   UINT32                    BytCnt;
1079   UINT32                    BlkSize;
1080 
1081   Data    = Trb->DataPhy;
1082   DataLen = Trb->DataLen;
1083   PciIo   = Trb->Private->PciIo;
1084   //
1085   // Only support 32bit DMA Descriptor Table
1086   //
1087   if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
1088     return EFI_INVALID_PARAMETER;
1089   }
1090   //
1091   // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
1092   // for 32-bit address descriptor table.
1093   //
1094   if ((Data & (BIT0 | BIT1)) != 0) {
1095     DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct DMA desc is not aligned to 4 bytes boundary!\n", Data));
1096   }
1097 
1098   Entries   = (DataLen + DWMMC_DMA_BUF_SIZE - 1) / DWMMC_DMA_BUF_SIZE;
1099   TableSize = Entries * sizeof (DW_MMC_HC_DMA_DESC_LINE);
1100   Blocks    = (DataLen + DW_MMC_BLOCK_SIZE - 1) / DW_MMC_BLOCK_SIZE;
1101 
1102   Trb->DmaDescPages = (UINT32)EFI_SIZE_TO_PAGES (Entries * DWMMC_DMA_BUF_SIZE);
1103   Status = PciIo->AllocateBuffer (
1104                     PciIo,
1105                     AllocateAnyPages,
1106                     EfiBootServicesData,
1107                     EFI_SIZE_TO_PAGES (TableSize),
1108                     (VOID **)&Trb->DmaDesc,
1109                     0
1110                     );
1111   if (EFI_ERROR (Status)) {
1112     return EFI_OUT_OF_RESOURCES;
1113   }
1114   ZeroMem (Trb->DmaDesc, TableSize);
1115   Bytes  = TableSize;
1116   Status = PciIo->Map (
1117                     PciIo,
1118                     EfiPciIoOperationBusMasterCommonBuffer,
1119                     Trb->DmaDesc,
1120                     &Bytes,
1121                     &Trb->DmaDescPhy,
1122                     &Trb->DmaMap
1123                     );
1124 
1125   if (EFI_ERROR (Status) || (Bytes != TableSize)) {
1126     //
1127     // Map error or unable to map the whole RFis buffer into a contiguous region.
1128     //
1129     PciIo->FreeBuffer (
1130              PciIo,
1131              EFI_SIZE_TO_PAGES (TableSize),
1132              Trb->DmaDesc
1133              );
1134     return EFI_OUT_OF_RESOURCES;
1135   }
1136 
1137   if ((UINT64)(UINTN)Trb->DmaDescPhy > 0x100000000ul) {
1138     //
1139     // The DMA doesn't support 64bit addressing.
1140     //
1141     PciIo->Unmap (
1142       PciIo,
1143       Trb->DmaMap
1144     );
1145 #if 0
1146     PciIo->FreeBuffer (
1147       PciIo,
1148       EFI_SIZE_TO_PAGES (TableSize),
1149       Trb->DmaDesc
1150     );
1151 #endif
1152     return EFI_DEVICE_ERROR;
1153   }
1154 
1155   if (DataLen < DW_MMC_BLOCK_SIZE) {
1156     BlkSize = DataLen;
1157     BytCnt = DataLen;
1158     Remaining = DataLen;
1159   } else {
1160     BlkSize = DW_MMC_BLOCK_SIZE;
1161     BytCnt = DW_MMC_BLOCK_SIZE * Blocks;
1162     Remaining = DW_MMC_BLOCK_SIZE * Blocks;
1163   }
1164   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BLKSIZ, FALSE, sizeof (BlkSize), &BlkSize);
1165   if (EFI_ERROR (Status)) {
1166     DEBUG ((DEBUG_ERROR, "BuildDmaDescTable: set block size fails: %r\n", Status));
1167     return Status;
1168   }
1169   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BYTCNT, FALSE, sizeof (BytCnt), &BytCnt);
1170   if (EFI_ERROR (Status)) {
1171     return Status;
1172   }
1173   DmaDesc = Trb->DmaDesc;
1174   for (Index = 0; Index < Entries; Index++, DmaDesc++) {
1175     DmaDesc->Des0 = DW_MMC_IDMAC_DES0_OWN | DW_MMC_IDMAC_DES0_CH |
1176                     DW_MMC_IDMAC_DES0_DIC;
1177     DmaDesc->Des1 = DW_MMC_IDMAC_DES1_BS1 (DWMMC_DMA_BUF_SIZE);
1178     // Buffer Address
1179     DmaDesc->Des2 = (UINT32)((UINTN)Trb->DataPhy + (DWMMC_DMA_BUF_SIZE * Index));
1180     // Next Descriptor Address
1181     DmaDesc->Des3 = (UINT32)((UINTN)Trb->DmaDescPhy + sizeof (DW_MMC_HC_DMA_DESC_LINE) * (Index + 1));
1182     Remaining = Remaining - DWMMC_DMA_BUF_SIZE;
1183   }
1184   // First Descriptor
1185   Trb->DmaDesc[0].Des0 |= DW_MMC_IDMAC_DES0_FS;
1186   // Last Descriptor
1187   Trb->DmaDesc[Entries - 1].Des0 &= ~(DW_MMC_IDMAC_DES0_CH | DW_MMC_IDMAC_DES0_DIC);
1188   Trb->DmaDesc[Entries - 1].Des0 |= DW_MMC_IDMAC_DES0_OWN | DW_MMC_IDMAC_DES0_LD;
1189   Trb->DmaDesc[Entries - 1].Des1 = DW_MMC_IDMAC_DES1_BS1 (Remaining + DWMMC_DMA_BUF_SIZE);
1190   // Set the next field of the Last Descriptor
1191   Trb->DmaDesc[Entries - 1].Des3 = 0;
1192   DmaDescPhy = (UINT32)Trb->DmaDescPhy;
1193   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_DBADDR, FALSE, sizeof (DmaDescPhy), &DmaDescPhy);
1194   if (EFI_ERROR (Status)) {
1195     return Status;
1196   }
1197   ArmDataSynchronizationBarrier ();
1198   ArmInstructionSynchronizationBarrier ();
1199   // Clear interrupts
1200   Idsts = ~0;
1201   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_IDSTS, FALSE, sizeof (Idsts), &Idsts);
1202   return Status;
1203 }
1204 
1205 EFI_STATUS
ReadFifo(IN DW_MMC_HC_TRB * Trb)1206 ReadFifo (
1207   IN DW_MMC_HC_TRB          *Trb
1208   )
1209 {
1210   EFI_STATUS                Status;
1211   EFI_PCI_IO_PROTOCOL       *PciIo;
1212   UINT32                    Data;
1213   UINT32                    Received;
1214   UINT32                    Count;
1215   UINT32                    Intsts;
1216   UINT32                    Sts;
1217   UINT32                    FifoCount;
1218   UINT32                    Index;     // count with bytes
1219   UINT32                    Ascending;
1220   UINT32                    Descending;
1221 
1222   PciIo   = Trb->Private->PciIo;
1223   Received = 0;
1224   Count = 0;
1225   Index = 0;
1226   Ascending = 0;
1227   Descending = ((Trb->DataLen + 3) & ~3) - 4;
1228   do {
1229     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, TRUE, sizeof (Intsts), &Intsts);
1230     if (EFI_ERROR (Status)) {
1231       DEBUG ((DEBUG_ERROR, "ReadFifo: failed to read RINTSTS, Status:%r\n", Status));
1232       return Status;
1233     }
1234     if (Trb->DataLen && ((Intsts & DW_MMC_INT_RXDR) || (Intsts & DW_MMC_INT_DTO))) {
1235       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_STATUS, TRUE, sizeof (Sts), &Sts);
1236       if (EFI_ERROR (Status)) {
1237         DEBUG ((DEBUG_ERROR, "ReadFifo: failed to read STATUS, Status:%r\n", Status));
1238         return Status;
1239       }
1240       // Convert to bytes
1241       FifoCount = GET_STS_FIFO_COUNT (Sts) << 2;
1242       if ((FifoCount == 0) && (Received < Trb->DataLen)) {
1243         continue;
1244       }
1245       Index = 0;
1246       Count = (MIN (FifoCount, Trb->DataLen) + 3) & ~3;
1247       while (Index < Count) {
1248         Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_FIFO_START, TRUE, sizeof (Data), &Data);
1249         if (EFI_ERROR (Status)) {
1250           DEBUG ((DEBUG_ERROR, "ReadFifo: failed to read FIFO, Status:%r\n", Status));
1251           return Status;
1252         }
1253         if (Trb->UseBE) {
1254           *(UINT32 *)((UINTN)Trb->Data + Descending) = SwapBytes32 (Data);
1255           Descending = Descending - 4;
1256         } else {
1257           *(UINT32 *)((UINTN)Trb->Data + Ascending) = Data;
1258           Ascending += 4;
1259         }
1260         Index += 4;
1261         Received += 4;
1262       } // while
1263     } // if
1264   } while (((Intsts & DW_MMC_INT_CMD_DONE) == 0) || (Received < Trb->DataLen));
1265   // Clear RINTSTS
1266   Intsts = ~0;
1267   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, FALSE, sizeof (Intsts), &Intsts);
1268   if (EFI_ERROR (Status)) {
1269     DEBUG ((DEBUG_ERROR, "ReadFifo: failed to write RINTSTS, Status:%r\n", Status));
1270     return Status;
1271   }
1272   return EFI_SUCCESS;
1273 }
1274 
1275 /**
1276   Create a new TRB for the SD/MMC cmd request.
1277 
1278   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1279   @param[in] Slot           The slot number of the SD card to send the command to.
1280   @param[in] Packet         A pointer to the SD command data structure.
1281   @param[in] Event          If Event is NULL, blocking I/O is performed. If Event is
1282                             not NULL, then nonblocking I/O is performed, and Event
1283                             will be signaled when the Packet completes.
1284 
1285   @return Created Trb or NULL.
1286 
1287 **/
1288 DW_MMC_HC_TRB *
DwMmcCreateTrb(IN DW_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot,IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET * Packet,IN EFI_EVENT Event)1289 DwMmcCreateTrb (
1290   IN DW_MMC_HC_PRIVATE_DATA              *Private,
1291   IN UINT8                               Slot,
1292   IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,
1293   IN EFI_EVENT                           Event
1294   )
1295 {
1296   DW_MMC_HC_TRB                 *Trb;
1297   EFI_STATUS                    Status;
1298   EFI_TPL                       OldTpl;
1299   EFI_PCI_IO_PROTOCOL_OPERATION Flag;
1300   EFI_PCI_IO_PROTOCOL           *PciIo;
1301   UINTN                         MapLength;
1302 
1303   Trb = AllocateZeroPool (sizeof (DW_MMC_HC_TRB));
1304   if (Trb == NULL) {
1305     return NULL;
1306   }
1307 
1308   Trb->Signature = DW_MMC_HC_TRB_SIG;
1309   Trb->Slot      = Slot;
1310   Trb->BlockSize = 0x200;
1311   Trb->Packet    = Packet;
1312   Trb->Event     = Event;
1313   Trb->Started   = FALSE;
1314   Trb->Timeout   = Packet->Timeout;
1315   Trb->Private   = Private;
1316 
1317   if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {
1318     Trb->Data    = Packet->InDataBuffer;
1319     Trb->DataLen = Packet->InTransferLength;
1320     Trb->Read    = TRUE;
1321     ZeroMem (Trb->Data, Trb->DataLen);
1322   } else if ((Packet->OutTransferLength != 0) && (Packet->OutDataBuffer != NULL)) {
1323     Trb->Data    = Packet->OutDataBuffer;
1324     Trb->DataLen = Packet->OutTransferLength;
1325     Trb->Read    = FALSE;
1326   } else if ((Packet->InTransferLength == 0) && (Packet->OutTransferLength == 0)) {
1327     Trb->Data    = NULL;
1328     Trb->DataLen = 0;
1329   } else {
1330     goto Error;
1331   }
1332 
1333   if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&
1334        (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||
1335       ((Private->Slot[Trb->Slot].CardType == SdCardType) &&
1336        (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {
1337     Trb->Mode = SdMmcPioMode;
1338   } else {
1339     if (Trb->Read) {
1340       Flag = EfiPciIoOperationBusMasterWrite;
1341     } else {
1342       Flag = EfiPciIoOperationBusMasterRead;
1343     }
1344 
1345     PciIo = Private->PciIo;
1346 #if 0
1347     if ((Private->Slot[Trb->Slot].CardType == SdCardType) &&
1348         (Trb->DataLen != 0) &&
1349         (Trb->DataLen <= DWMMC_FIFO_THRESHOLD)) {
1350 #else
1351     if (Private->Slot[Trb->Slot].CardType == SdCardType) {
1352 #endif
1353       Trb->UseFifo = TRUE;
1354     } else {
1355       Trb->UseFifo = FALSE;
1356       if (Trb->DataLen) {
1357         MapLength = Trb->DataLen;
1358         Status = PciIo->Map (
1359                           PciIo,
1360                           Flag,
1361                           Trb->Data,
1362                           &MapLength,
1363                           &Trb->DataPhy,
1364                           &Trb->DataMap
1365                           );
1366         if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {
1367           Status = EFI_BAD_BUFFER_SIZE;
1368           goto Error;
1369         }
1370 
1371         Status = BuildDmaDescTable (Trb);
1372         if (EFI_ERROR (Status)) {
1373           PciIo->Unmap (PciIo, Trb->DataMap);
1374           goto Error;
1375         }
1376         Status = DwMmcHcStartDma (Private, Trb);
1377         if (EFI_ERROR (Status)) {
1378           PciIo->Unmap (PciIo, Trb->DataMap);
1379           goto Error;
1380         }
1381       }
1382     }
1383   } // TuningBlock
1384 
1385   if (Event != NULL) {
1386     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1387     InsertTailList (&Private->Queue, &Trb->TrbList);
1388     gBS->RestoreTPL (OldTpl);
1389   }
1390 
1391   return Trb;
1392 
1393 Error:
1394   //DwMmcFreeTrb (Trb);
1395   return NULL;
1396 }
1397 
1398 /**
1399   Free the resource used by the TRB.
1400 
1401   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1402 
1403 **/
1404 VOID
1405 DwMmcFreeTrb (
1406   IN DW_MMC_HC_TRB           *Trb
1407   )
1408 {
1409   EFI_PCI_IO_PROTOCOL        *PciIo;
1410 
1411   PciIo = Trb->Private->PciIo;
1412 
1413   if (Trb->DmaMap != NULL) {
1414     PciIo->Unmap (
1415       PciIo,
1416       Trb->DmaMap
1417     );
1418   }
1419 #if 0
1420   // Free is handled in Unmap().
1421   if (Trb->DmaDesc != NULL) {
1422     PciIo->FreeBuffer (
1423       PciIo,
1424       Trb->DmaDescPages,
1425       Trb->DmaDesc
1426     );
1427   }
1428 #endif
1429   if (Trb->DataMap != NULL) {
1430     PciIo->Unmap (
1431       PciIo,
1432       Trb->DataMap
1433     );
1434   }
1435   FreePool (Trb);
1436   return;
1437 }
1438 
1439 /**
1440   Check if the env is ready for execute specified TRB.
1441 
1442   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1443   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1444 
1445   @retval EFI_SUCCESS       The env is ready for TRB execution.
1446   @retval EFI_NOT_READY     The env is not ready for TRB execution.
1447   @retval Others            Some erros happen.
1448 
1449 **/
1450 EFI_STATUS
1451 DwMmcCheckTrbEnv (
1452   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1453   IN DW_MMC_HC_TRB                    *Trb
1454   )
1455 {
1456   return EFI_SUCCESS;
1457 }
1458 
1459 /**
1460   Wait for the env to be ready for execute specified TRB.
1461 
1462   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1463   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1464 
1465   @retval EFI_SUCCESS       The env is ready for TRB execution.
1466   @retval EFI_TIMEOUT       The env is not ready for TRB execution in time.
1467   @retval Others            Some erros happen.
1468 
1469 **/
1470 EFI_STATUS
1471 DwMmcWaitTrbEnv (
1472   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1473   IN DW_MMC_HC_TRB                    *Trb
1474   )
1475 {
1476   EFI_STATUS                          Status;
1477   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
1478   UINT64                              Timeout;
1479   BOOLEAN                             InfiniteWait;
1480 
1481   //
1482   // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register
1483   //
1484   Packet  = Trb->Packet;
1485   Timeout = Packet->Timeout;
1486   if (Timeout == 0) {
1487     InfiniteWait = TRUE;
1488   } else {
1489     InfiniteWait = FALSE;
1490   }
1491 
1492   while (InfiniteWait || (Timeout > 0)) {
1493     //
1494     // Check Trb execution result by reading Normal Interrupt Status register.
1495     //
1496     Status = DwMmcCheckTrbEnv (Private, Trb);
1497     if (Status != EFI_NOT_READY) {
1498       return Status;
1499     }
1500     //
1501     // Stall for 1 microsecond.
1502     //
1503     gBS->Stall (1);
1504 
1505     Timeout--;
1506   }
1507 
1508   return EFI_TIMEOUT;
1509 }
1510 
1511 EFI_STATUS
1512 DwEmmcExecTrb (
1513   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1514   IN DW_MMC_HC_TRB                    *Trb
1515   )
1516 {
1517   EFI_STATUS                          Status;
1518   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
1519   EFI_PCI_IO_PROTOCOL                 *PciIo;
1520   UINT32                              Cmd;
1521   UINT32                              MmcStatus;
1522   UINT32                              IntStatus;
1523   UINT32                              Argument;
1524   UINT32                              ErrMask;
1525   UINT32                              Timeout;
1526 
1527   Packet = Trb->Packet;
1528   PciIo  = Trb->Private->PciIo;
1529 
1530   ArmDataSynchronizationBarrier ();
1531   ArmInstructionSynchronizationBarrier ();
1532   // Wait until MMC is idle
1533   do {
1534     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_STATUS, TRUE, sizeof (MmcStatus), &MmcStatus);
1535     if (EFI_ERROR (Status)) {
1536       return Status;
1537     }
1538   } while (MmcStatus & DW_MMC_STS_DATA_BUSY);
1539 
1540   IntStatus = ~0;
1541   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, FALSE, sizeof (IntStatus), &IntStatus);
1542   if (EFI_ERROR (Status)) {
1543     return Status;
1544   }
1545   Cmd = CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex);
1546   if ((Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAc) ||
1547       (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc)) {
1548     switch (Packet->SdMmcCmdBlk->CommandIndex) {
1549     case EMMC_SET_RELATIVE_ADDR:
1550       Cmd |= BIT_CMD_SEND_INIT;
1551       break;
1552     case EMMC_SEND_STATUS:
1553       Cmd |= BIT_CMD_WAIT_PRVDATA_COMPLETE;
1554       break;
1555     case EMMC_STOP_TRANSMISSION:
1556       Cmd |= BIT_CMD_STOP_ABORT_CMD;
1557       break;
1558     }
1559     if (Packet->InTransferLength) {
1560       Cmd |= BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;
1561     } else if (Packet->OutTransferLength) {
1562       Cmd |= BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;
1563     }
1564     Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
1565   } else {
1566     switch (Packet->SdMmcCmdBlk->CommandIndex) {
1567     case EMMC_GO_IDLE_STATE:
1568       Cmd |= BIT_CMD_SEND_INIT;
1569       break;
1570     case EMMC_SEND_OP_COND:
1571       Cmd |= BIT_CMD_RESPONSE_EXPECT;
1572       break;
1573     case EMMC_ALL_SEND_CID:
1574       Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
1575              BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
1576       break;
1577     }
1578   }
1579   switch (Packet->SdMmcCmdBlk->ResponseType) {
1580   case SdMmcResponseTypeR2:
1581     Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_LONG_RESPONSE;
1582     break;
1583   case SdMmcResponseTypeR3:
1584     Cmd |= BIT_CMD_RESPONSE_EXPECT;
1585     break;
1586   }
1587   Cmd |= BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
1588 
1589   Argument = Packet->SdMmcCmdBlk->CommandArgument;
1590   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CMDARG, FALSE, sizeof (Argument), &Argument);
1591   if (EFI_ERROR (Status)) {
1592     return Status;
1593   }
1594   ArmDataSynchronizationBarrier ();
1595   ArmInstructionSynchronizationBarrier ();
1596   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CMD, FALSE, sizeof (Cmd), &Cmd);
1597   if (EFI_ERROR (Status)) {
1598     return Status;
1599   }
1600   ArmDataSynchronizationBarrier ();
1601   ArmInstructionSynchronizationBarrier ();
1602 
1603   ErrMask = DW_MMC_INT_EBE | DW_MMC_INT_HLE | DW_MMC_INT_RTO |
1604             DW_MMC_INT_RCRC | DW_MMC_INT_RE;
1605   ErrMask |= DW_MMC_INT_DCRC | DW_MMC_INT_DRT | DW_MMC_INT_SBE;
1606   do {
1607     Timeout = 10000;
1608     if (--Timeout == 0) {
1609       break;
1610     }
1611     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, TRUE, sizeof (IntStatus), &IntStatus);
1612     if (EFI_ERROR (Status)) {
1613       return Status;
1614     }
1615     if (IntStatus & ErrMask) {
1616       return EFI_DEVICE_ERROR;
1617     }
1618     if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) == 0)) {
1619       // Transfer Not Done
1620       MicroSecondDelay (10);
1621       continue;
1622     }
1623     MicroSecondDelay (10);
1624   } while (!(IntStatus & DW_MMC_INT_CMD_DONE));
1625   switch (Packet->SdMmcCmdBlk->ResponseType) {
1626     case SdMmcResponseTypeR1:
1627     case SdMmcResponseTypeR1b:
1628     case SdMmcResponseTypeR3:
1629     case SdMmcResponseTypeR4:
1630     case SdMmcResponseTypeR5:
1631       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP0, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp0), &Packet->SdMmcStatusBlk->Resp0);
1632       if (EFI_ERROR (Status)) {
1633         return Status;
1634       }
1635       break;
1636     case SdMmcResponseTypeR2:
1637       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP0, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp0), &Packet->SdMmcStatusBlk->Resp0);
1638       if (EFI_ERROR (Status)) {
1639         return Status;
1640       }
1641       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP1, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp1), &Packet->SdMmcStatusBlk->Resp1);
1642       if (EFI_ERROR (Status)) {
1643         return Status;
1644       }
1645       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP2, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp2), &Packet->SdMmcStatusBlk->Resp2);
1646       if (EFI_ERROR (Status)) {
1647         return Status;
1648       }
1649       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP3, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp3), &Packet->SdMmcStatusBlk->Resp3);
1650       if (EFI_ERROR (Status)) {
1651         return Status;
1652       }
1653       break;
1654   }
1655 
1656   //
1657   // The workaround on EMMC_SEND_CSD is used to be compatible with SDHC.
1658   //
1659   if (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_CSD) {
1660     {
1661       UINT32   Buf[4];
1662       ZeroMem (Buf, sizeof (Buf));
1663       CopyMem ((UINT8 *)Buf, (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, sizeof (Buf) - 1);
1664       CopyMem ((UINT8 *)&Packet->SdMmcStatusBlk->Resp0, (UINT8 *)Buf, sizeof (Buf) - 1);
1665     }
1666   }
1667 
1668   return EFI_SUCCESS;
1669 }
1670 
1671 EFI_STATUS
1672 DwSdExecTrb (
1673   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1674   IN DW_MMC_HC_TRB                    *Trb
1675   )
1676 {
1677   EFI_STATUS                          Status;
1678   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
1679   EFI_PCI_IO_PROTOCOL                 *PciIo;
1680   UINT32                              Cmd;
1681   UINT32                              MmcStatus;
1682   UINT32                              IntStatus;
1683   UINT32                              Argument;
1684   UINT32                              ErrMask;
1685   UINT32                              Timeout;
1686   UINT32                              Idsts;
1687   UINT32                              BytCnt;
1688   UINT32                              BlkSize;
1689 
1690   Packet = Trb->Packet;
1691   PciIo  = Trb->Private->PciIo;
1692 
1693   ArmDataSynchronizationBarrier ();
1694   ArmInstructionSynchronizationBarrier ();
1695   // Wait until MMC is idle
1696   do {
1697     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_STATUS, TRUE, sizeof (MmcStatus), &MmcStatus);
1698     if (EFI_ERROR (Status)) {
1699       return Status;
1700     }
1701   } while (MmcStatus & DW_MMC_STS_DATA_BUSY);
1702 
1703   IntStatus = ~0;
1704   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, FALSE, sizeof (IntStatus), &IntStatus);
1705   if (EFI_ERROR (Status)) {
1706     return Status;
1707   }
1708   Cmd = CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex);
1709   if ((Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAc) ||
1710       (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc)) {
1711     switch (Packet->SdMmcCmdBlk->CommandIndex) {
1712     case SD_SET_RELATIVE_ADDR:
1713       Cmd |= BIT_CMD_SEND_INIT;
1714       break;
1715     case SD_STOP_TRANSMISSION:
1716       Cmd |= BIT_CMD_STOP_ABORT_CMD;
1717       break;
1718     case SD_SEND_SCR:
1719       Trb->UseBE = TRUE;
1720       break;
1721     }
1722     if (Packet->InTransferLength) {
1723       Cmd |= BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;
1724     } else if (Packet->OutTransferLength) {
1725       Cmd |= BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;
1726     }
1727     Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
1728   } else {
1729     switch (Packet->SdMmcCmdBlk->CommandIndex) {
1730     case SD_GO_IDLE_STATE:
1731       Cmd |= BIT_CMD_SEND_INIT;
1732       break;
1733     }
1734   }
1735   switch (Packet->SdMmcCmdBlk->ResponseType) {
1736   case SdMmcResponseTypeR2:
1737     Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_LONG_RESPONSE;
1738     break;
1739   case SdMmcResponseTypeR3:
1740     Cmd |= BIT_CMD_RESPONSE_EXPECT;
1741     break;
1742   case SdMmcResponseTypeR1b:
1743   case SdMmcResponseTypeR4:
1744   case SdMmcResponseTypeR6:
1745   case SdMmcResponseTypeR7:
1746     Cmd |= BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
1747     break;
1748   }
1749   Cmd |= BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
1750 
1751   if (Trb->UseFifo == TRUE) {
1752     BytCnt = Packet->InTransferLength;
1753     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BYTCNT, FALSE, sizeof (BytCnt), &BytCnt);
1754     if (EFI_ERROR (Status)) {
1755       return Status;
1756     }
1757     if (Packet->InTransferLength > DW_MMC_BLOCK_SIZE) {
1758       BlkSize = DW_MMC_BLOCK_SIZE;
1759     } else {
1760       BlkSize = Packet->InTransferLength;
1761     }
1762     Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_BLKSIZ, FALSE, sizeof (BlkSize), &BlkSize);
1763     if (EFI_ERROR (Status)) {
1764       DEBUG ((DEBUG_ERROR, "DwMmcHcReset: set block size fails: %r\n", Status));
1765       return Status;
1766     }
1767   }
1768 
1769   Argument = Packet->SdMmcCmdBlk->CommandArgument;
1770   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CMDARG, FALSE, sizeof (Argument), &Argument);
1771   if (EFI_ERROR (Status)) {
1772     return Status;
1773   }
1774   ArmDataSynchronizationBarrier ();
1775   ArmInstructionSynchronizationBarrier ();
1776   Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_CMD, FALSE, sizeof (Cmd), &Cmd);
1777   if (EFI_ERROR (Status)) {
1778     return Status;
1779   }
1780   ArmDataSynchronizationBarrier ();
1781   ArmInstructionSynchronizationBarrier ();
1782 
1783   ErrMask = DW_MMC_INT_EBE | DW_MMC_INT_HLE | DW_MMC_INT_RTO |
1784             DW_MMC_INT_RCRC | DW_MMC_INT_RE;
1785   ErrMask |= DW_MMC_INT_DRT | DW_MMC_INT_SBE;
1786   if (Packet->InTransferLength || Packet->OutTransferLength) {
1787     ErrMask |= DW_MMC_INT_DCRC;
1788   }
1789   if (Trb->UseFifo == TRUE) {
1790     Status = ReadFifo (Trb);
1791     if (EFI_ERROR (Status)) {
1792       return Status;
1793     }
1794   } else {
1795     Timeout = 10000;
1796     do {
1797       if (--Timeout == 0) {
1798         break;
1799       }
1800       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RINTSTS, TRUE, sizeof (IntStatus), &IntStatus);
1801       if (EFI_ERROR (Status)) {
1802         return Status;
1803       }
1804       if (IntStatus & ErrMask) {
1805         return EFI_DEVICE_ERROR;
1806       }
1807       if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) == 0)) {
1808         // Transfer not Done
1809         MicroSecondDelay (10);
1810         continue;
1811       }
1812       MicroSecondDelay (10);
1813     } while (!(IntStatus & DW_MMC_INT_CMD_DONE));
1814     if (Packet->InTransferLength) {
1815       do {
1816         Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_IDSTS, TRUE, sizeof (Idsts), &Idsts);
1817         if (EFI_ERROR (Status)) {
1818           return Status;
1819         }
1820       } while ((Idsts & DW_MMC_IDSTS_RI) == 0);
1821       Status = DwMmcHcStopDma (Private, Trb);
1822       if (EFI_ERROR (Status)) {
1823         return Status;
1824       }
1825     } else if (Packet->OutTransferLength) {
1826       do {
1827         Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_IDSTS, TRUE, sizeof (Idsts), &Idsts);
1828         if (EFI_ERROR (Status)) {
1829           return Status;
1830         }
1831       } while ((Idsts & DW_MMC_IDSTS_TI) == 0);
1832       Status = DwMmcHcStopDma (Private, Trb);
1833       if (EFI_ERROR (Status)) {
1834         return Status;
1835       }
1836     } // Packet->InTransferLength
1837   } // UseFifo
1838   switch (Packet->SdMmcCmdBlk->ResponseType) {
1839     case SdMmcResponseTypeR1:
1840     case SdMmcResponseTypeR1b:
1841     case SdMmcResponseTypeR3:
1842     case SdMmcResponseTypeR4:
1843     case SdMmcResponseTypeR5:
1844     case SdMmcResponseTypeR6:
1845     case SdMmcResponseTypeR7:
1846       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP0, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp0), &Packet->SdMmcStatusBlk->Resp0);
1847       if (EFI_ERROR (Status)) {
1848         return Status;
1849       }
1850       break;
1851     case SdMmcResponseTypeR2:
1852       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP0, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp0), &Packet->SdMmcStatusBlk->Resp0);
1853       if (EFI_ERROR (Status)) {
1854         return Status;
1855       }
1856       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP1, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp1), &Packet->SdMmcStatusBlk->Resp1);
1857       if (EFI_ERROR (Status)) {
1858         return Status;
1859       }
1860       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP2, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp2), &Packet->SdMmcStatusBlk->Resp2);
1861       if (EFI_ERROR (Status)) {
1862         return Status;
1863       }
1864       Status = DwMmcHcRwMmio (PciIo, Trb->Slot, DW_MMC_RESP3, TRUE, sizeof (Packet->SdMmcStatusBlk->Resp3), &Packet->SdMmcStatusBlk->Resp3);
1865       if (EFI_ERROR (Status)) {
1866         return Status;
1867       }
1868       break;
1869   }
1870 
1871   //
1872   // The workaround on SD_SEND_CSD is used to be compatible with SDHC.
1873   //
1874   if (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_CSD) {
1875     {
1876       UINT32   Buf[4];
1877       ZeroMem (Buf, sizeof (Buf));
1878       CopyMem ((UINT8 *)Buf, (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, sizeof (Buf) - 1);
1879       CopyMem ((UINT8 *)&Packet->SdMmcStatusBlk->Resp0, (UINT8 *)Buf, sizeof (Buf) - 1);
1880     }
1881   }
1882 
1883   return EFI_SUCCESS;
1884 }
1885 
1886 /**
1887   Execute the specified TRB.
1888 
1889   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1890   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1891 
1892   @retval EFI_SUCCESS       The TRB is sent to host controller successfully.
1893   @retval Others            Some erros happen when sending this request to the host controller.
1894 
1895 **/
1896 EFI_STATUS
1897 DwMmcExecTrb (
1898   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1899   IN DW_MMC_HC_TRB                    *Trb
1900   )
1901 {
1902   EFI_STATUS                          Status = EFI_SUCCESS;
1903   UINT32                              Slot;
1904 
1905   Slot = Trb->Slot;
1906   if (Private->Slot[Slot].CardType == EmmcCardType) {
1907     Status = DwEmmcExecTrb (Private, Trb);
1908   } else if (Private->Slot[Slot].CardType == SdCardType) {
1909     Status = DwSdExecTrb (Private, Trb);
1910   } else {
1911     ASSERT (0);
1912   }
1913   return Status;
1914 }
1915 
1916 /**
1917   Check the TRB execution result.
1918 
1919   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1920   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1921 
1922   @retval EFI_SUCCESS       The TRB is executed successfully.
1923   @retval EFI_NOT_READY     The TRB is not completed for execution.
1924   @retval Others            Some erros happen when executing this request.
1925 
1926 **/
1927 EFI_STATUS
1928 DwMmcCheckTrbResult (
1929   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1930   IN DW_MMC_HC_TRB                    *Trb
1931   )
1932 {
1933   EFI_STATUS                          Status;
1934   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
1935   UINT32                              Idsts;
1936 
1937   Packet  = Trb->Packet;
1938   if (Trb->UseFifo == TRUE) {
1939     return EFI_SUCCESS;
1940   }
1941   if (Packet->InTransferLength) {
1942     do {
1943       Status = DwMmcHcRwMmio (Private->PciIo, Trb->Slot, DW_MMC_IDSTS, TRUE, sizeof (Idsts), &Idsts);
1944       if (EFI_ERROR (Status)) {
1945         return Status;
1946       }
1947     } while ((Idsts & BIT1) == 0);
1948   } else if (Packet->OutTransferLength) {
1949     do {
1950       Status = DwMmcHcRwMmio (Private->PciIo, Trb->Slot, DW_MMC_IDSTS, TRUE, sizeof (Idsts), &Idsts);
1951       if (EFI_ERROR (Status)) {
1952         return Status;
1953       }
1954     } while ((Idsts & BIT0) == 0);
1955   } else {
1956     return EFI_SUCCESS;
1957   }
1958   Idsts = ~0;
1959   Status = DwMmcHcRwMmio (Private->PciIo, Trb->Slot, DW_MMC_IDSTS, FALSE, sizeof (Idsts), &Idsts);
1960   if (EFI_ERROR (Status)) {
1961     return Status;
1962   }
1963   return EFI_SUCCESS;
1964 }
1965 
1966 /**
1967   Wait for the TRB execution result.
1968 
1969   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
1970   @param[in] Trb            The pointer to the DW_MMC_HC_TRB instance.
1971 
1972   @retval EFI_SUCCESS       The TRB is executed successfully.
1973   @retval Others            Some erros happen when executing this request.
1974 
1975 **/
1976 EFI_STATUS
1977 DwMmcWaitTrbResult (
1978   IN DW_MMC_HC_PRIVATE_DATA           *Private,
1979   IN DW_MMC_HC_TRB                    *Trb
1980   )
1981 {
1982   EFI_STATUS                          Status;
1983   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
1984   UINT64                              Timeout;
1985   BOOLEAN                             InfiniteWait;
1986 
1987   Packet = Trb->Packet;
1988   //
1989   // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register
1990   //
1991   Timeout = Packet->Timeout;
1992   if (Timeout == 0) {
1993     InfiniteWait = TRUE;
1994   } else {
1995     InfiniteWait = FALSE;
1996   }
1997 
1998   while (InfiniteWait || (Timeout > 0)) {
1999     //
2000     // Check Trb execution result by reading Normal Interrupt Status register.
2001     //
2002     Status = DwMmcCheckTrbResult (Private, Trb);
2003     if (Status != EFI_NOT_READY) {
2004       return Status;
2005     }
2006     //
2007     // Stall for 1 microsecond.
2008     //
2009     gBS->Stall (1);
2010 
2011     Timeout--;
2012   }
2013 
2014   return EFI_TIMEOUT;
2015 }
2016