public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
@ 2018-12-18 21:29 Ashish Singhal
  2018-12-19  1:46 ` Wu, Hao A
  2019-01-02  6:28 ` Wu, Hao A
  0 siblings, 2 replies; 7+ messages in thread
From: Ashish Singhal @ 2018-12-18 21:29 UTC (permalink / raw)
  To: edk2-devel; +Cc: Ashish Singhal

Add SDMA, ADMA2 and 26b data length support.

If V4 64 bit address mode is enabled in compatibility register,
program controller to enable V4 host mode and use appropriate
SDMA registers supporting 64 bit addresses.

If V4 64 bit address mode is enabled in compatibility register,
program controller to enable V4 host mode and use appropriate
ADMA descriptors supporting 64 bit addresses.

If host controller version is above V4.0, enable ADMA2 with 26b data
length support for better performance. HC 2 register is configured to
use 26 bit data lengths and ADMA2 descriptors are configured appropriately.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
---
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328 +++++++++++++++++----
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
 6 files changed, 363 insertions(+), 83 deletions(-)
 mode change 100755 => 100644 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c

diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
old mode 100755
new mode 100644
index 2d3fb68..0c5646f
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
@@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
   //
   // Convert the clock freq unit from MHz to KHz.
   //
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot]);
+  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
   if (EFI_ERROR (Status)) {
     return Status;
   }
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
index 68485c8..cdcdfa3 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
@@ -864,7 +864,7 @@ SdCardSetBusMode (
     return Status;
   }
 
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot]);
+  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1064,7 +1064,7 @@ SdCardIdentification (
         goto Error;
       }
 
-      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
+      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
 
       gBS->Stall (1000);
 
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
index a87f8de..b5bc260 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
@@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
   {                                 // MaxCurrent
     0,
   },
-  0                                 // ControllerVersion
+  {
+    0                               // ControllerVersion
+  }
 };
 
 SD_DEVICE_PATH    mSdDpTemplate = {
@@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
     Private->Slot[Slot].Enable = TRUE;
 
+    //
+    // Get SD/MMC Pci Host Controller Version
+    //
+    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
     Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
     if (EFI_ERROR (Status)) {
       continue;
@@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
       Private->BaseClkFreq[Slot]
       ));
 
-    Support64BitDma &= Private->Capability[Slot].SysBus64;
+    //
+    // If any of the slots does not support 64b system bus
+    // do not enable 64b DMA in the PCI layer.
+    //
+    if (Private->Capability[Slot].SysBus64V3 == 0 &&
+        Private->Capability[Slot].SysBus64V4 == 0) {
+      Support64BitDma = FALSE;
+    }
 
     Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
     if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
index 8c1a589..1bb701a 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
@@ -2,6 +2,7 @@
 
   Provides some data structure definitions used by the SD/MMC host controller driver.
 
+Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
@@ -116,8 +117,7 @@ typedef struct {
   SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
   SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
   UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
-
-  UINT32                              ControllerVersion;
+  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
 
   //
   // Some controllers may require to override base clock frequency
@@ -150,7 +150,8 @@ typedef struct {
   BOOLEAN                             Started;
   UINT64                              Timeout;
 
-  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
+  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
+  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
   EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
   VOID                                *AdmaMap;
   UINT32                              AdmaPages;
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
index ddf6dcf..6086720 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
@@ -4,6 +4,7 @@
 
   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
 
+  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -45,7 +46,8 @@ DumpCapabilityReg (
   DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
-  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   SlotType          "));
   if (Capability->SlotType == 0x00) {
@@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
 }
 
 /**
+  Get the controller version information from the specified slot.
+
+  @param[in]  PciIo           The PCI IO protocol instance.
+  @param[in]  Slot            The slot number of the SD card to send the command to.
+  @param[out] Version         The buffer to store the version information.
+
+  @retval EFI_SUCCESS         The operation executes successfully.
+  @retval Others              The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN     UINT8                Slot,
+  OUT    UINT16               *Version
+  )
+{
+  EFI_STATUS                Status;
+
+  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *Version &= 0xFF;
+
+  return EFI_SUCCESS;
+}
+
+/**
   Software reset the specified SD/MMC host controller and enable all interrupts.
 
   @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@@ -722,6 +754,7 @@ SdMmcHcStopClock (
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
   @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.
 
   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -732,14 +765,14 @@ SdMmcHcClockSupply (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
   IN UINT64                 ClockFreq,
-  IN UINT32                 BaseClkFreq
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
 {
   EFI_STATUS                Status;
   UINT32                    SettingFreq;
   UINT32                    Divisor;
   UINT32                    Remainder;
-  UINT16                    ControllerVer;
   UINT16                    ClockCtrl;
 
   //
@@ -775,18 +808,15 @@ SdMmcHcClockSupply (
 
   DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
 
-  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
   //
   // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
   //
-  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
-      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
+  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
     ASSERT (Divisor <= 0x3FF);
     ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
-  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
     //
     // Only the most significant bit can be used as divisor.
     //
@@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
 }
 
 /**
+  Configure V4 controller enhancements at initialization.
+
+  @param[in] PciIo          The PCI IO protocol instance.
+  @param[in] Slot           The slot number of the SD card to send the command to.
+  @param[in] Capability     The capability of the slot.
+  @param[in] ControllerVer  The version of host controller.
+
+  @retval EFI_SUCCESS       The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_HC_SLOT_CAP     Capability,
+  IN UINT16                 ControllerVer
+  )
+{
+  EFI_STATUS                Status;
+  UINT16                    HostCtrl2;
+
+  //
+  // Check if controller version V4 or higher
+  //
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    HostCtrl2 = SD_MMC_HC_V4_EN;
+    //
+    // Check if V4 64bit support is available
+    //
+    if (Capability.SysBus64V4 != 0) {
+      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+    }
+    //
+    // Check if controller version V4.10 or higher
+    //
+    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+    }
+    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Supply SD/MMC card with lowest clock frequency at initialization.
 
   @param[in] PciIo          The PCI IO protocol instance.
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.
 
   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -948,7 +1029,8 @@ EFI_STATUS
 SdMmcHcInitClockFreq (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
-  IN UINT32                 BaseClkFreq
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
 {
   EFI_STATUS                Status;
@@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
   // Supply 400KHz clock frequency at initialization phase.
   //
   InitFreq = 400;
-  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
+  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
   return Status;
 }
 
@@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
   PciIo = Private->PciIo;
   Capability = Private->Capability[Slot];
 
-  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
+  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
 /**
   Build ADMA descriptor table for transfer.
 
-  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
 
   @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
+  @param[in] ControllerVer  The version of host controller.
 
   @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
   @retval Others            The ADMA descriptor table isn't created successfully.
@@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
 **/
 EFI_STATUS
 BuildAdmaDescTable (
-  IN SD_MMC_HC_TRB          *Trb
+  IN SD_MMC_HC_TRB          *Trb,
+  IN UINT16                 ControllerVer
   )
 {
   EFI_PHYSICAL_ADDRESS      Data;
@@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
   UINT64                    Entries;
   UINT32                    Index;
   UINT64                    Remaining;
-  UINT32                    Address;
+  UINT64                    Address;
   UINTN                     TableSize;
   EFI_PCI_IO_PROTOCOL       *PciIo;
   EFI_STATUS                Status;
   UINTN                     Bytes;
+  BOOLEAN                   AddressingMode64;
+  BOOLEAN                   DataLength26;
+  UINT32                    AdmaMaxDataPerLine;
+  UINT32                    DescSize;
+  VOID                      *AdmaDesc;
+
+  AddressingMode64   = FALSE;
+  DataLength26       = FALSE;
+  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
+  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+  AdmaDesc           = NULL;
 
   Data    = Trb->DataPhy;
   DataLen = Trb->DataLen;
   PciIo   = Trb->Private->PciIo;
+
   //
-  // Only support 32bit ADMA Descriptor Table
+  // Detect whether 64bit addressing is supported.
   //
-  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
+    }
+  }
+  //
+  // Check for valid ranges in 32bit ADMA Descriptor Table
+  //
+  if (!AddressingMode64 &&
+      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
     return EFI_INVALID_PARAMETER;
   }
   //
-  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
-  // for 32-bit address descriptor table.
+  // Check address field alignment
   //
-  if ((Data & (BIT0 | BIT1)) != 0) {
-    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+  if (AddressingMode64) {
+    //
+    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+    }
+  } else {
+    //
+    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+    }
+  }
+  //
+  // Detect whether 26bit data length is supported.
+  //
+  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                               SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
+  if (!EFI_ERROR (Status)) {
+    DataLength26 = TRUE;
+    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
   }
 
-  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
-  TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
   Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
   Status = PciIo->AllocateBuffer (
                     PciIo,
                     AllocateAnyPages,
                     EfiBootServicesData,
                     EFI_SIZE_TO_PAGES (TableSize),
-                    (VOID **)&Trb->AdmaDesc,
+                    (VOID **)&AdmaDesc,
                     0
                     );
   if (EFI_ERROR (Status)) {
     return EFI_OUT_OF_RESOURCES;
   }
-  ZeroMem (Trb->AdmaDesc, TableSize);
+  ZeroMem (AdmaDesc, TableSize);
   Bytes  = TableSize;
   Status = PciIo->Map (
                     PciIo,
                     EfiPciIoOperationBusMasterCommonBuffer,
-                    Trb->AdmaDesc,
+                    AdmaDesc,
                     &Bytes,
                     &Trb->AdmaDescPhy,
                     &Trb->AdmaMap
@@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
              PciIo,
              EFI_SIZE_TO_PAGES (TableSize),
-             Trb->AdmaDesc
+             AdmaDesc
              );
     return EFI_OUT_OF_RESOURCES;
   }
 
-  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+  if ((!AddressingMode64) &&
+      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
     //
     // The ADMA doesn't support 64bit addressing.
     //
@@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
       PciIo,
       EFI_SIZE_TO_PAGES (TableSize),
-      Trb->AdmaDesc
+      AdmaDesc
     );
     return EFI_DEVICE_ERROR;
   }
 
   Remaining = DataLen;
-  Address   = (UINT32)Data;
+  Address   = Data;
+  if (!AddressingMode64) {
+    Trb->Adma32Desc = AdmaDesc;
+    Trb->Adma64Desc = NULL;
+  } else {
+    Trb->Adma64Desc = AdmaDesc;
+    Trb->Adma32Desc = NULL;
+  }
   for (Index = 0; Index < Entries; Index++) {
-    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
-      Trb->AdmaDesc[Index].Address = Address;
-      break;
+    if (!AddressingMode64) {
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
+        }
+        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+        break;
+      } else {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma32Desc[Index].LowerLength  = 0;
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+      }
     } else {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = 0;
-      Trb->AdmaDesc[Index].Address = Address;
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
+        }
+        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
+        break;
+      } else {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma64Desc[Index].LowerLength  = 0;
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
+      }
     }
 
-    Remaining -= ADMA_MAX_DATA_PER_LINE;
-    Address   += ADMA_MAX_DATA_PER_LINE;
+    Remaining -= AdmaMaxDataPerLine;
+    Address   += AdmaMaxDataPerLine;
   }
 
   //
   // Set the last descriptor line as end of descriptor table
   //
-  Trb->AdmaDesc[Index].End = 1;
+  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
   return EFI_SUCCESS;
 }
 
@@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
       Trb->Mode = SdMmcNoData;
     } else if (Private->Capability[Slot].Adma2 != 0) {
       Trb->Mode = SdMmcAdmaMode;
-      Status = BuildAdmaDescTable (Trb);
+      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
       if (EFI_ERROR (Status)) {
         PciIo->Unmap (PciIo, Trb->DataMap);
         goto Error;
@@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
       Trb->AdmaMap
     );
   }
-  if (Trb->AdmaDesc != NULL) {
+  if (Trb->Adma32Desc != NULL) {
+    PciIo->FreeBuffer (
+      PciIo,
+      Trb->AdmaPages,
+      Trb->Adma32Desc
+    );
+  }
+  if (Trb->Adma64Desc != NULL) {
     PciIo->FreeBuffer (
       PciIo,
       Trb->AdmaPages,
-      Trb->AdmaDesc
+      Trb->Adma64Desc
     );
   }
   if (Trb->DataMap != NULL) {
@@ -1667,12 +1844,15 @@ SdMmcExecTrb (
   UINT16                              Cmd;
   UINT16                              IntStatus;
   UINT32                              Argument;
-  UINT16                              BlkCount;
+  UINT32                              BlkCount;
   UINT16                              BlkSize;
   UINT16                              TransMode;
   UINT8                               HostCtrl1;
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT64                              AdmaAddr;
+  BOOLEAN                             AddressingMode64;
+
+  AddressingMode64 = FALSE;
 
   Packet = Trb->Packet;
   PciIo  = Trb->Private->PciIo;
@@ -1705,13 +1885,28 @@ SdMmcExecTrb (
 
   SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
 
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+    }
+  }
+
   if (Trb->Mode == SdMmcSdmaMode) {
-    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+    if ((!AddressingMode64) &&
+        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
       return EFI_INVALID_PARAMETER;
     }
 
-    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
-    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+    } else {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+    }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
@@ -1741,9 +1936,13 @@ SdMmcExecTrb (
     //
     // Calcuate Block Count.
     //
-    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+    BlkCount = (Trb->DataLen / Trb->BlockSize);
+  }
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+  } else {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
   }
-  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
   UINT16                              IntStatus;
   UINT32                              Response[4];
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT8                               Index;
   UINT8                               SwReset;
   UINT32                              PioLength;
@@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
     //
     // Update SDMA Address register.
     //
-    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
-    Status   = SdMmcHcRwMmio (
+    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (
+                 Private->PciIo,
+                 Trb->Slot,
+                 SD_MMC_HC_ADMA_SYS_ADDR,
+                 FALSE,
+                 sizeof (UINT64),
+                 &SdmaAddr
+                 );
+    } else {
+      Status = SdMmcHcRwMmio (
                  Private->PciIo,
                  Trb->Slot,
                  SD_MMC_HC_SDMA_ADDR,
@@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
                  sizeof (UINT32),
                  &SdmaAddr
                  );
+    }
+
     if (EFI_ERROR (Status)) {
       goto Done;
     }
-    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
   }
 
   if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index dd45cbd..d157f2c 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
@@ -2,6 +2,7 @@
 
   Provides some data structure definitions used by the SD/MMC host controller driver.
 
+Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
@@ -91,18 +92,38 @@ typedef enum {
 //
 // The maximum data length of each descriptor line
 //
-#define ADMA_MAX_DATA_PER_LINE     0x10000
+#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
+#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
 
+//
+// ADMA descriptor for 32b addressing.
+//
 typedef struct {
   UINT32 Valid:1;
   UINT32 End:1;
   UINT32 Int:1;
   UINT32 Reserved:1;
   UINT32 Act:2;
-  UINT32 Reserved1:10;
-  UINT32 Length:16;
+  UINT32 UpperLength:10;
+  UINT32 LowerLength:16;
   UINT32 Address;
-} SD_MMC_HC_ADMA_DESC_LINE;
+} SD_MMC_HC_ADMA_32_DESC_LINE;
+
+//
+// ADMA descriptor for 64b addressing.
+//
+typedef struct {
+  UINT32 Valid:1;
+  UINT32 End:1;
+  UINT32 Int:1;
+  UINT32 Reserved:1;
+  UINT32 Act:2;
+  UINT32 UpperLength:10;
+  UINT32 LowerLength:16;
+  UINT32 LowerAddress;
+  UINT32 UpperAddress;
+  UINT32 Reserved1;
+} SD_MMC_HC_ADMA_64_DESC_LINE;
 
 #define SD_MMC_SDMA_BOUNDARY          512 * 1024
 #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
@@ -129,36 +150,43 @@ typedef struct {
   UINT32   Voltage33:1;       // bit 24
   UINT32   Voltage30:1;       // bit 25
   UINT32   Voltage18:1;       // bit 26
-  UINT32   Reserved3:1;       // bit 27
-  UINT32   SysBus64:1;        // bit 28
+  UINT32   SysBus64V4:1;      // bit 27
+  UINT32   SysBus64V3:1;      // bit 28
   UINT32   AsyncInt:1;        // bit 29
   UINT32   SlotType:2;        // bit 30:31
   UINT32   Sdr50:1;           // bit 32
   UINT32   Sdr104:1;          // bit 33
   UINT32   Ddr50:1;           // bit 34
-  UINT32   Reserved4:1;       // bit 35
+  UINT32   Reserved3:1;       // bit 35
   UINT32   DriverTypeA:1;     // bit 36
   UINT32   DriverTypeC:1;     // bit 37
   UINT32   DriverTypeD:1;     // bit 38
   UINT32   DriverType4:1;     // bit 39
   UINT32   TimerCount:4;      // bit 40:43
-  UINT32   Reserved5:1;       // bit 44
+  UINT32   Reserved4:1;       // bit 44
   UINT32   TuningSDR50:1;     // bit 45
   UINT32   RetuningMod:2;     // bit 46:47
   UINT32   ClkMultiplier:8;   // bit 48:55
-  UINT32   Reserved6:7;       // bit 56:62
+  UINT32   Reserved5:7;       // bit 56:62
   UINT32   Hs400:1;           // bit 63
 } SD_MMC_HC_SLOT_CAP;
 
 //
 // SD Host controller version
 //
-#define SD_MMC_HC_CTRL_VER_100      0x00
-#define SD_MMC_HC_CTRL_VER_200      0x01
-#define SD_MMC_HC_CTRL_VER_300      0x02
-#define SD_MMC_HC_CTRL_VER_400      0x03
-#define SD_MMC_HC_CTRL_VER_410      0x04
-#define SD_MMC_HC_CTRL_VER_420      0x05
+#define SD_MMC_HC_CTRL_VER_100        0x00
+#define SD_MMC_HC_CTRL_VER_200        0x01
+#define SD_MMC_HC_CTRL_VER_300        0x02
+#define SD_MMC_HC_CTRL_VER_400        0x03
+#define SD_MMC_HC_CTRL_VER_410        0x04
+#define SD_MMC_HC_CTRL_VER_420        0x05
+
+//
+// SD Host controller V4 enhancements
+//
+#define SD_MMC_HC_V4_EN               BIT12
+#define SD_MMC_HC_64_ADDR_EN          BIT13
+#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
 
 /**
   Dump the content of SD/MMC host controller's Capability Register.
@@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
   );
 
 /**
+  Get the controller version information from the specified slot.
+
+  @param[in]  PciIo           The PCI IO protocol instance.
+  @param[in]  Slot            The slot number of the SD card to send the command to.
+  @param[out] Version         The buffer to store the version information.
+
+  @retval EFI_SUCCESS         The operation executes successfully.
+  @retval Others              The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN  UINT8                Slot,
+  OUT UINT16               *Version
+  );
+
+/**
   Set all interrupt status bits in Normal and Error Interrupt Status Enable
   register.
 
@@ -424,6 +470,7 @@ SdMmcHcStopClock (
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
   @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.
 
   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -434,7 +481,8 @@ SdMmcHcClockSupply (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
   IN UINT64                 ClockFreq,
-  IN UINT32                 BaseClkFreq
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   );
 
 /**
@@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
   @param[in] PciIo          The PCI IO protocol instance.
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.
 
   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -492,7 +541,8 @@ EFI_STATUS
 SdMmcHcInitClockFreq (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
-  IN UINT32                 BaseClkFreq
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   );
 
 /**
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2018-12-18 21:29 [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support Ashish Singhal
@ 2018-12-19  1:46 ` Wu, Hao A
  2018-12-19 20:00   ` Ashish Singhal
  2018-12-26 21:24   ` Ashish Singhal
  2019-01-02  6:28 ` Wu, Hao A
  1 sibling, 2 replies; 7+ messages in thread
From: Wu, Hao A @ 2018-12-19  1:46 UTC (permalink / raw)
  To: Ashish Singhal, edk2-devel@lists.01.org

Hi,

Could you grant me some time for reviewing this patch?

I will try to give you the feedbacks before the end of WW01 2019. Sorry for the
potential delay.

Best Regards,
Hao Wu


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ashish Singhal
> Sent: Wednesday, December 19, 2018 5:29 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC
> HC v4 and above Support.
> 
> Add SDMA, ADMA2 and 26b data length support.
> 
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> SDMA registers supporting 64 bit addresses.
> 
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> ADMA descriptors supporting 64 bit addresses.
> 
> If host controller version is above V4.0, enable ADMA2 with 26b data
> length support for better performance. HC 2 register is configured to
> use 26 bit data lengths and ADMA2 descriptors are configured appropriately.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
>  6 files changed, 363 insertions(+), 83 deletions(-)
>  mode change 100755 => 100644
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> old mode 100755
> new mode 100644
> index 2d3fb68..0c5646f
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
>    //
>    // Convert the clock freq unit from MHz to KHz.
>    //
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> index 68485c8..cdcdfa3 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> @@ -864,7 +864,7 @@ SdCardSetBusMode (
>      return Status;
>    }
> 
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1064,7 +1064,7 @@ SdCardIdentification (
>          goto Error;
>        }
> 
> -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private-
> >ControllerVersion[Slot]);
> 
>        gBS->Stall (1000);
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> index a87f8de..b5bc260 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate =
> {
>    {                                 // MaxCurrent
>      0,
>    },
> -  0                                 // ControllerVersion
> +  {
> +    0                               // ControllerVersion
> +  }
>  };
> 
>  SD_DEVICE_PATH    mSdDpTemplate = {
> @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
>    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
>      Private->Slot[Slot].Enable = TRUE;
> 
> +    //
> +    // Get SD/MMC Pci Host Controller Version
> +    //
> +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> >ControllerVersion[Slot]);
> +    if (EFI_ERROR (Status)) {
> +      goto Done;
> +    }
> +
>      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
>      if (EFI_ERROR (Status)) {
>        continue;
> @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
>        Private->BaseClkFreq[Slot]
>        ));
> 
> -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> +    //
> +    // If any of the slots does not support 64b system bus
> +    // do not enable 64b DMA in the PCI layer.
> +    //
> +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> +        Private->Capability[Slot].SysBus64V4 == 0) {
> +      Support64BitDma = FALSE;
> +    }
> 
>      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> >MaxCurrent[Slot]);
>      if (EFI_ERROR (Status)) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index 8c1a589..1bb701a 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -116,8 +117,7 @@ typedef struct {
>    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
>    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
>    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> -
> -  UINT32                              ControllerVersion;
> +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
> 
>    //
>    // Some controllers may require to override base clock frequency
> @@ -150,7 +150,8 @@ typedef struct {
>    BOOLEAN                             Started;
>    UINT64                              Timeout;
> 
> -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
>    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
>    VOID                                *AdmaMap;
>    UINT32                              AdmaPages;
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> index ddf6dcf..6086720 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> @@ -4,6 +4,7 @@
> 
>    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
> 
> +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
> @@ -45,7 +46,8 @@ DumpCapabilityReg (
>    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> "TRUE" : "FALSE"));
> -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> >SysBus64V4 ? "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> >SysBus64V3 ? "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   SlotType          "));
>    if (Capability->SlotType == 0x00) {
> @@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
>  }
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN     UINT8                Slot,
> +  OUT    UINT16               *Version
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (UINT16), Version);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *Version &= 0xFF;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Software reset the specified SD/MMC host controller and enable all
> interrupts.
> 
>    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> instance.
> @@ -722,6 +754,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
>    UINT32                    SettingFreq;
>    UINT32                    Divisor;
>    UINT32                    Remainder;
> -  UINT16                    ControllerVer;
>    UINT16                    ClockCtrl;
> 
>    //
> @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> 
>    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d
> ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> 
> -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (ControllerVer), &ControllerVer);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
>    //
>    // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock
> Control register.
>    //
> -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
>      ASSERT (Divisor <= 0x3FF);
>      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
> +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
>  }
> 
>  /**
> +  Configure V4 controller enhancements at initialization.
> +
> +  @param[in] PciIo          The PCI IO protocol instance.
> +  @param[in] Slot           The slot number of the SD card to send the
> command to.
> +  @param[in] Capability     The capability of the slot.
> +  @param[in] ControllerVer  The version of host controller.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcInitV4Enhancements (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability,
> +  IN UINT16                 ControllerVer
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if controller version V4 or higher
> +  //
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN;
> +    //
> +    // Check if V4 64bit support is available
> +    //
> +    if (Capability.SysBus64V4 != 0) {
> +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> +    }
> +    //
> +    // Check if controller version V4.10 or higher
> +    //
> +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> support\n"));
> +    }
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
> 
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -948,7 +1029,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
> @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
>    // Supply 400KHz clock frequency at initialization phase.
>    //
>    InitFreq = 400;
> -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> ControllerVer);
>    return Status;
>  }
> 
> @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
> 
> -  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private-
> >ControllerVersion[Slot]);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
>  /**
>    Build ADMA descriptor table for transfer.
> 
> -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> 
>    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
>    @retval Others            The ADMA descriptor table isn't created successfully.
> @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
>  **/
>  EFI_STATUS
>  BuildAdmaDescTable (
> -  IN SD_MMC_HC_TRB          *Trb
> +  IN SD_MMC_HC_TRB          *Trb,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_PHYSICAL_ADDRESS      Data;
> @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  BOOLEAN                   AddressingMode64;
> +  BOOLEAN                   DataLength26;
> +  UINT32                    AdmaMaxDataPerLine;
> +  UINT32                    DescSize;
> +  VOID                      *AdmaDesc;
> +
> +  AddressingMode64   = FALSE;
> +  DataLength26       = FALSE;
> +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  AdmaDesc           = NULL;
> 
>    Data    = Trb->DataPhy;
>    DataLen = Trb->DataLen;
>    PciIo   = Trb->Private->PciIo;
> +
>    //
> -  // Only support 32bit ADMA Descriptor Table
> +  // Detect whether 64bit addressing is supported.
>    //
> -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> +    }
> +  }
> +  //
> +  // Check for valid ranges in 32bit ADMA Descriptor Table
> +  //
> +  if (!AddressingMode64 &&
> +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
>      return EFI_INVALID_PARAMETER;
>    }
>    //
> -  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to
> 0)
> -  // for 32-bit address descriptor table.
> +  // Check address field alignment
>    //
> -  if ((Data & (BIT0 | BIT1)) != 0) {
> -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not
> aligned to 4 bytes boundary!\n", Data));
> +  if (AddressingMode64) {
> +    //
> +    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 8 bytes boundary!\n", Data));
> +    }
> +  } else {
> +    //
> +    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 4 bytes boundary!\n", Data));
> +    }
> +  }
> +  //
> +  // Detect whether 26bit data length is supported.
> +  //
> +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> +  if (!EFI_ERROR (Status)) {
> +    DataLength26 = TRUE;
> +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
>    }
> 
> -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> ADMA_MAX_DATA_PER_LINE);
> -  TableSize = (UINTN)MultU64x32 (Entries, sizeof
> (SD_MMC_HC_ADMA_DESC_LINE));
> +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> AdmaMaxDataPerLine);
> +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
>    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
>    Status = PciIo->AllocateBuffer (
>                      PciIo,
>                      AllocateAnyPages,
>                      EfiBootServicesData,
>                      EFI_SIZE_TO_PAGES (TableSize),
> -                    (VOID **)&Trb->AdmaDesc,
> +                    (VOID **)&AdmaDesc,
>                      0
>                      );
>    if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
> -  ZeroMem (Trb->AdmaDesc, TableSize);
> +  ZeroMem (AdmaDesc, TableSize);
>    Bytes  = TableSize;
>    Status = PciIo->Map (
>                      PciIo,
>                      EfiPciIoOperationBusMasterCommonBuffer,
> -                    Trb->AdmaDesc,
> +                    AdmaDesc,
>                      &Bytes,
>                      &Trb->AdmaDescPhy,
>                      &Trb->AdmaMap
> @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>               PciIo,
>               EFI_SIZE_TO_PAGES (TableSize),
> -             Trb->AdmaDesc
> +             AdmaDesc
>               );
>      return EFI_OUT_OF_RESOURCES;
>    }
> 
> -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> +  if ((!AddressingMode64) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>        PciIo,
>        EFI_SIZE_TO_PAGES (TableSize),
> -      Trb->AdmaDesc
> +      AdmaDesc
>      );
>      return EFI_DEVICE_ERROR;
>    }
> 
>    Remaining = DataLen;
> -  Address   = (UINT32)Data;
> +  Address   = Data;
> +  if (!AddressingMode64) {
> +    Trb->Adma32Desc = AdmaDesc;
> +    Trb->Adma64Desc = NULL;
> +  } else {
> +    Trb->Adma64Desc = AdmaDesc;
> +    Trb->Adma32Desc = NULL;
> +  }
>    for (Index = 0; Index < Entries; Index++) {
> -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> -      Trb->AdmaDesc[Index].Address = Address;
> -      break;
> +    if (!AddressingMode64) {
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma32Desc[Index].LowerLength  = 0;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +      }
>      } else {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = 0;
> -      Trb->AdmaDesc[Index].Address = Address;
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +      }
>      }
> 
> -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> -    Address   += ADMA_MAX_DATA_PER_LINE;
> +    Remaining -= AdmaMaxDataPerLine;
> +    Address   += AdmaMaxDataPerLine;
>    }
> 
>    //
>    // Set the last descriptor line as end of descriptor table
>    //
> -  Trb->AdmaDesc[Index].End = 1;
> +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> >Adma32Desc[Index].End = 1);
>    return EFI_SUCCESS;
>  }
> 
> @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
>        Trb->Mode = SdMmcNoData;
>      } else if (Private->Capability[Slot].Adma2 != 0) {
>        Trb->Mode = SdMmcAdmaMode;
> -      Status = BuildAdmaDescTable (Trb);
> +      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
>        if (EFI_ERROR (Status)) {
>          PciIo->Unmap (PciIo, Trb->DataMap);
>          goto Error;
> @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
>        Trb->AdmaMap
>      );
>    }
> -  if (Trb->AdmaDesc != NULL) {
> +  if (Trb->Adma32Desc != NULL) {
> +    PciIo->FreeBuffer (
> +      PciIo,
> +      Trb->AdmaPages,
> +      Trb->Adma32Desc
> +    );
> +  }
> +  if (Trb->Adma64Desc != NULL) {
>      PciIo->FreeBuffer (
>        PciIo,
>        Trb->AdmaPages,
> -      Trb->AdmaDesc
> +      Trb->Adma64Desc
>      );
>    }
>    if (Trb->DataMap != NULL) {
> @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
>    UINT16                              Cmd;
>    UINT16                              IntStatus;
>    UINT32                              Argument;
> -  UINT16                              BlkCount;
> +  UINT32                              BlkCount;
>    UINT16                              BlkSize;
>    UINT16                              TransMode;
>    UINT8                               HostCtrl1;
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT64                              AdmaAddr;
> +  BOOLEAN                             AddressingMode64;
> +
> +  AddressingMode64 = FALSE;
> 
>    Packet = Trb->Packet;
>    PciIo  = Trb->Private->PciIo;
> @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> 
>    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> 
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +    }
> +  }
> +
>    if (Trb->Mode == SdMmcSdmaMode) {
> -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> +    if ((!AddressingMode64) &&
> +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
>        return EFI_INVALID_PARAMETER;
>      }
> 
> -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (SdmaAddr), &SdmaAddr);
> +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> +    } else {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        return Status;
>      }
> @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
>      //
>      // Calcuate Block Count.
>      //
> -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> +    BlkCount = (Trb->DataLen / Trb->BlockSize);
> +  }
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (UINT32), &BlkCount);
> +  } else {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (UINT16), &BlkCount);
>    }
> -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (BlkCount), &BlkCount);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
>    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
>    UINT16                              IntStatus;
>    UINT32                              Response[4];
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT8                               Index;
>    UINT8                               SwReset;
>    UINT32                              PioLength;
> @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
>      //
>      // Update SDMA Address register.
>      //
> -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> >DataPhy, SD_MMC_SDMA_BOUNDARY);
> -    Status   = SdMmcHcRwMmio (
> +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> SD_MMC_SDMA_BOUNDARY);
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (
> +                 Private->PciIo,
> +                 Trb->Slot,
> +                 SD_MMC_HC_ADMA_SYS_ADDR,
> +                 FALSE,
> +                 sizeof (UINT64),
> +                 &SdmaAddr
> +                 );
> +    } else {
> +      Status = SdMmcHcRwMmio (
>                   Private->PciIo,
>                   Trb->Slot,
>                   SD_MMC_HC_SDMA_ADDR,
> @@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
>                   sizeof (UINT32),
>                   &SdmaAddr
>                   );
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        goto Done;
>      }
> -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
>    }
> 
>    if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc)
> &&
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index dd45cbd..d157f2c 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -91,18 +92,38 @@ typedef enum {
>  //
>  // The maximum data length of each descriptor line
>  //
> -#define ADMA_MAX_DATA_PER_LINE     0x10000
> +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
> 
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
>    UINT32 Int:1;
>    UINT32 Reserved:1;
>    UINT32 Act:2;
> -  UINT32 Reserved1:10;
> -  UINT32 Length:16;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
>    UINT32 Address;
> -} SD_MMC_HC_ADMA_DESC_LINE;
> +} SD_MMC_HC_ADMA_32_DESC_LINE;
> +
> +//
> +// ADMA descriptor for 64b addressing.
> +//
> +typedef struct {
> +  UINT32 Valid:1;
> +  UINT32 End:1;
> +  UINT32 Int:1;
> +  UINT32 Reserved:1;
> +  UINT32 Act:2;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved1;
> +} SD_MMC_HC_ADMA_64_DESC_LINE;
> 
>  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
>  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> @@ -129,36 +150,43 @@ typedef struct {
>    UINT32   Voltage33:1;       // bit 24
>    UINT32   Voltage30:1;       // bit 25
>    UINT32   Voltage18:1;       // bit 26
> -  UINT32   Reserved3:1;       // bit 27
> -  UINT32   SysBus64:1;        // bit 28
> +  UINT32   SysBus64V4:1;      // bit 27
> +  UINT32   SysBus64V3:1;      // bit 28
>    UINT32   AsyncInt:1;        // bit 29
>    UINT32   SlotType:2;        // bit 30:31
>    UINT32   Sdr50:1;           // bit 32
>    UINT32   Sdr104:1;          // bit 33
>    UINT32   Ddr50:1;           // bit 34
> -  UINT32   Reserved4:1;       // bit 35
> +  UINT32   Reserved3:1;       // bit 35
>    UINT32   DriverTypeA:1;     // bit 36
>    UINT32   DriverTypeC:1;     // bit 37
>    UINT32   DriverTypeD:1;     // bit 38
>    UINT32   DriverType4:1;     // bit 39
>    UINT32   TimerCount:4;      // bit 40:43
> -  UINT32   Reserved5:1;       // bit 44
> +  UINT32   Reserved4:1;       // bit 44
>    UINT32   TuningSDR50:1;     // bit 45
>    UINT32   RetuningMod:2;     // bit 46:47
>    UINT32   ClkMultiplier:8;   // bit 48:55
> -  UINT32   Reserved6:7;       // bit 56:62
> +  UINT32   Reserved5:7;       // bit 56:62
>    UINT32   Hs400:1;           // bit 63
>  } SD_MMC_HC_SLOT_CAP;
> 
>  //
>  // SD Host controller version
>  //
> -#define SD_MMC_HC_CTRL_VER_100      0x00
> -#define SD_MMC_HC_CTRL_VER_200      0x01
> -#define SD_MMC_HC_CTRL_VER_300      0x02
> -#define SD_MMC_HC_CTRL_VER_400      0x03
> -#define SD_MMC_HC_CTRL_VER_410      0x04
> -#define SD_MMC_HC_CTRL_VER_420      0x05
> +#define SD_MMC_HC_CTRL_VER_100        0x00
> +#define SD_MMC_HC_CTRL_VER_200        0x01
> +#define SD_MMC_HC_CTRL_VER_300        0x02
> +#define SD_MMC_HC_CTRL_VER_400        0x03
> +#define SD_MMC_HC_CTRL_VER_410        0x04
> +#define SD_MMC_HC_CTRL_VER_420        0x05
> +
> +//
> +// SD Host controller V4 enhancements
> +//
> +#define SD_MMC_HC_V4_EN               BIT12
> +#define SD_MMC_HC_64_ADDR_EN          BIT13
> +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> 
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
>    );
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN  UINT8                Slot,
> +  OUT UINT16               *Version
> +  );
> +
> +/**
>    Set all interrupt status bits in Normal and Error Interrupt Status Enable
>    register.
> 
> @@ -424,6 +470,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -492,7 +541,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> --
> 2.7.4
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2018-12-19  1:46 ` Wu, Hao A
@ 2018-12-19 20:00   ` Ashish Singhal
  2018-12-26 21:24   ` Ashish Singhal
  1 sibling, 0 replies; 7+ messages in thread
From: Ashish Singhal @ 2018-12-19 20:00 UTC (permalink / raw)
  To: Wu, Hao A, edk2-devel@lists.01.org

No problem. Please let me know when you have reviewed it and I will send the final patch with your name as reviewer.


Thanks

Ashish

________________________________
From: Wu, Hao A <hao.a.wu@intel.com>
Sent: Tuesday, December 18, 2018 6:46:57 PM
To: Ashish Singhal; edk2-devel@lists.01.org
Subject: RE: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.

Hi,

Could you grant me some time for reviewing this patch?

I will try to give you the feedbacks before the end of WW01 2019. Sorry for the
potential delay.

Best Regards,
Hao Wu


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ashish Singhal
> Sent: Wednesday, December 19, 2018 5:29 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC
> HC v4 and above Support.
>
> Add SDMA, ADMA2 and 26b data length support.
>
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> SDMA registers supporting 64 bit addresses.
>
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> ADMA descriptors supporting 64 bit addresses.
>
> If host controller version is above V4.0, enable ADMA2 with 26b data
> length support for better performance. HC 2 register is configured to
> use 26 bit data lengths and ADMA2 descriptors are configured appropriately.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
>  6 files changed, 363 insertions(+), 83 deletions(-)
>  mode change 100755 => 100644
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
>
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> old mode 100755
> new mode 100644
> index 2d3fb68..0c5646f
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
>    //
>    // Convert the clock freq unit from MHz to KHz.
>    //
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> index 68485c8..cdcdfa3 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> @@ -864,7 +864,7 @@ SdCardSetBusMode (
>      return Status;
>    }
>
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1064,7 +1064,7 @@ SdCardIdentification (
>          goto Error;
>        }
>
> -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private-
> >ControllerVersion[Slot]);
>
>        gBS->Stall (1000);
>
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> index a87f8de..b5bc260 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate =
> {
>    {                                 // MaxCurrent
>      0,
>    },
> -  0                                 // ControllerVersion
> +  {
> +    0                               // ControllerVersion
> +  }
>  };
>
>  SD_DEVICE_PATH    mSdDpTemplate = {
> @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
>    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
>      Private->Slot[Slot].Enable = TRUE;
>
> +    //
> +    // Get SD/MMC Pci Host Controller Version
> +    //
> +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> >ControllerVersion[Slot]);
> +    if (EFI_ERROR (Status)) {
> +      goto Done;
> +    }
> +
>      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
>      if (EFI_ERROR (Status)) {
>        continue;
> @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
>        Private->BaseClkFreq[Slot]
>        ));
>
> -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> +    //
> +    // If any of the slots does not support 64b system bus
> +    // do not enable 64b DMA in the PCI layer.
> +    //
> +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> +        Private->Capability[Slot].SysBus64V4 == 0) {
> +      Support64BitDma = FALSE;
> +    }
>
>      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> >MaxCurrent[Slot]);
>      if (EFI_ERROR (Status)) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index 8c1a589..1bb701a 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> @@ -2,6 +2,7 @@
>
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
>
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -116,8 +117,7 @@ typedef struct {
>    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
>    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
>    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> -
> -  UINT32                              ControllerVersion;
> +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
>
>    //
>    // Some controllers may require to override base clock frequency
> @@ -150,7 +150,8 @@ typedef struct {
>    BOOLEAN                             Started;
>    UINT64                              Timeout;
>
> -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
>    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
>    VOID                                *AdmaMap;
>    UINT32                              AdmaPages;
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> index ddf6dcf..6086720 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> @@ -4,6 +4,7 @@
>
>    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
>
> +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
> @@ -45,7 +46,8 @@ DumpCapabilityReg (
>    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> "TRUE" : "FALSE"));
> -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> >SysBus64V4 ? "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> >SysBus64V3 ? "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   SlotType          "));
>    if (Capability->SlotType == 0x00) {
> @@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
>  }
>
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN     UINT8                Slot,
> +  OUT    UINT16               *Version
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (UINT16), Version);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *Version &= 0xFF;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Software reset the specified SD/MMC host controller and enable all
> interrupts.
>
>    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> instance.
> @@ -722,6 +754,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
>
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
>    UINT32                    SettingFreq;
>    UINT32                    Divisor;
>    UINT32                    Remainder;
> -  UINT16                    ControllerVer;
>    UINT16                    ClockCtrl;
>
>    //
> @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
>
>    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d
> ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
>
> -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (ControllerVer), &ControllerVer);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
>    //
>    // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock
> Control register.
>    //
> -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
>      ASSERT (Divisor <= 0x3FF);
>      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
> +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
>  }
>
>  /**
> +  Configure V4 controller enhancements at initialization.
> +
> +  @param[in] PciIo          The PCI IO protocol instance.
> +  @param[in] Slot           The slot number of the SD card to send the
> command to.
> +  @param[in] Capability     The capability of the slot.
> +  @param[in] ControllerVer  The version of host controller.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcInitV4Enhancements (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability,
> +  IN UINT16                 ControllerVer
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if controller version V4 or higher
> +  //
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN;
> +    //
> +    // Check if V4 64bit support is available
> +    //
> +    if (Capability.SysBus64V4 != 0) {
> +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> +    }
> +    //
> +    // Check if controller version V4.10 or higher
> +    //
> +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> support\n"));
> +    }
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
>
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
>
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -948,7 +1029,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
> @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
>    // Supply 400KHz clock frequency at initialization phase.
>    //
>    InitFreq = 400;
> -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> ControllerVer);
>    return Status;
>  }
>
> @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
>
> -  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private-
> >ControllerVersion[Slot]);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
>  /**
>    Build ADMA descriptor table for transfer.
>
> -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
>
>    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> +  @param[in] ControllerVer  The version of host controller.
>
>    @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
>    @retval Others            The ADMA descriptor table isn't created successfully.
> @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
>  **/
>  EFI_STATUS
>  BuildAdmaDescTable (
> -  IN SD_MMC_HC_TRB          *Trb
> +  IN SD_MMC_HC_TRB          *Trb,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_PHYSICAL_ADDRESS      Data;
> @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  BOOLEAN                   AddressingMode64;
> +  BOOLEAN                   DataLength26;
> +  UINT32                    AdmaMaxDataPerLine;
> +  UINT32                    DescSize;
> +  VOID                      *AdmaDesc;
> +
> +  AddressingMode64   = FALSE;
> +  DataLength26       = FALSE;
> +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  AdmaDesc           = NULL;
>
>    Data    = Trb->DataPhy;
>    DataLen = Trb->DataLen;
>    PciIo   = Trb->Private->PciIo;
> +
>    //
> -  // Only support 32bit ADMA Descriptor Table
> +  // Detect whether 64bit addressing is supported.
>    //
> -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> +    }
> +  }
> +  //
> +  // Check for valid ranges in 32bit ADMA Descriptor Table
> +  //
> +  if (!AddressingMode64 &&
> +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
>      return EFI_INVALID_PARAMETER;
>    }
>    //
> -  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to
> 0)
> -  // for 32-bit address descriptor table.
> +  // Check address field alignment
>    //
> -  if ((Data & (BIT0 | BIT1)) != 0) {
> -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not
> aligned to 4 bytes boundary!\n", Data));
> +  if (AddressingMode64) {
> +    //
> +    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 8 bytes boundary!\n", Data));
> +    }
> +  } else {
> +    //
> +    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 4 bytes boundary!\n", Data));
> +    }
> +  }
> +  //
> +  // Detect whether 26bit data length is supported.
> +  //
> +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> +  if (!EFI_ERROR (Status)) {
> +    DataLength26 = TRUE;
> +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
>    }
>
> -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> ADMA_MAX_DATA_PER_LINE);
> -  TableSize = (UINTN)MultU64x32 (Entries, sizeof
> (SD_MMC_HC_ADMA_DESC_LINE));
> +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> AdmaMaxDataPerLine);
> +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
>    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
>    Status = PciIo->AllocateBuffer (
>                      PciIo,
>                      AllocateAnyPages,
>                      EfiBootServicesData,
>                      EFI_SIZE_TO_PAGES (TableSize),
> -                    (VOID **)&Trb->AdmaDesc,
> +                    (VOID **)&AdmaDesc,
>                      0
>                      );
>    if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
> -  ZeroMem (Trb->AdmaDesc, TableSize);
> +  ZeroMem (AdmaDesc, TableSize);
>    Bytes  = TableSize;
>    Status = PciIo->Map (
>                      PciIo,
>                      EfiPciIoOperationBusMasterCommonBuffer,
> -                    Trb->AdmaDesc,
> +                    AdmaDesc,
>                      &Bytes,
>                      &Trb->AdmaDescPhy,
>                      &Trb->AdmaMap
> @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>               PciIo,
>               EFI_SIZE_TO_PAGES (TableSize),
> -             Trb->AdmaDesc
> +             AdmaDesc
>               );
>      return EFI_OUT_OF_RESOURCES;
>    }
>
> -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> +  if ((!AddressingMode64) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>        PciIo,
>        EFI_SIZE_TO_PAGES (TableSize),
> -      Trb->AdmaDesc
> +      AdmaDesc
>      );
>      return EFI_DEVICE_ERROR;
>    }
>
>    Remaining = DataLen;
> -  Address   = (UINT32)Data;
> +  Address   = Data;
> +  if (!AddressingMode64) {
> +    Trb->Adma32Desc = AdmaDesc;
> +    Trb->Adma64Desc = NULL;
> +  } else {
> +    Trb->Adma64Desc = AdmaDesc;
> +    Trb->Adma32Desc = NULL;
> +  }
>    for (Index = 0; Index < Entries; Index++) {
> -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> -      Trb->AdmaDesc[Index].Address = Address;
> -      break;
> +    if (!AddressingMode64) {
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma32Desc[Index].LowerLength  = 0;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +      }
>      } else {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = 0;
> -      Trb->AdmaDesc[Index].Address = Address;
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +      }
>      }
>
> -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> -    Address   += ADMA_MAX_DATA_PER_LINE;
> +    Remaining -= AdmaMaxDataPerLine;
> +    Address   += AdmaMaxDataPerLine;
>    }
>
>    //
>    // Set the last descriptor line as end of descriptor table
>    //
> -  Trb->AdmaDesc[Index].End = 1;
> +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> >Adma32Desc[Index].End = 1);
>    return EFI_SUCCESS;
>  }
>
> @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
>        Trb->Mode = SdMmcNoData;
>      } else if (Private->Capability[Slot].Adma2 != 0) {
>        Trb->Mode = SdMmcAdmaMode;
> -      Status = BuildAdmaDescTable (Trb);
> +      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
>        if (EFI_ERROR (Status)) {
>          PciIo->Unmap (PciIo, Trb->DataMap);
>          goto Error;
> @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
>        Trb->AdmaMap
>      );
>    }
> -  if (Trb->AdmaDesc != NULL) {
> +  if (Trb->Adma32Desc != NULL) {
> +    PciIo->FreeBuffer (
> +      PciIo,
> +      Trb->AdmaPages,
> +      Trb->Adma32Desc
> +    );
> +  }
> +  if (Trb->Adma64Desc != NULL) {
>      PciIo->FreeBuffer (
>        PciIo,
>        Trb->AdmaPages,
> -      Trb->AdmaDesc
> +      Trb->Adma64Desc
>      );
>    }
>    if (Trb->DataMap != NULL) {
> @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
>    UINT16                              Cmd;
>    UINT16                              IntStatus;
>    UINT32                              Argument;
> -  UINT16                              BlkCount;
> +  UINT32                              BlkCount;
>    UINT16                              BlkSize;
>    UINT16                              TransMode;
>    UINT8                               HostCtrl1;
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT64                              AdmaAddr;
> +  BOOLEAN                             AddressingMode64;
> +
> +  AddressingMode64 = FALSE;
>
>    Packet = Trb->Packet;
>    PciIo  = Trb->Private->PciIo;
> @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
>
>    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
>
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +    }
> +  }
> +
>    if (Trb->Mode == SdMmcSdmaMode) {
> -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> +    if ((!AddressingMode64) &&
> +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
>        return EFI_INVALID_PARAMETER;
>      }
>
> -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (SdmaAddr), &SdmaAddr);
> +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> +    } else {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        return Status;
>      }
> @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
>      //
>      // Calcuate Block Count.
>      //
> -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> +    BlkCount = (Trb->DataLen / Trb->BlockSize);
> +  }
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (UINT32), &BlkCount);
> +  } else {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (UINT16), &BlkCount);
>    }
> -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (BlkCount), &BlkCount);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
>    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
>    UINT16                              IntStatus;
>    UINT32                              Response[4];
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT8                               Index;
>    UINT8                               SwReset;
>    UINT32                              PioLength;
> @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
>      //
>      // Update SDMA Address register.
>      //
> -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> >DataPhy, SD_MMC_SDMA_BOUNDARY);
> -    Status   = SdMmcHcRwMmio (
> +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> SD_MMC_SDMA_BOUNDARY);
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (
> +                 Private->PciIo,
> +                 Trb->Slot,
> +                 SD_MMC_HC_ADMA_SYS_ADDR,
> +                 FALSE,
> +                 sizeof (UINT64),
> +                 &SdmaAddr
> +                 );
> +    } else {
> +      Status = SdMmcHcRwMmio (
>                   Private->PciIo,
>                   Trb->Slot,
>                   SD_MMC_HC_SDMA_ADDR,
> @@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
>                   sizeof (UINT32),
>                   &SdmaAddr
>                   );
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        goto Done;
>      }
> -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
>    }
>
>    if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc)
> &&
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index dd45cbd..d157f2c 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> @@ -2,6 +2,7 @@
>
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
>
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -91,18 +92,38 @@ typedef enum {
>  //
>  // The maximum data length of each descriptor line
>  //
> -#define ADMA_MAX_DATA_PER_LINE     0x10000
> +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
>
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
>    UINT32 Int:1;
>    UINT32 Reserved:1;
>    UINT32 Act:2;
> -  UINT32 Reserved1:10;
> -  UINT32 Length:16;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
>    UINT32 Address;
> -} SD_MMC_HC_ADMA_DESC_LINE;
> +} SD_MMC_HC_ADMA_32_DESC_LINE;
> +
> +//
> +// ADMA descriptor for 64b addressing.
> +//
> +typedef struct {
> +  UINT32 Valid:1;
> +  UINT32 End:1;
> +  UINT32 Int:1;
> +  UINT32 Reserved:1;
> +  UINT32 Act:2;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved1;
> +} SD_MMC_HC_ADMA_64_DESC_LINE;
>
>  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
>  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> @@ -129,36 +150,43 @@ typedef struct {
>    UINT32   Voltage33:1;       // bit 24
>    UINT32   Voltage30:1;       // bit 25
>    UINT32   Voltage18:1;       // bit 26
> -  UINT32   Reserved3:1;       // bit 27
> -  UINT32   SysBus64:1;        // bit 28
> +  UINT32   SysBus64V4:1;      // bit 27
> +  UINT32   SysBus64V3:1;      // bit 28
>    UINT32   AsyncInt:1;        // bit 29
>    UINT32   SlotType:2;        // bit 30:31
>    UINT32   Sdr50:1;           // bit 32
>    UINT32   Sdr104:1;          // bit 33
>    UINT32   Ddr50:1;           // bit 34
> -  UINT32   Reserved4:1;       // bit 35
> +  UINT32   Reserved3:1;       // bit 35
>    UINT32   DriverTypeA:1;     // bit 36
>    UINT32   DriverTypeC:1;     // bit 37
>    UINT32   DriverTypeD:1;     // bit 38
>    UINT32   DriverType4:1;     // bit 39
>    UINT32   TimerCount:4;      // bit 40:43
> -  UINT32   Reserved5:1;       // bit 44
> +  UINT32   Reserved4:1;       // bit 44
>    UINT32   TuningSDR50:1;     // bit 45
>    UINT32   RetuningMod:2;     // bit 46:47
>    UINT32   ClkMultiplier:8;   // bit 48:55
> -  UINT32   Reserved6:7;       // bit 56:62
> +  UINT32   Reserved5:7;       // bit 56:62
>    UINT32   Hs400:1;           // bit 63
>  } SD_MMC_HC_SLOT_CAP;
>
>  //
>  // SD Host controller version
>  //
> -#define SD_MMC_HC_CTRL_VER_100      0x00
> -#define SD_MMC_HC_CTRL_VER_200      0x01
> -#define SD_MMC_HC_CTRL_VER_300      0x02
> -#define SD_MMC_HC_CTRL_VER_400      0x03
> -#define SD_MMC_HC_CTRL_VER_410      0x04
> -#define SD_MMC_HC_CTRL_VER_420      0x05
> +#define SD_MMC_HC_CTRL_VER_100        0x00
> +#define SD_MMC_HC_CTRL_VER_200        0x01
> +#define SD_MMC_HC_CTRL_VER_300        0x02
> +#define SD_MMC_HC_CTRL_VER_400        0x03
> +#define SD_MMC_HC_CTRL_VER_410        0x04
> +#define SD_MMC_HC_CTRL_VER_420        0x05
> +
> +//
> +// SD Host controller V4 enhancements
> +//
> +#define SD_MMC_HC_V4_EN               BIT12
> +#define SD_MMC_HC_64_ADDR_EN          BIT13
> +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
>
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
>    );
>
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN  UINT8                Slot,
> +  OUT UINT16               *Version
> +  );
> +
> +/**
>    Set all interrupt status bits in Normal and Error Interrupt Status Enable
>    register.
>
> @@ -424,6 +470,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
>
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
>
>  /**
> @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
>
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -492,7 +541,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
>
>  /**
> --
> 2.7.4
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2018-12-19  1:46 ` Wu, Hao A
  2018-12-19 20:00   ` Ashish Singhal
@ 2018-12-26 21:24   ` Ashish Singhal
  1 sibling, 0 replies; 7+ messages in thread
From: Ashish Singhal @ 2018-12-26 21:24 UTC (permalink / raw)
  To: Wu, Hao A, edk2-devel@lists.01.org

Hello Hao,

Do you happen to have any update on this?

Thanks
Ashish

-----Original Message-----
From: Wu, Hao A <hao.a.wu@intel.com> 
Sent: Tuesday, December 18, 2018 6:47 PM
To: Ashish Singhal <ashishsingha@nvidia.com>; edk2-devel@lists.01.org
Subject: RE: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.

Hi,

Could you grant me some time for reviewing this patch?

I will try to give you the feedbacks before the end of WW01 2019. Sorry for the potential delay.

Best Regards,
Hao Wu


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Ashish Singhal
> Sent: Wednesday, December 19, 2018 5:29 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 
> and above Support.
> 
> Add SDMA, ADMA2 and 26b data length support.
> 
> If V4 64 bit address mode is enabled in compatibility register, 
> program controller to enable V4 host mode and use appropriate SDMA 
> registers supporting 64 bit addresses.
> 
> If V4 64 bit address mode is enabled in compatibility register, 
> program controller to enable V4 host mode and use appropriate ADMA 
> descriptors supporting 64 bit addresses.
> 
> If host controller version is above V4.0, enable ADMA2 with 26b data 
> length support for better performance. HC 2 register is configured to 
> use 26 bit data lengths and ADMA2 descriptors are configured appropriately.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
>  6 files changed, 363 insertions(+), 83 deletions(-)  mode change 
> 100755 => 100644 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> old mode 100755
> new mode 100644
> index 2d3fb68..0c5646f
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
>    //
>    // Convert the clock freq unit from MHz to KHz.
>    //
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> + Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> index 68485c8..cdcdfa3 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> @@ -864,7 +864,7 @@ SdCardSetBusMode (
>      return Status;
>    }
> 
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> + Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1064,7 +1064,7 @@ SdCardIdentification (
>          goto Error;
>        }
> 
> -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], 
> + Private-
> >ControllerVersion[Slot]);
> 
>        gBS->Stall (1000);
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> index a87f8de..b5bc260 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
>    {                                 // MaxCurrent
>      0,
>    },
> -  0                                 // ControllerVersion
> +  {
> +    0                               // ControllerVersion
> +  }
>  };
> 
>  SD_DEVICE_PATH    mSdDpTemplate = {
> @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
>    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
>      Private->Slot[Slot].Enable = TRUE;
> 
> +    //
> +    // Get SD/MMC Pci Host Controller Version
> +    //
> +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> >ControllerVersion[Slot]);
> +    if (EFI_ERROR (Status)) {
> +      goto Done;
> +    }
> +
>      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
>      if (EFI_ERROR (Status)) {
>        continue;
> @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
>        Private->BaseClkFreq[Slot]
>        ));
> 
> -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> +    //
> +    // If any of the slots does not support 64b system bus
> +    // do not enable 64b DMA in the PCI layer.
> +    //
> +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> +        Private->Capability[Slot].SysBus64V4 == 0) {
> +      Support64BitDma = FALSE;
> +    }
> 
>      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> >MaxCurrent[Slot]);
>      if (EFI_ERROR (Status)) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index 8c1a589..1bb701a 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host 
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>  This 
> program and the accompanying materials  are licensed and made 
> available under the terms and conditions of the BSD License @@ -116,8 
> +117,7 @@ typedef struct {
>    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
>    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
>    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> -
> -  UINT32                              ControllerVersion;
> +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
> 
>    //
>    // Some controllers may require to override base clock frequency @@ 
> -150,7 +150,8 @@ typedef struct {
>    BOOLEAN                             Started;
>    UINT64                              Timeout;
> 
> -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
>    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
>    VOID                                *AdmaMap;
>    UINT32                              AdmaPages;
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> index ddf6dcf..6086720 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> @@ -4,6 +4,7 @@
> 
>    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
> 
> +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of 
> the BSD License @@ -45,7 +46,8 @@ DumpCapabilityReg (
>    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> "TRUE" : "FALSE"));
> -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> >SysBus64V4 ? "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> >SysBus64V3 ? "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   SlotType          "));
>    if (Capability->SlotType == 0x00) { @@ -417,6 +419,36 @@ 
> SdMmcHcWaitMmioSet (  }
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN     UINT8                Slot,
> +  OUT    UINT16               *Version
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (UINT16), Version);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *Version &= 0xFF;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Software reset the specified SD/MMC host controller and enable all 
> interrupts.
> 
>    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> instance.
> @@ -722,6 +754,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
>    UINT32                    SettingFreq;
>    UINT32                    Divisor;
>    UINT32                    Remainder;
> -  UINT16                    ControllerVer;
>    UINT16                    ClockCtrl;
> 
>    //
> @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> 
>    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq 
> %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> 
> -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, 
> sizeof (ControllerVer), &ControllerVer);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
>    //
>    // Set SDCLK Frequency Select and Internal Clock Enable fields in 
> Clock Control register.
>    //
> -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
>      ASSERT (Divisor <= 0x3FF);
>      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) 
> == 1)) {
> +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (  }
> 
>  /**
> +  Configure V4 controller enhancements at initialization.
> +
> +  @param[in] PciIo          The PCI IO protocol instance.
> +  @param[in] Slot           The slot number of the SD card to send the
> command to.
> +  @param[in] Capability     The capability of the slot.
> +  @param[in] ControllerVer  The version of host controller.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcInitV4Enhancements (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability,
> +  IN UINT16                 ControllerVer
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if controller version V4 or higher  //  if (ControllerVer 
> + >= SD_MMC_HC_CTRL_VER_400) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN;
> +    //
> +    // Check if V4 64bit support is available
> +    //
> +    if (Capability.SysBus64V4 != 0) {
> +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> +    }
> +    //
> +    // Check if controller version V4.10 or higher
> +    //
> +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> support\n"));
> +    }
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
> 
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -948,7 +1029,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
> @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
>    // Supply 400KHz clock frequency at initialization phase.
>    //
>    InitFreq = 400;
> -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> ControllerVer);
>    return Status;
>  }
> 
> @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
> 
> -  Status = SdMmcHcInitClockFreq (PciIo, Slot, 
> Private->BaseClkFreq[Slot]);
> +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, 
> + Private-
> >ControllerVersion[Slot]);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = SdMmcHcInitClockFreq (PciIo, Slot, 
> + Private->BaseClkFreq[Slot],
> Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
>  /**
>    Build ADMA descriptor table for transfer.
> 
> -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> 
>    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
>    @retval Others            The ADMA descriptor table isn't created successfully.
> @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (  **/  EFI_STATUS  
> BuildAdmaDescTable (
> -  IN SD_MMC_HC_TRB          *Trb
> +  IN SD_MMC_HC_TRB          *Trb,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_PHYSICAL_ADDRESS      Data;
> @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  BOOLEAN                   AddressingMode64;
> +  BOOLEAN                   DataLength26;
> +  UINT32                    AdmaMaxDataPerLine;
> +  UINT32                    DescSize;
> +  VOID                      *AdmaDesc;
> +
> +  AddressingMode64   = FALSE;
> +  DataLength26       = FALSE;
> +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  AdmaDesc           = NULL;
> 
>    Data    = Trb->DataPhy;
>    DataLen = Trb->DataLen;
>    PciIo   = Trb->Private->PciIo;
> +
>    //
> -  // Only support 32bit ADMA Descriptor Table
> +  // Detect whether 64bit addressing is supported.
>    //
> -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) 
> {
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 
> + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> +    }
> +  }
> +  //
> +  // Check for valid ranges in 32bit ADMA Descriptor Table  //  if 
> + (!AddressingMode64 &&
> +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 
> + 0x100000000ul))) {
>      return EFI_INVALID_PARAMETER;
>    }
>    //
> -  // Address field shall be set on 32-bit boundary (Lower 2-bit is 
> always set to
> 0)
> -  // for 32-bit address descriptor table.
> +  // Check address field alignment
>    //
> -  if ((Data & (BIT0 | BIT1)) != 0) {
> -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not
> aligned to 4 bytes boundary!\n", Data));
> +  if (AddressingMode64) {
> +    //
> +    // Address field shall be set on 64-bit boundary (Lower 3-bit is 
> + always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc 
> + is
> not aligned to 8 bytes boundary!\n", Data));
> +    }
> +  } else {
> +    //
> +    // Address field shall be set on 32-bit boundary (Lower 2-bit is 
> + always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc 
> + is
> not aligned to 4 bytes boundary!\n", Data));
> +    }
> +  }
> +  //
> +  // Detect whether 26bit data length is supported.
> +  //
> +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> +  if (!EFI_ERROR (Status)) {
> +    DataLength26 = TRUE;
> +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
>    }
> 
> -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> ADMA_MAX_DATA_PER_LINE);
> -  TableSize = (UINTN)MultU64x32 (Entries, sizeof 
> (SD_MMC_HC_ADMA_DESC_LINE));
> +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> AdmaMaxDataPerLine);
> +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
>    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
>    Status = PciIo->AllocateBuffer (
>                      PciIo,
>                      AllocateAnyPages,
>                      EfiBootServicesData,
>                      EFI_SIZE_TO_PAGES (TableSize),
> -                    (VOID **)&Trb->AdmaDesc,
> +                    (VOID **)&AdmaDesc,
>                      0
>                      );
>    if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
> -  ZeroMem (Trb->AdmaDesc, TableSize);
> +  ZeroMem (AdmaDesc, TableSize);
>    Bytes  = TableSize;
>    Status = PciIo->Map (
>                      PciIo,
>                      EfiPciIoOperationBusMasterCommonBuffer,
> -                    Trb->AdmaDesc,
> +                    AdmaDesc,
>                      &Bytes,
>                      &Trb->AdmaDescPhy,
>                      &Trb->AdmaMap
> @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>               PciIo,
>               EFI_SIZE_TO_PAGES (TableSize),
> -             Trb->AdmaDesc
> +             AdmaDesc
>               );
>      return EFI_OUT_OF_RESOURCES;
>    }
> 
> -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> +  if ((!AddressingMode64) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>        PciIo,
>        EFI_SIZE_TO_PAGES (TableSize),
> -      Trb->AdmaDesc
> +      AdmaDesc
>      );
>      return EFI_DEVICE_ERROR;
>    }
> 
>    Remaining = DataLen;
> -  Address   = (UINT32)Data;
> +  Address   = Data;
> +  if (!AddressingMode64) {
> +    Trb->Adma32Desc = AdmaDesc;
> +    Trb->Adma64Desc = NULL;
> +  } else {
> +    Trb->Adma64Desc = AdmaDesc;
> +    Trb->Adma32Desc = NULL;
> +  }
>    for (Index = 0; Index < Entries; Index++) {
> -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> -      Trb->AdmaDesc[Index].Address = Address;
> -      break;
> +    if (!AddressingMode64) {
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma32Desc[Index].LowerLength  = 0;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +      }
>      } else {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = 0;
> -      Trb->AdmaDesc[Index].Address = Address;
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +      }
>      }
> 
> -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> -    Address   += ADMA_MAX_DATA_PER_LINE;
> +    Remaining -= AdmaMaxDataPerLine;
> +    Address   += AdmaMaxDataPerLine;
>    }
> 
>    //
>    // Set the last descriptor line as end of descriptor table
>    //
> -  Trb->AdmaDesc[Index].End = 1;
> +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> >Adma32Desc[Index].End = 1);
>    return EFI_SUCCESS;
>  }
> 
> @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
>        Trb->Mode = SdMmcNoData;
>      } else if (Private->Capability[Slot].Adma2 != 0) {
>        Trb->Mode = SdMmcAdmaMode;
> -      Status = BuildAdmaDescTable (Trb);
> +      Status = BuildAdmaDescTable (Trb, 
> + Private->ControllerVersion[Slot]);
>        if (EFI_ERROR (Status)) {
>          PciIo->Unmap (PciIo, Trb->DataMap);
>          goto Error;
> @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
>        Trb->AdmaMap
>      );
>    }
> -  if (Trb->AdmaDesc != NULL) {
> +  if (Trb->Adma32Desc != NULL) {
> +    PciIo->FreeBuffer (
> +      PciIo,
> +      Trb->AdmaPages,
> +      Trb->Adma32Desc
> +    );
> +  }
> +  if (Trb->Adma64Desc != NULL) {
>      PciIo->FreeBuffer (
>        PciIo,
>        Trb->AdmaPages,
> -      Trb->AdmaDesc
> +      Trb->Adma64Desc
>      );
>    }
>    if (Trb->DataMap != NULL) {
> @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
>    UINT16                              Cmd;
>    UINT16                              IntStatus;
>    UINT32                              Argument;
> -  UINT16                              BlkCount;
> +  UINT32                              BlkCount;
>    UINT16                              BlkSize;
>    UINT16                              TransMode;
>    UINT8                               HostCtrl1;
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT64                              AdmaAddr;
> +  BOOLEAN                             AddressingMode64;
> +
> +  AddressingMode64 = FALSE;
> 
>    Packet = Trb->Packet;
>    PciIo  = Trb->Private->PciIo;
> @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> 
>    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> 
> +  if (Private->ControllerVersion[Trb->Slot] >= 
> + SD_MMC_HC_CTRL_VER_400)
> {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 
> + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +    }
> +  }
> +
>    if (Trb->Mode == SdMmcSdmaMode) {
> -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> +    if ((!AddressingMode64) &&
> +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
>        return EFI_INVALID_PARAMETER;
>      }
> 
> -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (SdmaAddr), &SdmaAddr);
> +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= 
> + SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> +    } else {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        return Status;
>      }
> @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
>      //
>      // Calcuate Block Count.
>      //
> -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> +    BlkCount = (Trb->DataLen / Trb->BlockSize);  }  if 
> + (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (UINT32), &BlkCount);
> +  } else {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (UINT16), &BlkCount);
>    }
> -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (BlkCount), &BlkCount);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
>    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
>    UINT16                              IntStatus;
>    UINT32                              Response[4];
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT8                               Index;
>    UINT8                               SwReset;
>    UINT32                              PioLength;
> @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
>      //
>      // Update SDMA Address register.
>      //
> -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> >DataPhy, SD_MMC_SDMA_BOUNDARY);
> -    Status   = SdMmcHcRwMmio (
> +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> SD_MMC_SDMA_BOUNDARY);
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= 
> + SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (
> +                 Private->PciIo,
> +                 Trb->Slot,
> +                 SD_MMC_HC_ADMA_SYS_ADDR,
> +                 FALSE,
> +                 sizeof (UINT64),
> +                 &SdmaAddr
> +                 );
> +    } else {
> +      Status = SdMmcHcRwMmio (
>                   Private->PciIo,
>                   Trb->Slot,
>                   SD_MMC_HC_SDMA_ADDR, @@ -1972,10 +2182,12 @@ 
> SdMmcCheckTrbResult (
>                   sizeof (UINT32),
>                   &SdmaAddr
>                   );
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        goto Done;
>      }
> -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
>    }
> 
>    if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) && 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index dd45cbd..d157f2c 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host 
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>  This 
> program and the accompanying materials  are licensed and made 
> available under the terms and conditions of the BSD License @@ -91,18 
> +92,38 @@ typedef enum {  //  // The maximum data length of each 
> descriptor line  //
> -#define ADMA_MAX_DATA_PER_LINE     0x10000
> +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
> 
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
>    UINT32 Int:1;
>    UINT32 Reserved:1;
>    UINT32 Act:2;
> -  UINT32 Reserved1:10;
> -  UINT32 Length:16;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
>    UINT32 Address;
> -} SD_MMC_HC_ADMA_DESC_LINE;
> +} SD_MMC_HC_ADMA_32_DESC_LINE;
> +
> +//
> +// ADMA descriptor for 64b addressing.
> +//
> +typedef struct {
> +  UINT32 Valid:1;
> +  UINT32 End:1;
> +  UINT32 Int:1;
> +  UINT32 Reserved:1;
> +  UINT32 Act:2;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved1;
> +} SD_MMC_HC_ADMA_64_DESC_LINE;
> 
>  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
>  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> @@ -129,36 +150,43 @@ typedef struct {
>    UINT32   Voltage33:1;       // bit 24
>    UINT32   Voltage30:1;       // bit 25
>    UINT32   Voltage18:1;       // bit 26
> -  UINT32   Reserved3:1;       // bit 27
> -  UINT32   SysBus64:1;        // bit 28
> +  UINT32   SysBus64V4:1;      // bit 27
> +  UINT32   SysBus64V3:1;      // bit 28
>    UINT32   AsyncInt:1;        // bit 29
>    UINT32   SlotType:2;        // bit 30:31
>    UINT32   Sdr50:1;           // bit 32
>    UINT32   Sdr104:1;          // bit 33
>    UINT32   Ddr50:1;           // bit 34
> -  UINT32   Reserved4:1;       // bit 35
> +  UINT32   Reserved3:1;       // bit 35
>    UINT32   DriverTypeA:1;     // bit 36
>    UINT32   DriverTypeC:1;     // bit 37
>    UINT32   DriverTypeD:1;     // bit 38
>    UINT32   DriverType4:1;     // bit 39
>    UINT32   TimerCount:4;      // bit 40:43
> -  UINT32   Reserved5:1;       // bit 44
> +  UINT32   Reserved4:1;       // bit 44
>    UINT32   TuningSDR50:1;     // bit 45
>    UINT32   RetuningMod:2;     // bit 46:47
>    UINT32   ClkMultiplier:8;   // bit 48:55
> -  UINT32   Reserved6:7;       // bit 56:62
> +  UINT32   Reserved5:7;       // bit 56:62
>    UINT32   Hs400:1;           // bit 63
>  } SD_MMC_HC_SLOT_CAP;
> 
>  //
>  // SD Host controller version
>  //
> -#define SD_MMC_HC_CTRL_VER_100      0x00
> -#define SD_MMC_HC_CTRL_VER_200      0x01
> -#define SD_MMC_HC_CTRL_VER_300      0x02
> -#define SD_MMC_HC_CTRL_VER_400      0x03
> -#define SD_MMC_HC_CTRL_VER_410      0x04
> -#define SD_MMC_HC_CTRL_VER_420      0x05
> +#define SD_MMC_HC_CTRL_VER_100        0x00
> +#define SD_MMC_HC_CTRL_VER_200        0x01
> +#define SD_MMC_HC_CTRL_VER_300        0x02
> +#define SD_MMC_HC_CTRL_VER_400        0x03
> +#define SD_MMC_HC_CTRL_VER_410        0x04
> +#define SD_MMC_HC_CTRL_VER_420        0x05
> +
> +//
> +// SD Host controller V4 enhancements //
> +#define SD_MMC_HC_V4_EN               BIT12
> +#define SD_MMC_HC_64_ADDR_EN          BIT13
> +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> 
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
>    );
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN  UINT8                Slot,
> +  OUT UINT16               *Version
> +  );
> +
> +/**
>    Set all interrupt status bits in Normal and Error Interrupt Status Enable
>    register.
> 
> @@ -424,6 +470,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -492,7 +541,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> --
> 2.7.4
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2018-12-18 21:29 [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support Ashish Singhal
  2018-12-19  1:46 ` Wu, Hao A
@ 2019-01-02  6:28 ` Wu, Hao A
  2019-01-02  6:36   ` Wu, Hao A
  1 sibling, 1 reply; 7+ messages in thread
From: Wu, Hao A @ 2019-01-02  6:28 UTC (permalink / raw)
  To: Ashish Singhal, edk2-devel@lists.01.org

Hello,

I have 2 minor comments, please refer to those inline comments.
Apart from that, the patch is good to me:
Reviewed-by: Hao Wu <hao.a.wu@intel.com>

If you agree those inline comments, I will directly modify the patch on my
side and then push it into the repository.

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ashish Singhal
> Sent: Wednesday, December 19, 2018 5:29 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC
> HC v4 and above Support.

Add the Bugzilla tracker information at the start of the commit log message:

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1359

> 
> Add SDMA, ADMA2 and 26b data length support.
> 
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> SDMA registers supporting 64 bit addresses.
> 
> If V4 64 bit address mode is enabled in compatibility register,
> program controller to enable V4 host mode and use appropriate
> ADMA descriptors supporting 64 bit addresses.
> 
> If host controller version is above V4.0, enable ADMA2 with 26b data
> length support for better performance. HC 2 register is configured to
> use 26 bit data lengths and ADMA2 descriptors are configured appropriately.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
>  6 files changed, 363 insertions(+), 83 deletions(-)
>  mode change 100755 => 100644
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> old mode 100755
> new mode 100644
> index 2d3fb68..0c5646f
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
>    //
>    // Convert the clock freq unit from MHz to KHz.
>    //
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> index 68485c8..cdcdfa3 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> @@ -864,7 +864,7 @@ SdCardSetBusMode (
>      return Status;
>    }
> 
> -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot]);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1064,7 +1064,7 @@ SdCardIdentification (
>          goto Error;
>        }
> 
> -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private-
> >ControllerVersion[Slot]);
> 
>        gBS->Stall (1000);
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> index a87f8de..b5bc260 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate =
> {
>    {                                 // MaxCurrent
>      0,
>    },
> -  0                                 // ControllerVersion
> +  {
> +    0                               // ControllerVersion
> +  }
>  };
> 
>  SD_DEVICE_PATH    mSdDpTemplate = {
> @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
>    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
>      Private->Slot[Slot].Enable = TRUE;
> 
> +    //
> +    // Get SD/MMC Pci Host Controller Version
> +    //
> +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> >ControllerVersion[Slot]);
> +    if (EFI_ERROR (Status)) {
> +      goto Done;

Like other error handling in the for loop:
Instead of "goto Done;", change to "continue;".


Thanks for the patience.

Best Regards,
Hao Wu

> +    }
> +
>      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
>      if (EFI_ERROR (Status)) {
>        continue;
> @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
>        Private->BaseClkFreq[Slot]
>        ));
> 
> -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> +    //
> +    // If any of the slots does not support 64b system bus
> +    // do not enable 64b DMA in the PCI layer.
> +    //
> +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> +        Private->Capability[Slot].SysBus64V4 == 0) {
> +      Support64BitDma = FALSE;
> +    }
> 
>      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> >MaxCurrent[Slot]);
>      if (EFI_ERROR (Status)) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index 8c1a589..1bb701a 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -116,8 +117,7 @@ typedef struct {
>    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
>    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
>    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> -
> -  UINT32                              ControllerVersion;
> +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
> 
>    //
>    // Some controllers may require to override base clock frequency
> @@ -150,7 +150,8 @@ typedef struct {
>    BOOLEAN                             Started;
>    UINT64                              Timeout;
> 
> -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
>    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
>    VOID                                *AdmaMap;
>    UINT32                              AdmaPages;
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> index ddf6dcf..6086720 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> @@ -4,6 +4,7 @@
> 
>    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
> 
> +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
> @@ -45,7 +46,8 @@ DumpCapabilityReg (
>    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> "TRUE" : "FALSE"));
> -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> >SysBus64V4 ? "TRUE" : "FALSE"));
> +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> >SysBus64V3 ? "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> "TRUE" : "FALSE"));
>    DEBUG ((DEBUG_INFO, "   SlotType          "));
>    if (Capability->SlotType == 0x00) {
> @@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
>  }
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN     UINT8                Slot,
> +  OUT    UINT16               *Version
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (UINT16), Version);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *Version &= 0xFF;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Software reset the specified SD/MMC host controller and enable all
> interrupts.
> 
>    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> instance.
> @@ -722,6 +754,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
>    UINT32                    SettingFreq;
>    UINT32                    Divisor;
>    UINT32                    Remainder;
> -  UINT16                    ControllerVer;
>    UINT16                    ClockCtrl;
> 
>    //
> @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> 
>    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d
> ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> 
> -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> sizeof (ControllerVer), &ControllerVer);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
>    //
>    // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock
> Control register.
>    //
> -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
>      ASSERT (Divisor <= 0x3FF);
>      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
> +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
>  }
> 
>  /**
> +  Configure V4 controller enhancements at initialization.
> +
> +  @param[in] PciIo          The PCI IO protocol instance.
> +  @param[in] Slot           The slot number of the SD card to send the
> command to.
> +  @param[in] Capability     The capability of the slot.
> +  @param[in] ControllerVer  The version of host controller.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcInitV4Enhancements (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability,
> +  IN UINT16                 ControllerVer
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if controller version V4 or higher
> +  //
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN;
> +    //
> +    // Check if V4 64bit support is available
> +    //
> +    if (Capability.SysBus64V4 != 0) {
> +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> +    }
> +    //
> +    // Check if controller version V4.10 or higher
> +    //
> +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> support\n"));
> +    }
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
> 
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -948,7 +1029,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_STATUS                Status;
> @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
>    // Supply 400KHz clock frequency at initialization phase.
>    //
>    InitFreq = 400;
> -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> ControllerVer);
>    return Status;
>  }
> 
> @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
> 
> -  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private-
> >ControllerVersion[Slot]);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> Private->ControllerVersion[Slot]);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
>  /**
>    Build ADMA descriptor table for transfer.
> 
> -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> 
>    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
>    @retval Others            The ADMA descriptor table isn't created successfully.
> @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
>  **/
>  EFI_STATUS
>  BuildAdmaDescTable (
> -  IN SD_MMC_HC_TRB          *Trb
> +  IN SD_MMC_HC_TRB          *Trb,
> +  IN UINT16                 ControllerVer
>    )
>  {
>    EFI_PHYSICAL_ADDRESS      Data;
> @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  BOOLEAN                   AddressingMode64;
> +  BOOLEAN                   DataLength26;
> +  UINT32                    AdmaMaxDataPerLine;
> +  UINT32                    DescSize;
> +  VOID                      *AdmaDesc;
> +
> +  AddressingMode64   = FALSE;
> +  DataLength26       = FALSE;
> +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  AdmaDesc           = NULL;
> 
>    Data    = Trb->DataPhy;
>    DataLen = Trb->DataLen;
>    PciIo   = Trb->Private->PciIo;
> +
>    //
> -  // Only support 32bit ADMA Descriptor Table
> +  // Detect whether 64bit addressing is supported.
>    //
> -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> +    }
> +  }
> +  //
> +  // Check for valid ranges in 32bit ADMA Descriptor Table
> +  //
> +  if (!AddressingMode64 &&
> +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
>      return EFI_INVALID_PARAMETER;
>    }
>    //
> -  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to
> 0)
> -  // for 32-bit address descriptor table.
> +  // Check address field alignment
>    //
> -  if ((Data & (BIT0 | BIT1)) != 0) {
> -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not
> aligned to 4 bytes boundary!\n", Data));
> +  if (AddressingMode64) {
> +    //
> +    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 8 bytes boundary!\n", Data));
> +    }
> +  } else {
> +    //
> +    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set
> to 0)
> +    //
> +    if ((Data & (BIT0 | BIT1)) != 0) {
> +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not aligned to 4 bytes boundary!\n", Data));
> +    }
> +  }
> +  //
> +  // Detect whether 26bit data length is supported.
> +  //
> +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> +  if (!EFI_ERROR (Status)) {
> +    DataLength26 = TRUE;
> +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
>    }
> 
> -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> ADMA_MAX_DATA_PER_LINE);
> -  TableSize = (UINTN)MultU64x32 (Entries, sizeof
> (SD_MMC_HC_ADMA_DESC_LINE));
> +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> AdmaMaxDataPerLine);
> +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
>    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
>    Status = PciIo->AllocateBuffer (
>                      PciIo,
>                      AllocateAnyPages,
>                      EfiBootServicesData,
>                      EFI_SIZE_TO_PAGES (TableSize),
> -                    (VOID **)&Trb->AdmaDesc,
> +                    (VOID **)&AdmaDesc,
>                      0
>                      );
>    if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
> -  ZeroMem (Trb->AdmaDesc, TableSize);
> +  ZeroMem (AdmaDesc, TableSize);
>    Bytes  = TableSize;
>    Status = PciIo->Map (
>                      PciIo,
>                      EfiPciIoOperationBusMasterCommonBuffer,
> -                    Trb->AdmaDesc,
> +                    AdmaDesc,
>                      &Bytes,
>                      &Trb->AdmaDescPhy,
>                      &Trb->AdmaMap
> @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>               PciIo,
>               EFI_SIZE_TO_PAGES (TableSize),
> -             Trb->AdmaDesc
> +             AdmaDesc
>               );
>      return EFI_OUT_OF_RESOURCES;
>    }
> 
> -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> +  if ((!AddressingMode64) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
>      PciIo->FreeBuffer (
>        PciIo,
>        EFI_SIZE_TO_PAGES (TableSize),
> -      Trb->AdmaDesc
> +      AdmaDesc
>      );
>      return EFI_DEVICE_ERROR;
>    }
> 
>    Remaining = DataLen;
> -  Address   = (UINT32)Data;
> +  Address   = Data;
> +  if (!AddressingMode64) {
> +    Trb->Adma32Desc = AdmaDesc;
> +    Trb->Adma64Desc = NULL;
> +  } else {
> +    Trb->Adma64Desc = AdmaDesc;
> +    Trb->Adma32Desc = NULL;
> +  }
>    for (Index = 0; Index < Entries; Index++) {
> -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> -      Trb->AdmaDesc[Index].Address = Address;
> -      break;
> +    if (!AddressingMode64) {
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma32Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma32Desc[Index].LowerLength  = 0;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +      }
>      } else {
> -      Trb->AdmaDesc[Index].Valid = 1;
> -      Trb->AdmaDesc[Index].Act   = 2;
> -      Trb->AdmaDesc[Index].Length  = 0;
> -      Trb->AdmaDesc[Index].Address = Address;
> +      if (Remaining <= AdmaMaxDataPerLine) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> MAX_UINT16);
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        if (DataLength26) {
> +          Trb->Adma64Desc[Index].UpperLength  = 0;
> +        }
> +        Trb->Adma64Desc[Index].LowerLength  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> +      }
>      }
> 
> -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> -    Address   += ADMA_MAX_DATA_PER_LINE;
> +    Remaining -= AdmaMaxDataPerLine;
> +    Address   += AdmaMaxDataPerLine;
>    }
> 
>    //
>    // Set the last descriptor line as end of descriptor table
>    //
> -  Trb->AdmaDesc[Index].End = 1;
> +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> >Adma32Desc[Index].End = 1);
>    return EFI_SUCCESS;
>  }
> 
> @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
>        Trb->Mode = SdMmcNoData;
>      } else if (Private->Capability[Slot].Adma2 != 0) {
>        Trb->Mode = SdMmcAdmaMode;
> -      Status = BuildAdmaDescTable (Trb);
> +      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
>        if (EFI_ERROR (Status)) {
>          PciIo->Unmap (PciIo, Trb->DataMap);
>          goto Error;
> @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
>        Trb->AdmaMap
>      );
>    }
> -  if (Trb->AdmaDesc != NULL) {
> +  if (Trb->Adma32Desc != NULL) {
> +    PciIo->FreeBuffer (
> +      PciIo,
> +      Trb->AdmaPages,
> +      Trb->Adma32Desc
> +    );
> +  }
> +  if (Trb->Adma64Desc != NULL) {
>      PciIo->FreeBuffer (
>        PciIo,
>        Trb->AdmaPages,
> -      Trb->AdmaDesc
> +      Trb->Adma64Desc
>      );
>    }
>    if (Trb->DataMap != NULL) {
> @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
>    UINT16                              Cmd;
>    UINT16                              IntStatus;
>    UINT32                              Argument;
> -  UINT16                              BlkCount;
> +  UINT32                              BlkCount;
>    UINT16                              BlkSize;
>    UINT16                              TransMode;
>    UINT8                               HostCtrl1;
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT64                              AdmaAddr;
> +  BOOLEAN                             AddressingMode64;
> +
> +  AddressingMode64 = FALSE;
> 
>    Packet = Trb->Packet;
>    PciIo  = Trb->Private->PciIo;
> @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> 
>    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> 
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> +    if (!EFI_ERROR (Status)) {
> +      AddressingMode64 = TRUE;
> +    }
> +  }
> +
>    if (Trb->Mode == SdMmcSdmaMode) {
> -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> +    if ((!AddressingMode64) &&
> +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
>        return EFI_INVALID_PARAMETER;
>      }
> 
> -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (SdmaAddr), &SdmaAddr);
> +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> +    } else {
> +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        return Status;
>      }
> @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
>      //
>      // Calcuate Block Count.
>      //
> -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> +    BlkCount = (Trb->DataLen / Trb->BlockSize);
> +  }
> +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> FALSE, sizeof (UINT32), &BlkCount);
> +  } else {
> +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (UINT16), &BlkCount);
>    }
> -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> FALSE, sizeof (BlkCount), &BlkCount);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
>    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
>    UINT16                              IntStatus;
>    UINT32                              Response[4];
> -  UINT32                              SdmaAddr;
> +  UINT64                              SdmaAddr;
>    UINT8                               Index;
>    UINT8                               SwReset;
>    UINT32                              PioLength;
> @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
>      //
>      // Update SDMA Address register.
>      //
> -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> >DataPhy, SD_MMC_SDMA_BOUNDARY);
> -    Status   = SdMmcHcRwMmio (
> +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> SD_MMC_SDMA_BOUNDARY);
> +
> +    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> {
> +      Status = SdMmcHcRwMmio (
> +                 Private->PciIo,
> +                 Trb->Slot,
> +                 SD_MMC_HC_ADMA_SYS_ADDR,
> +                 FALSE,
> +                 sizeof (UINT64),
> +                 &SdmaAddr
> +                 );
> +    } else {
> +      Status = SdMmcHcRwMmio (
>                   Private->PciIo,
>                   Trb->Slot,
>                   SD_MMC_HC_SDMA_ADDR,
> @@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
>                   sizeof (UINT32),
>                   &SdmaAddr
>                   );
> +    }
> +
>      if (EFI_ERROR (Status)) {
>        goto Done;
>      }
> -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
>    }
> 
>    if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc)
> &&
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index dd45cbd..d157f2c 100644
> --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> @@ -2,6 +2,7 @@
> 
>    Provides some data structure definitions used by the SD/MMC host
> controller driver.
> 
> +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
> @@ -91,18 +92,38 @@ typedef enum {
>  //
>  // The maximum data length of each descriptor line
>  //
> -#define ADMA_MAX_DATA_PER_LINE     0x10000
> +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
> 
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
>    UINT32 Int:1;
>    UINT32 Reserved:1;
>    UINT32 Act:2;
> -  UINT32 Reserved1:10;
> -  UINT32 Length:16;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
>    UINT32 Address;
> -} SD_MMC_HC_ADMA_DESC_LINE;
> +} SD_MMC_HC_ADMA_32_DESC_LINE;
> +
> +//
> +// ADMA descriptor for 64b addressing.
> +//
> +typedef struct {
> +  UINT32 Valid:1;
> +  UINT32 End:1;
> +  UINT32 Int:1;
> +  UINT32 Reserved:1;
> +  UINT32 Act:2;
> +  UINT32 UpperLength:10;
> +  UINT32 LowerLength:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved1;
> +} SD_MMC_HC_ADMA_64_DESC_LINE;
> 
>  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
>  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> @@ -129,36 +150,43 @@ typedef struct {
>    UINT32   Voltage33:1;       // bit 24
>    UINT32   Voltage30:1;       // bit 25
>    UINT32   Voltage18:1;       // bit 26
> -  UINT32   Reserved3:1;       // bit 27
> -  UINT32   SysBus64:1;        // bit 28
> +  UINT32   SysBus64V4:1;      // bit 27
> +  UINT32   SysBus64V3:1;      // bit 28
>    UINT32   AsyncInt:1;        // bit 29
>    UINT32   SlotType:2;        // bit 30:31
>    UINT32   Sdr50:1;           // bit 32
>    UINT32   Sdr104:1;          // bit 33
>    UINT32   Ddr50:1;           // bit 34
> -  UINT32   Reserved4:1;       // bit 35
> +  UINT32   Reserved3:1;       // bit 35
>    UINT32   DriverTypeA:1;     // bit 36
>    UINT32   DriverTypeC:1;     // bit 37
>    UINT32   DriverTypeD:1;     // bit 38
>    UINT32   DriverType4:1;     // bit 39
>    UINT32   TimerCount:4;      // bit 40:43
> -  UINT32   Reserved5:1;       // bit 44
> +  UINT32   Reserved4:1;       // bit 44
>    UINT32   TuningSDR50:1;     // bit 45
>    UINT32   RetuningMod:2;     // bit 46:47
>    UINT32   ClkMultiplier:8;   // bit 48:55
> -  UINT32   Reserved6:7;       // bit 56:62
> +  UINT32   Reserved5:7;       // bit 56:62
>    UINT32   Hs400:1;           // bit 63
>  } SD_MMC_HC_SLOT_CAP;
> 
>  //
>  // SD Host controller version
>  //
> -#define SD_MMC_HC_CTRL_VER_100      0x00
> -#define SD_MMC_HC_CTRL_VER_200      0x01
> -#define SD_MMC_HC_CTRL_VER_300      0x02
> -#define SD_MMC_HC_CTRL_VER_400      0x03
> -#define SD_MMC_HC_CTRL_VER_410      0x04
> -#define SD_MMC_HC_CTRL_VER_420      0x05
> +#define SD_MMC_HC_CTRL_VER_100        0x00
> +#define SD_MMC_HC_CTRL_VER_200        0x01
> +#define SD_MMC_HC_CTRL_VER_300        0x02
> +#define SD_MMC_HC_CTRL_VER_400        0x03
> +#define SD_MMC_HC_CTRL_VER_410        0x04
> +#define SD_MMC_HC_CTRL_VER_420        0x05
> +
> +//
> +// SD Host controller V4 enhancements
> +//
> +#define SD_MMC_HC_V4_EN               BIT12
> +#define SD_MMC_HC_64_ADDR_EN          BIT13
> +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> 
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
>    );
> 
>  /**
> +  Get the controller version information from the specified slot.
> +
> +  @param[in]  PciIo           The PCI IO protocol instance.
> +  @param[in]  Slot            The slot number of the SD card to send the
> command to.
> +  @param[out] Version         The buffer to store the version information.
> +
> +  @retval EFI_SUCCESS         The operation executes successfully.
> +  @retval Others              The operation fails.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcGetControllerVersion (
> +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN  UINT8                Slot,
> +  OUT UINT16               *Version
> +  );
> +
> +/**
>    Set all interrupt status bits in Normal and Error Interrupt Status Enable
>    register.
> 
> @@ -424,6 +470,7 @@ SdMmcHcStopClock (
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] ClockFreq      The max clock frequency to be set. The unit is KHz.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
>    IN UINT64                 ClockFreq,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
>    @param[in] PciIo          The PCI IO protocol instance.
>    @param[in] Slot           The slot number of the SD card to send the command
> to.
>    @param[in] BaseClkFreq    The base clock frequency of host controller in
> MHz.
> +  @param[in] ControllerVer  The version of host controller.
> 
>    @retval EFI_SUCCESS       The clock is supplied successfully.
>    @retval Others            The clock isn't supplied successfully.
> @@ -492,7 +541,8 @@ EFI_STATUS
>  SdMmcHcInitClockFreq (
>    IN EFI_PCI_IO_PROTOCOL    *PciIo,
>    IN UINT8                  Slot,
> -  IN UINT32                 BaseClkFreq
> +  IN UINT32                 BaseClkFreq,
> +  IN UINT16                 ControllerVer
>    );
> 
>  /**
> --
> 2.7.4
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2019-01-02  6:28 ` Wu, Hao A
@ 2019-01-02  6:36   ` Wu, Hao A
  2019-01-02 15:47     ` Ashish Singhal
  0 siblings, 1 reply; 7+ messages in thread
From: Wu, Hao A @ 2019-01-02  6:36 UTC (permalink / raw)
  To: Wu, Hao A, Ashish Singhal, edk2-devel@lists.01.org

Missed one comment for commit message:

"If V4 64 bit address mode is enabled in compatibility register"
->
"If V4 64 bit address mode is supported in capabilities register"


Best Regards,
Hao Wu


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Wu, Hao A
> Sent: Wednesday, January 02, 2019 2:29 PM
> To: Ashish Singhal; edk2-devel@lists.01.org
> Subject: Re: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add
> SDMMC HC v4 and above Support.
> 
> Hello,
> 
> I have 2 minor comments, please refer to those inline comments.
> Apart from that, the patch is good to me:
> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
> 
> If you agree those inline comments, I will directly modify the patch on my
> side and then push it into the repository.
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > Ashish Singhal
> > Sent: Wednesday, December 19, 2018 5:29 AM
> > To: edk2-devel@lists.01.org
> > Cc: Ashish Singhal
> > Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC
> > HC v4 and above Support.
> 
> Add the Bugzilla tracker information at the start of the commit log message:
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1359
> 
> >
> > Add SDMA, ADMA2 and 26b data length support.
> >
> > If V4 64 bit address mode is enabled in compatibility register,
> > program controller to enable V4 host mode and use appropriate
> > SDMA registers supporting 64 bit addresses.
> >
> > If V4 64 bit address mode is enabled in compatibility register,
> > program controller to enable V4 host mode and use appropriate
> > ADMA descriptors supporting 64 bit addresses.
> >
> > If host controller version is above V4.0, enable ADMA2 with 26b data
> > length support for better performance. HC 2 register is configured to
> > use 26 bit data lengths and ADMA2 descriptors are configured
> appropriately.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> > ---
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> > +++++++++++++++++----
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
> >  6 files changed, 363 insertions(+), 83 deletions(-)
> >  mode change 100755 => 100644
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > old mode 100755
> > new mode 100644
> > index 2d3fb68..0c5646f
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
> >    //
> >    // Convert the clock freq unit from MHz to KHz.
> >    //
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot]);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > index 68485c8..cdcdfa3 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > @@ -864,7 +864,7 @@ SdCardSetBusMode (
> >      return Status;
> >    }
> >
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot]);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1064,7 +1064,7 @@ SdCardIdentification (
> >          goto Error;
> >        }
> >
> > -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> > +      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> Private-
> > >ControllerVersion[Slot]);
> >
> >        gBS->Stall (1000);
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > index a87f8de..b5bc260 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate
> =
> > {
> >    {                                 // MaxCurrent
> >      0,
> >    },
> > -  0                                 // ControllerVersion
> > +  {
> > +    0                               // ControllerVersion
> > +  }
> >  };
> >
> >  SD_DEVICE_PATH    mSdDpTemplate = {
> > @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
> >    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> >      Private->Slot[Slot].Enable = TRUE;
> >
> > +    //
> > +    // Get SD/MMC Pci Host Controller Version
> > +    //
> > +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> > >ControllerVersion[Slot]);
> > +    if (EFI_ERROR (Status)) {
> > +      goto Done;
> 
> Like other error handling in the for loop:
> Instead of "goto Done;", change to "continue;".
> 
> 
> Thanks for the patience.
> 
> Best Regards,
> Hao Wu
> 
> > +    }
> > +
> >      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
> >      if (EFI_ERROR (Status)) {
> >        continue;
> > @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
> >        Private->BaseClkFreq[Slot]
> >        ));
> >
> > -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> > +    //
> > +    // If any of the slots does not support 64b system bus
> > +    // do not enable 64b DMA in the PCI layer.
> > +    //
> > +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> > +        Private->Capability[Slot].SysBus64V4 == 0) {
> > +      Support64BitDma = FALSE;
> > +    }
> >
> >      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> > >MaxCurrent[Slot]);
> >      if (EFI_ERROR (Status)) {
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > index 8c1a589..1bb701a 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > @@ -2,6 +2,7 @@
> >
> >    Provides some data structure definitions used by the SD/MMC host
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> >  This program and the accompanying materials
> >  are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -116,8 +117,7 @@ typedef struct {
> >    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
> >    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
> >    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> > -
> > -  UINT32                              ControllerVersion;
> > +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
> >
> >    //
> >    // Some controllers may require to override base clock frequency
> > @@ -150,7 +150,8 @@ typedef struct {
> >    BOOLEAN                             Started;
> >    UINT64                              Timeout;
> >
> > -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> > +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> > +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
> >    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
> >    VOID                                *AdmaMap;
> >    UINT32                              AdmaPages;
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > index ddf6dcf..6086720 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > @@ -4,6 +4,7 @@
> >
> >    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer
> use.
> >
> > +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> >    This program and the accompanying materials
> >    are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -45,7 +46,8 @@ DumpCapabilityReg (
> >    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> > "TRUE" : "FALSE"));
> > -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> > "TRUE" : "FALSE"));
> > +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V4 ? "TRUE" : "FALSE"));
> > +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V3 ? "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   SlotType          "));
> >    if (Capability->SlotType == 0x00) {
> > @@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
> >  }
> >
> >  /**
> > +  Get the controller version information from the specified slot.
> > +
> > +  @param[in]  PciIo           The PCI IO protocol instance.
> > +  @param[in]  Slot            The slot number of the SD card to send the
> > command to.
> > +  @param[out] Version         The buffer to store the version information.
> > +
> > +  @retval EFI_SUCCESS         The operation executes successfully.
> > +  @retval Others              The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> > +  IN     UINT8                Slot,
> > +  OUT    UINT16               *Version
> > +  )
> > +{
> > +  EFI_STATUS                Status;
> > +
> > +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> > sizeof (UINT16), Version);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  *Version &= 0xFF;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> >    Software reset the specified SD/MMC host controller and enable all
> > interrupts.
> >
> >    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> > instance.
> > @@ -722,6 +754,7 @@ SdMmcHcStopClock (
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] ClockFreq      The max clock frequency to be set. The unit is
> KHz.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> >    IN UINT64                 ClockFreq,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_STATUS                Status;
> >    UINT32                    SettingFreq;
> >    UINT32                    Divisor;
> >    UINT32                    Remainder;
> > -  UINT16                    ControllerVer;
> >    UINT16                    ClockCtrl;
> >
> >    //
> > @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> >
> >    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d
> > ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> >
> > -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> > sizeof (ControllerVer), &ControllerVer);
> > -  if (EFI_ERROR (Status)) {
> > -    return Status;
> > -  }
> >    //
> >    // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock
> > Control register.
> >    //
> > -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> > -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> > +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> > +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
> >      ASSERT (Divisor <= 0x3FF);
> >      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> > -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
> > +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> > +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
> >      //
> >      // Only the most significant bit can be used as divisor.
> >      //
> > @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
> >  }
> >
> >  /**
> > +  Configure V4 controller enhancements at initialization.
> > +
> > +  @param[in] PciIo          The PCI IO protocol instance.
> > +  @param[in] Slot           The slot number of the SD card to send the
> > command to.
> > +  @param[in] Capability     The capability of the slot.
> > +  @param[in] ControllerVer  The version of host controller.
> > +
> > +  @retval EFI_SUCCESS       The clock is supplied successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcInitV4Enhancements (
> > +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> > +  IN UINT8                  Slot,
> > +  IN SD_MMC_HC_SLOT_CAP     Capability,
> > +  IN UINT16                 ControllerVer
> > +  )
> > +{
> > +  EFI_STATUS                Status;
> > +  UINT16                    HostCtrl2;
> > +
> > +  //
> > +  // Check if controller version V4 or higher
> > +  //
> > +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > +    HostCtrl2 = SD_MMC_HC_V4_EN;
> > +    //
> > +    // Check if V4 64bit support is available
> > +    //
> > +    if (Capability.SysBus64V4 != 0) {
> > +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> > +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> > +    }
> > +    //
> > +    // Check if controller version V4.10 or higher
> > +    //
> > +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> > +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> > +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> > support\n"));
> > +    }
> > +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2,
> sizeof
> > (HostCtrl2), &HostCtrl2);
> > +    if (EFI_ERROR (Status)) {
> > +      return Status;
> > +    }
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> >    Supply SD/MMC card with lowest clock frequency at initialization.
> >
> >    @param[in] PciIo          The PCI IO protocol instance.
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -948,7 +1029,8 @@ EFI_STATUS
> >  SdMmcHcInitClockFreq (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_STATUS                Status;
> > @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
> >    // Supply 400KHz clock frequency at initialization phase.
> >    //
> >    InitFreq = 400;
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> > ControllerVer);
> >    return Status;
> >  }
> >
> > @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
> >    PciIo = Private->PciIo;
> >    Capability = Private->Capability[Slot];
> >
> > -  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> > +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private-
> > >ControllerVersion[Slot]);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> > Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
> >  /**
> >    Build ADMA descriptor table for transfer.
> >
> > -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> > +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> >
> >    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The ADMA descriptor table is created
> successfully.
> >    @retval Others            The ADMA descriptor table isn't created
> successfully.
> > @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
> >  **/
> >  EFI_STATUS
> >  BuildAdmaDescTable (
> > -  IN SD_MMC_HC_TRB          *Trb
> > +  IN SD_MMC_HC_TRB          *Trb,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_PHYSICAL_ADDRESS      Data;
> > @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
> >    UINT64                    Entries;
> >    UINT32                    Index;
> >    UINT64                    Remaining;
> > -  UINT32                    Address;
> > +  UINT64                    Address;
> >    UINTN                     TableSize;
> >    EFI_PCI_IO_PROTOCOL       *PciIo;
> >    EFI_STATUS                Status;
> >    UINTN                     Bytes;
> > +  BOOLEAN                   AddressingMode64;
> > +  BOOLEAN                   DataLength26;
> > +  UINT32                    AdmaMaxDataPerLine;
> > +  UINT32                    DescSize;
> > +  VOID                      *AdmaDesc;
> > +
> > +  AddressingMode64   = FALSE;
> > +  DataLength26       = FALSE;
> > +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> > +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> > +  AdmaDesc           = NULL;
> >
> >    Data    = Trb->DataPhy;
> >    DataLen = Trb->DataLen;
> >    PciIo   = Trb->Private->PciIo;
> > +
> >    //
> > -  // Only support 32bit ADMA Descriptor Table
> > +  // Detect whether 64bit addressing is supported.
> >    //
> > -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
> > +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > +    if (!EFI_ERROR (Status)) {
> > +      AddressingMode64 = TRUE;
> > +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> > +    }
> > +  }
> > +  //
> > +  // Check for valid ranges in 32bit ADMA Descriptor Table
> > +  //
> > +  if (!AddressingMode64 &&
> > +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
> >      return EFI_INVALID_PARAMETER;
> >    }
> >    //
> > -  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set
> to
> > 0)
> > -  // for 32-bit address descriptor table.
> > +  // Check address field alignment
> >    //
> > -  if ((Data & (BIT0 | BIT1)) != 0) {
> > -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not
> > aligned to 4 bytes boundary!\n", Data));
> > +  if (AddressingMode64) {
> > +    //
> > +    // Address field shall be set on 64-bit boundary (Lower 3-bit is always
> set
> > to 0)
> > +    //
> > +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> > +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> > not aligned to 8 bytes boundary!\n", Data));
> > +    }
> > +  } else {
> > +    //
> > +    // Address field shall be set on 32-bit boundary (Lower 2-bit is always
> set
> > to 0)
> > +    //
> > +    if ((Data & (BIT0 | BIT1)) != 0) {
> > +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> > not aligned to 4 bytes boundary!\n", Data));
> > +    }
> > +  }
> > +  //
> > +  // Detect whether 26bit data length is supported.
> > +  //
> > +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> > SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> > +  if (!EFI_ERROR (Status)) {
> > +    DataLength26 = TRUE;
> > +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
> >    }
> >
> > -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> > ADMA_MAX_DATA_PER_LINE);
> > -  TableSize = (UINTN)MultU64x32 (Entries, sizeof
> > (SD_MMC_HC_ADMA_DESC_LINE));
> > +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> > AdmaMaxDataPerLine);
> > +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
> >    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
> >    Status = PciIo->AllocateBuffer (
> >                      PciIo,
> >                      AllocateAnyPages,
> >                      EfiBootServicesData,
> >                      EFI_SIZE_TO_PAGES (TableSize),
> > -                    (VOID **)&Trb->AdmaDesc,
> > +                    (VOID **)&AdmaDesc,
> >                      0
> >                      );
> >    if (EFI_ERROR (Status)) {
> >      return EFI_OUT_OF_RESOURCES;
> >    }
> > -  ZeroMem (Trb->AdmaDesc, TableSize);
> > +  ZeroMem (AdmaDesc, TableSize);
> >    Bytes  = TableSize;
> >    Status = PciIo->Map (
> >                      PciIo,
> >                      EfiPciIoOperationBusMasterCommonBuffer,
> > -                    Trb->AdmaDesc,
> > +                    AdmaDesc,
> >                      &Bytes,
> >                      &Trb->AdmaDescPhy,
> >                      &Trb->AdmaMap
> > @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
> >      PciIo->FreeBuffer (
> >               PciIo,
> >               EFI_SIZE_TO_PAGES (TableSize),
> > -             Trb->AdmaDesc
> > +             AdmaDesc
> >               );
> >      return EFI_OUT_OF_RESOURCES;
> >    }
> >
> > -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> > +  if ((!AddressingMode64) &&
> > +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> >      //
> >      // The ADMA doesn't support 64bit addressing.
> >      //
> > @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
> >      PciIo->FreeBuffer (
> >        PciIo,
> >        EFI_SIZE_TO_PAGES (TableSize),
> > -      Trb->AdmaDesc
> > +      AdmaDesc
> >      );
> >      return EFI_DEVICE_ERROR;
> >    }
> >
> >    Remaining = DataLen;
> > -  Address   = (UINT32)Data;
> > +  Address   = Data;
> > +  if (!AddressingMode64) {
> > +    Trb->Adma32Desc = AdmaDesc;
> > +    Trb->Adma64Desc = NULL;
> > +  } else {
> > +    Trb->Adma64Desc = AdmaDesc;
> > +    Trb->Adma32Desc = NULL;
> > +  }
> >    for (Index = 0; Index < Entries; Index++) {
> > -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> > -      Trb->AdmaDesc[Index].Valid = 1;
> > -      Trb->AdmaDesc[Index].Act   = 2;
> > -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> > -      Trb->AdmaDesc[Index].Address = Address;
> > -      break;
> > +    if (!AddressingMode64) {
> > +      if (Remaining <= AdmaMaxDataPerLine) {
> > +        Trb->Adma32Desc[Index].Valid = 1;
> > +        Trb->Adma32Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> > +        }
> > +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> > MAX_UINT16);
> > +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > +        break;
> > +      } else {
> > +        Trb->Adma32Desc[Index].Valid = 1;
> > +        Trb->Adma32Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma32Desc[Index].UpperLength  = 0;
> > +        }
> > +        Trb->Adma32Desc[Index].LowerLength  = 0;
> > +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > +      }
> >      } else {
> > -      Trb->AdmaDesc[Index].Valid = 1;
> > -      Trb->AdmaDesc[Index].Act   = 2;
> > -      Trb->AdmaDesc[Index].Length  = 0;
> > -      Trb->AdmaDesc[Index].Address = Address;
> > +      if (Remaining <= AdmaMaxDataPerLine) {
> > +        Trb->Adma64Desc[Index].Valid = 1;
> > +        Trb->Adma64Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> > +        }
> > +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> > MAX_UINT16);
> > +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > +        break;
> > +      } else {
> > +        Trb->Adma64Desc[Index].Valid = 1;
> > +        Trb->Adma64Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma64Desc[Index].UpperLength  = 0;
> > +        }
> > +        Trb->Adma64Desc[Index].LowerLength  = 0;
> > +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > +      }
> >      }
> >
> > -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> > -    Address   += ADMA_MAX_DATA_PER_LINE;
> > +    Remaining -= AdmaMaxDataPerLine;
> > +    Address   += AdmaMaxDataPerLine;
> >    }
> >
> >    //
> >    // Set the last descriptor line as end of descriptor table
> >    //
> > -  Trb->AdmaDesc[Index].End = 1;
> > +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> > >Adma32Desc[Index].End = 1);
> >    return EFI_SUCCESS;
> >  }
> >
> > @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
> >        Trb->Mode = SdMmcNoData;
> >      } else if (Private->Capability[Slot].Adma2 != 0) {
> >        Trb->Mode = SdMmcAdmaMode;
> > -      Status = BuildAdmaDescTable (Trb);
> > +      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
> >        if (EFI_ERROR (Status)) {
> >          PciIo->Unmap (PciIo, Trb->DataMap);
> >          goto Error;
> > @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
> >        Trb->AdmaMap
> >      );
> >    }
> > -  if (Trb->AdmaDesc != NULL) {
> > +  if (Trb->Adma32Desc != NULL) {
> > +    PciIo->FreeBuffer (
> > +      PciIo,
> > +      Trb->AdmaPages,
> > +      Trb->Adma32Desc
> > +    );
> > +  }
> > +  if (Trb->Adma64Desc != NULL) {
> >      PciIo->FreeBuffer (
> >        PciIo,
> >        Trb->AdmaPages,
> > -      Trb->AdmaDesc
> > +      Trb->Adma64Desc
> >      );
> >    }
> >    if (Trb->DataMap != NULL) {
> > @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
> >    UINT16                              Cmd;
> >    UINT16                              IntStatus;
> >    UINT32                              Argument;
> > -  UINT16                              BlkCount;
> > +  UINT32                              BlkCount;
> >    UINT16                              BlkSize;
> >    UINT16                              TransMode;
> >    UINT8                               HostCtrl1;
> > -  UINT32                              SdmaAddr;
> > +  UINT64                              SdmaAddr;
> >    UINT64                              AdmaAddr;
> > +  BOOLEAN                             AddressingMode64;
> > +
> > +  AddressingMode64 = FALSE;
> >
> >    Packet = Trb->Packet;
> >    PciIo  = Trb->Private->PciIo;
> > @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> >
> >    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> >
> > +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> > {
> > +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > +    if (!EFI_ERROR (Status)) {
> > +      AddressingMode64 = TRUE;
> > +    }
> > +  }
> > +
> >    if (Trb->Mode == SdMmcSdmaMode) {
> > -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> > +    if ((!AddressingMode64) &&
> > +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
> >        return EFI_INVALID_PARAMETER;
> >      }
> >
> > -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> > -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (SdmaAddr), &SdmaAddr);
> > +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> > +
> > +    if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> > +    } else {
> > +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> > +    }
> > +
> >      if (EFI_ERROR (Status)) {
> >        return Status;
> >      }
> > @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
> >      //
> >      // Calcuate Block Count.
> >      //
> > -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> > +    BlkCount = (Trb->DataLen / Trb->BlockSize);
> > +  }
> > +  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> > {
> > +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (UINT32), &BlkCount);
> > +  } else {
> > +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (UINT16), &BlkCount);
> >    }
> > -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (BlkCount), &BlkCount);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
> >    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
> >    UINT16                              IntStatus;
> >    UINT32                              Response[4];
> > -  UINT32                              SdmaAddr;
> > +  UINT64                              SdmaAddr;
> >    UINT8                               Index;
> >    UINT8                               SwReset;
> >    UINT32                              PioLength;
> > @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
> >      //
> >      // Update SDMA Address register.
> >      //
> > -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> > >DataPhy, SD_MMC_SDMA_BOUNDARY);
> > -    Status   = SdMmcHcRwMmio (
> > +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> > SD_MMC_SDMA_BOUNDARY);
> > +
> > +    if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > +      Status = SdMmcHcRwMmio (
> > +                 Private->PciIo,
> > +                 Trb->Slot,
> > +                 SD_MMC_HC_ADMA_SYS_ADDR,
> > +                 FALSE,
> > +                 sizeof (UINT64),
> > +                 &SdmaAddr
> > +                 );
> > +    } else {
> > +      Status = SdMmcHcRwMmio (
> >                   Private->PciIo,
> >                   Trb->Slot,
> >                   SD_MMC_HC_SDMA_ADDR,
> > @@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
> >                   sizeof (UINT32),
> >                   &SdmaAddr
> >                   );
> > +    }
> > +
> >      if (EFI_ERROR (Status)) {
> >        goto Done;
> >      }
> > -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> > +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
> >    }
> >
> >    if ((Packet->SdMmcCmdBlk->CommandType !=
> SdMmcCommandTypeAdtc)
> > &&
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > index dd45cbd..d157f2c 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > @@ -2,6 +2,7 @@
> >
> >    Provides some data structure definitions used by the SD/MMC host
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> >  This program and the accompanying materials
> >  are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -91,18 +92,38 @@ typedef enum {
> >  //
> >  // The maximum data length of each descriptor line
> >  //
> > -#define ADMA_MAX_DATA_PER_LINE     0x10000
> > +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> > +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
> >
> > +//
> > +// ADMA descriptor for 32b addressing.
> > +//
> >  typedef struct {
> >    UINT32 Valid:1;
> >    UINT32 End:1;
> >    UINT32 Int:1;
> >    UINT32 Reserved:1;
> >    UINT32 Act:2;
> > -  UINT32 Reserved1:10;
> > -  UINT32 Length:16;
> > +  UINT32 UpperLength:10;
> > +  UINT32 LowerLength:16;
> >    UINT32 Address;
> > -} SD_MMC_HC_ADMA_DESC_LINE;
> > +} SD_MMC_HC_ADMA_32_DESC_LINE;
> > +
> > +//
> > +// ADMA descriptor for 64b addressing.
> > +//
> > +typedef struct {
> > +  UINT32 Valid:1;
> > +  UINT32 End:1;
> > +  UINT32 Int:1;
> > +  UINT32 Reserved:1;
> > +  UINT32 Act:2;
> > +  UINT32 UpperLength:10;
> > +  UINT32 LowerLength:16;
> > +  UINT32 LowerAddress;
> > +  UINT32 UpperAddress;
> > +  UINT32 Reserved1;
> > +} SD_MMC_HC_ADMA_64_DESC_LINE;
> >
> >  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
> >  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> > @@ -129,36 +150,43 @@ typedef struct {
> >    UINT32   Voltage33:1;       // bit 24
> >    UINT32   Voltage30:1;       // bit 25
> >    UINT32   Voltage18:1;       // bit 26
> > -  UINT32   Reserved3:1;       // bit 27
> > -  UINT32   SysBus64:1;        // bit 28
> > +  UINT32   SysBus64V4:1;      // bit 27
> > +  UINT32   SysBus64V3:1;      // bit 28
> >    UINT32   AsyncInt:1;        // bit 29
> >    UINT32   SlotType:2;        // bit 30:31
> >    UINT32   Sdr50:1;           // bit 32
> >    UINT32   Sdr104:1;          // bit 33
> >    UINT32   Ddr50:1;           // bit 34
> > -  UINT32   Reserved4:1;       // bit 35
> > +  UINT32   Reserved3:1;       // bit 35
> >    UINT32   DriverTypeA:1;     // bit 36
> >    UINT32   DriverTypeC:1;     // bit 37
> >    UINT32   DriverTypeD:1;     // bit 38
> >    UINT32   DriverType4:1;     // bit 39
> >    UINT32   TimerCount:4;      // bit 40:43
> > -  UINT32   Reserved5:1;       // bit 44
> > +  UINT32   Reserved4:1;       // bit 44
> >    UINT32   TuningSDR50:1;     // bit 45
> >    UINT32   RetuningMod:2;     // bit 46:47
> >    UINT32   ClkMultiplier:8;   // bit 48:55
> > -  UINT32   Reserved6:7;       // bit 56:62
> > +  UINT32   Reserved5:7;       // bit 56:62
> >    UINT32   Hs400:1;           // bit 63
> >  } SD_MMC_HC_SLOT_CAP;
> >
> >  //
> >  // SD Host controller version
> >  //
> > -#define SD_MMC_HC_CTRL_VER_100      0x00
> > -#define SD_MMC_HC_CTRL_VER_200      0x01
> > -#define SD_MMC_HC_CTRL_VER_300      0x02
> > -#define SD_MMC_HC_CTRL_VER_400      0x03
> > -#define SD_MMC_HC_CTRL_VER_410      0x04
> > -#define SD_MMC_HC_CTRL_VER_420      0x05
> > +#define SD_MMC_HC_CTRL_VER_100        0x00
> > +#define SD_MMC_HC_CTRL_VER_200        0x01
> > +#define SD_MMC_HC_CTRL_VER_300        0x02
> > +#define SD_MMC_HC_CTRL_VER_400        0x03
> > +#define SD_MMC_HC_CTRL_VER_410        0x04
> > +#define SD_MMC_HC_CTRL_VER_420        0x05
> > +
> > +//
> > +// SD Host controller V4 enhancements
> > +//
> > +#define SD_MMC_HC_V4_EN               BIT12
> > +#define SD_MMC_HC_64_ADDR_EN          BIT13
> > +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> >
> >  /**
> >    Dump the content of SD/MMC host controller's Capability Register.
> > @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
> >    );
> >
> >  /**
> > +  Get the controller version information from the specified slot.
> > +
> > +  @param[in]  PciIo           The PCI IO protocol instance.
> > +  @param[in]  Slot            The slot number of the SD card to send the
> > command to.
> > +  @param[out] Version         The buffer to store the version information.
> > +
> > +  @retval EFI_SUCCESS         The operation executes successfully.
> > +  @retval Others              The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> > +  IN  UINT8                Slot,
> > +  OUT UINT16               *Version
> > +  );
> > +
> > +/**
> >    Set all interrupt status bits in Normal and Error Interrupt Status Enable
> >    register.
> >
> > @@ -424,6 +470,7 @@ SdMmcHcStopClock (
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] ClockFreq      The max clock frequency to be set. The unit is
> KHz.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> >    IN UINT64                 ClockFreq,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    );
> >
> >  /**
> > @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
> >    @param[in] PciIo          The PCI IO protocol instance.
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -492,7 +541,8 @@ EFI_STATUS
> >  SdMmcHcInitClockFreq (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    );
> >
> >  /**
> > --
> > 2.7.4
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
  2019-01-02  6:36   ` Wu, Hao A
@ 2019-01-02 15:47     ` Ashish Singhal
  0 siblings, 0 replies; 7+ messages in thread
From: Ashish Singhal @ 2019-01-02 15:47 UTC (permalink / raw)
  To: Wu, Hao A, edk2-devel@lists.01.org

Hello Hao,

I have submitted patch v8 which incorporates all the changes.

Thanks
Ashish


-----Original Message-----
From: Wu, Hao A <hao.a.wu@intel.com> 
Sent: Tuesday, January 1, 2019 11:37 PM
To: Wu, Hao A <hao.a.wu@intel.com>; Ashish Singhal <ashishsingha@nvidia.com>; edk2-devel@lists.01.org
Subject: RE: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.

Missed one comment for commit message:

"If V4 64 bit address mode is enabled in compatibility register"
->
"If V4 64 bit address mode is supported in capabilities register"


Best Regards,
Hao Wu


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Wu, Hao A
> Sent: Wednesday, January 02, 2019 2:29 PM
> To: Ashish Singhal; edk2-devel@lists.01.org
> Subject: Re: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC 
> HC v4 and above Support.
> 
> Hello,
> 
> I have 2 minor comments, please refer to those inline comments.
> Apart from that, the patch is good to me:
> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
> 
> If you agree those inline comments, I will directly modify the patch 
> on my side and then push it into the repository.
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
> > Of Ashish Singhal
> > Sent: Wednesday, December 19, 2018 5:29 AM
> > To: edk2-devel@lists.01.org
> > Cc: Ashish Singhal
> > Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC 
> > v4 and above Support.
> 
> Add the Bugzilla tracker information at the start of the commit log message:
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1359
> 
> >
> > Add SDMA, ADMA2 and 26b data length support.
> >
> > If V4 64 bit address mode is enabled in compatibility register, 
> > program controller to enable V4 host mode and use appropriate SDMA 
> > registers supporting 64 bit addresses.
> >
> > If V4 64 bit address mode is enabled in compatibility register, 
> > program controller to enable V4 host mode and use appropriate ADMA 
> > descriptors supporting 64 bit addresses.
> >
> > If host controller version is above V4.0, enable ADMA2 with 26b data 
> > length support for better performance. HC 2 register is configured 
> > to use 26 bit data lengths and ADMA2 descriptors are configured
> appropriately.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> > ---
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c    |   2 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c      |   4 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  21 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   7 +-
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 328
> > +++++++++++++++++----
> >  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  84 ++++--
> >  6 files changed, 363 insertions(+), 83 deletions(-)  mode change 
> > 100755 => 100644 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > old mode 100755
> > new mode 100644
> > index 2d3fb68..0c5646f
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
> >    //
> >    // Convert the clock freq unit from MHz to KHz.
> >    //
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> > Private-
> > >BaseClkFreq[Slot]);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> > + Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > index 68485c8..cdcdfa3 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > @@ -864,7 +864,7 @@ SdCardSetBusMode (
> >      return Status;
> >    }
> >
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> > Private-
> > >BaseClkFreq[Slot]);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, 
> > + Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1064,7 +1064,7 @@ SdCardIdentification (
> >          goto Error;
> >        }
> >
> > -      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> > +      SdMmcHcInitClockFreq (PciIo, Slot, 
> > + Private->BaseClkFreq[Slot],
> Private-
> > >ControllerVersion[Slot]);
> >
> >        gBS->Stall (1000);
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > index a87f8de..b5bc260 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate
> =
> > {
> >    {                                 // MaxCurrent
> >      0,
> >    },
> > -  0                                 // ControllerVersion
> > +  {
> > +    0                               // ControllerVersion
> > +  }
> >  };
> >
> >  SD_DEVICE_PATH    mSdDpTemplate = {
> > @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
> >    for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> >      Private->Slot[Slot].Enable = TRUE;
> >
> > +    //
> > +    // Get SD/MMC Pci Host Controller Version
> > +    //
> > +    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> > >ControllerVersion[Slot]);
> > +    if (EFI_ERROR (Status)) {
> > +      goto Done;
> 
> Like other error handling in the for loop:
> Instead of "goto Done;", change to "continue;".
> 
> 
> Thanks for the patience.
> 
> Best Regards,
> Hao Wu
> 
> > +    }
> > +
> >      Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
> >      if (EFI_ERROR (Status)) {
> >        continue;
> > @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
> >        Private->BaseClkFreq[Slot]
> >        ));
> >
> > -    Support64BitDma &= Private->Capability[Slot].SysBus64;
> > +    //
> > +    // If any of the slots does not support 64b system bus
> > +    // do not enable 64b DMA in the PCI layer.
> > +    //
> > +    if (Private->Capability[Slot].SysBus64V3 == 0 &&
> > +        Private->Capability[Slot].SysBus64V4 == 0) {
> > +      Support64BitDma = FALSE;
> > +    }
> >
> >      Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> > >MaxCurrent[Slot]);
> >      if (EFI_ERROR (Status)) {
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > index 8c1a589..1bb701a 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > @@ -2,6 +2,7 @@
> >
> >    Provides some data structure definitions used by the SD/MMC host 
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>  
> > This program and the accompanying materials  are licensed and made 
> > available under the terms and conditions of the
> BSD
> > License
> > @@ -116,8 +117,7 @@ typedef struct {
> >    SD_MMC_HC_SLOT                      Slot[SD_MMC_HC_MAX_SLOT];
> >    SD_MMC_HC_SLOT_CAP                  Capability[SD_MMC_HC_MAX_SLOT];
> >    UINT64                              MaxCurrent[SD_MMC_HC_MAX_SLOT];
> > -
> > -  UINT32                              ControllerVersion;
> > +  UINT16                              ControllerVersion[SD_MMC_HC_MAX_SLOT];
> >
> >    //
> >    // Some controllers may require to override base clock frequency 
> > @@ -150,7 +150,8 @@ typedef struct {
> >    BOOLEAN                             Started;
> >    UINT64                              Timeout;
> >
> > -  SD_MMC_HC_ADMA_DESC_LINE            *AdmaDesc;
> > +  SD_MMC_HC_ADMA_32_DESC_LINE         *Adma32Desc;
> > +  SD_MMC_HC_ADMA_64_DESC_LINE         *Adma64Desc;
> >    EFI_PHYSICAL_ADDRESS                AdmaDescPhy;
> >    VOID                                *AdmaMap;
> >    UINT32                              AdmaPages;
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > index ddf6dcf..6086720 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > @@ -4,6 +4,7 @@
> >
> >    It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer
> use.
> >
> > +  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >    Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> >    This program and the accompanying materials
> >    are licensed and made available under the terms and conditions of 
> > the
> BSD
> > License
> > @@ -45,7 +46,8 @@ DumpCapabilityReg (
> >    DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ?
> > "TRUE" : "FALSE"));
> > -  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ?
> > "TRUE" : "FALSE"));
> > +  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V4 ? "TRUE" : "FALSE"));
> > +  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V3 ? "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ?
> > "TRUE" : "FALSE"));
> >    DEBUG ((DEBUG_INFO, "   SlotType          "));
> >    if (Capability->SlotType == 0x00) { @@ -417,6 +419,36 @@ 
> > SdMmcHcWaitMmioSet (  }
> >
> >  /**
> > +  Get the controller version information from the specified slot.
> > +
> > +  @param[in]  PciIo           The PCI IO protocol instance.
> > +  @param[in]  Slot            The slot number of the SD card to send the
> > command to.
> > +  @param[out] Version         The buffer to store the version information.
> > +
> > +  @retval EFI_SUCCESS         The operation executes successfully.
> > +  @retval Others              The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > +  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
> > +  IN     UINT8                Slot,
> > +  OUT    UINT16               *Version
> > +  )
> > +{
> > +  EFI_STATUS                Status;
> > +
> > +  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> > sizeof (UINT16), Version);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  *Version &= 0xFF;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> >    Software reset the specified SD/MMC host controller and enable 
> > all interrupts.
> >
> >    @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA
> > instance.
> > @@ -722,6 +754,7 @@ SdMmcHcStopClock (
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] ClockFreq      The max clock frequency to be set. The unit is
> KHz.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> >    IN UINT64                 ClockFreq,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_STATUS                Status;
> >    UINT32                    SettingFreq;
> >    UINT32                    Divisor;
> >    UINT32                    Remainder;
> > -  UINT16                    ControllerVer;
> >    UINT16                    ClockCtrl;
> >
> >    //
> > @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> >
> >    DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq 
> > %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> >
> > -  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, 
> > sizeof (ControllerVer), &ControllerVer);
> > -  if (EFI_ERROR (Status)) {
> > -    return Status;
> > -  }
> >    //
> >    // Set SDCLK Frequency Select and Internal Clock Enable fields in 
> > Clock Control register.
> >    //
> > -  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> > -      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> > +  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> > +      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
> >      ASSERT (Divisor <= 0x3FF);
> >      ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> > -  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 
> > 0xFF) == 1)) {
> > +  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> > +             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
> >      //
> >      // Only the most significant bit can be used as divisor.
> >      //
> > @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (  }
> >
> >  /**
> > +  Configure V4 controller enhancements at initialization.
> > +
> > +  @param[in] PciIo          The PCI IO protocol instance.
> > +  @param[in] Slot           The slot number of the SD card to send the
> > command to.
> > +  @param[in] Capability     The capability of the slot.
> > +  @param[in] ControllerVer  The version of host controller.
> > +
> > +  @retval EFI_SUCCESS       The clock is supplied successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcInitV4Enhancements (
> > +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> > +  IN UINT8                  Slot,
> > +  IN SD_MMC_HC_SLOT_CAP     Capability,
> > +  IN UINT16                 ControllerVer
> > +  )
> > +{
> > +  EFI_STATUS                Status;
> > +  UINT16                    HostCtrl2;
> > +
> > +  //
> > +  // Check if controller version V4 or higher  //  if 
> > + (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > +    HostCtrl2 = SD_MMC_HC_V4_EN;
> > +    //
> > +    // Check if V4 64bit support is available
> > +    //
> > +    if (Capability.SysBus64V4 != 0) {
> > +      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> > +      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> > +    }
> > +    //
> > +    // Check if controller version V4.10 or higher
> > +    //
> > +    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> > +      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> > +      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> > support\n"));
> > +    }
> > +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2,
> sizeof
> > (HostCtrl2), &HostCtrl2);
> > +    if (EFI_ERROR (Status)) {
> > +      return Status;
> > +    }
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> >    Supply SD/MMC card with lowest clock frequency at initialization.
> >
> >    @param[in] PciIo          The PCI IO protocol instance.
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -948,7 +1029,8 @@ EFI_STATUS
> >  SdMmcHcInitClockFreq (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_STATUS                Status;
> > @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
> >    // Supply 400KHz clock frequency at initialization phase.
> >    //
> >    InitFreq = 400;
> > -  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> > +  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> > ControllerVer);
> >    return Status;
> >  }
> >
> > @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
> >    PciIo = Private->PciIo;
> >    Capability = Private->Capability[Slot];
> >
> > -  Status = SdMmcHcInitClockFreq (PciIo, Slot, 
> > Private->BaseClkFreq[Slot]);
> > +  Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, 
> > + Private-
> > >ControllerVersion[Slot]);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = SdMmcHcInitClockFreq (PciIo, Slot, 
> > + Private->BaseClkFreq[Slot],
> > Private->ControllerVersion[Slot]);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
> >  /**
> >    Build ADMA descriptor table for transfer.
> >
> > -  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> > +  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> >
> >    @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The ADMA descriptor table is created
> successfully.
> >    @retval Others            The ADMA descriptor table isn't created
> successfully.
> > @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (  **/  EFI_STATUS  
> > BuildAdmaDescTable (
> > -  IN SD_MMC_HC_TRB          *Trb
> > +  IN SD_MMC_HC_TRB          *Trb,
> > +  IN UINT16                 ControllerVer
> >    )
> >  {
> >    EFI_PHYSICAL_ADDRESS      Data;
> > @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
> >    UINT64                    Entries;
> >    UINT32                    Index;
> >    UINT64                    Remaining;
> > -  UINT32                    Address;
> > +  UINT64                    Address;
> >    UINTN                     TableSize;
> >    EFI_PCI_IO_PROTOCOL       *PciIo;
> >    EFI_STATUS                Status;
> >    UINTN                     Bytes;
> > +  BOOLEAN                   AddressingMode64;
> > +  BOOLEAN                   DataLength26;
> > +  UINT32                    AdmaMaxDataPerLine;
> > +  UINT32                    DescSize;
> > +  VOID                      *AdmaDesc;
> > +
> > +  AddressingMode64   = FALSE;
> > +  DataLength26       = FALSE;
> > +  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> > +  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> > +  AdmaDesc           = NULL;
> >
> >    Data    = Trb->DataPhy;
> >    DataLen = Trb->DataLen;
> >    PciIo   = Trb->Private->PciIo;
> > +
> >    //
> > -  // Only support 32bit ADMA Descriptor Table
> > +  // Detect whether 64bit addressing is supported.
> >    //
> > -  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 
> > 0x100000000ul)) {
> > +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                                 
> > + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > +    if (!EFI_ERROR (Status)) {
> > +      AddressingMode64 = TRUE;
> > +      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> > +    }
> > +  }
> > +  //
> > +  // Check for valid ranges in 32bit ADMA Descriptor Table  //  if 
> > + (!AddressingMode64 &&
> > +      ((Data >= 0x100000000ul) || ((Data + DataLen) > 
> > + 0x100000000ul))) {
> >      return EFI_INVALID_PARAMETER;
> >    }
> >    //
> > -  // Address field shall be set on 32-bit boundary (Lower 2-bit is 
> > always set
> to
> > 0)
> > -  // for 32-bit address descriptor table.
> > +  // Check address field alignment
> >    //
> > -  if ((Data & (BIT0 | BIT1)) != 0) {
> > -    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not
> > aligned to 4 bytes boundary!\n", Data));
> > +  if (AddressingMode64) {
> > +    //
> > +    // Address field shall be set on 64-bit boundary (Lower 3-bit 
> > + is always
> set
> > to 0)
> > +    //
> > +    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> > +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc 
> > + is
> > not aligned to 8 bytes boundary!\n", Data));
> > +    }
> > +  } else {
> > +    //
> > +    // Address field shall be set on 32-bit boundary (Lower 2-bit 
> > + is always
> set
> > to 0)
> > +    //
> > +    if ((Data & (BIT0 | BIT1)) != 0) {
> > +      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc 
> > + is
> > not aligned to 4 bytes boundary!\n", Data));
> > +    }
> > +  }
> > +  //
> > +  // Detect whether 26bit data length is supported.
> > +  //
> > +  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                               SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> > SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> > +  if (!EFI_ERROR (Status)) {
> > +    DataLength26 = TRUE;
> > +    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
> >    }
> >
> > -  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> > ADMA_MAX_DATA_PER_LINE);
> > -  TableSize = (UINTN)MultU64x32 (Entries, sizeof 
> > (SD_MMC_HC_ADMA_DESC_LINE));
> > +  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> > AdmaMaxDataPerLine);
> > +  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
> >    Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
> >    Status = PciIo->AllocateBuffer (
> >                      PciIo,
> >                      AllocateAnyPages,
> >                      EfiBootServicesData,
> >                      EFI_SIZE_TO_PAGES (TableSize),
> > -                    (VOID **)&Trb->AdmaDesc,
> > +                    (VOID **)&AdmaDesc,
> >                      0
> >                      );
> >    if (EFI_ERROR (Status)) {
> >      return EFI_OUT_OF_RESOURCES;
> >    }
> > -  ZeroMem (Trb->AdmaDesc, TableSize);
> > +  ZeroMem (AdmaDesc, TableSize);
> >    Bytes  = TableSize;
> >    Status = PciIo->Map (
> >                      PciIo,
> >                      EfiPciIoOperationBusMasterCommonBuffer,
> > -                    Trb->AdmaDesc,
> > +                    AdmaDesc,
> >                      &Bytes,
> >                      &Trb->AdmaDescPhy,
> >                      &Trb->AdmaMap
> > @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
> >      PciIo->FreeBuffer (
> >               PciIo,
> >               EFI_SIZE_TO_PAGES (TableSize),
> > -             Trb->AdmaDesc
> > +             AdmaDesc
> >               );
> >      return EFI_OUT_OF_RESOURCES;
> >    }
> >
> > -  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> > +  if ((!AddressingMode64) &&
> > +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> >      //
> >      // The ADMA doesn't support 64bit addressing.
> >      //
> > @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
> >      PciIo->FreeBuffer (
> >        PciIo,
> >        EFI_SIZE_TO_PAGES (TableSize),
> > -      Trb->AdmaDesc
> > +      AdmaDesc
> >      );
> >      return EFI_DEVICE_ERROR;
> >    }
> >
> >    Remaining = DataLen;
> > -  Address   = (UINT32)Data;
> > +  Address   = Data;
> > +  if (!AddressingMode64) {
> > +    Trb->Adma32Desc = AdmaDesc;
> > +    Trb->Adma64Desc = NULL;
> > +  } else {
> > +    Trb->Adma64Desc = AdmaDesc;
> > +    Trb->Adma32Desc = NULL;
> > +  }
> >    for (Index = 0; Index < Entries; Index++) {
> > -    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> > -      Trb->AdmaDesc[Index].Valid = 1;
> > -      Trb->AdmaDesc[Index].Act   = 2;
> > -      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
> > -      Trb->AdmaDesc[Index].Address = Address;
> > -      break;
> > +    if (!AddressingMode64) {
> > +      if (Remaining <= AdmaMaxDataPerLine) {
> > +        Trb->Adma32Desc[Index].Valid = 1;
> > +        Trb->Adma32Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> > +        }
> > +        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> > MAX_UINT16);
> > +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > +        break;
> > +      } else {
> > +        Trb->Adma32Desc[Index].Valid = 1;
> > +        Trb->Adma32Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma32Desc[Index].UpperLength  = 0;
> > +        }
> > +        Trb->Adma32Desc[Index].LowerLength  = 0;
> > +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > +      }
> >      } else {
> > -      Trb->AdmaDesc[Index].Valid = 1;
> > -      Trb->AdmaDesc[Index].Act   = 2;
> > -      Trb->AdmaDesc[Index].Length  = 0;
> > -      Trb->AdmaDesc[Index].Address = Address;
> > +      if (Remaining <= AdmaMaxDataPerLine) {
> > +        Trb->Adma64Desc[Index].Valid = 1;
> > +        Trb->Adma64Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma64Desc[Index].UpperLength  = (UINT16)(Remaining >> 16);
> > +        }
> > +        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining &
> > MAX_UINT16);
> > +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > +        break;
> > +      } else {
> > +        Trb->Adma64Desc[Index].Valid = 1;
> > +        Trb->Adma64Desc[Index].Act   = 2;
> > +        if (DataLength26) {
> > +          Trb->Adma64Desc[Index].UpperLength  = 0;
> > +        }
> > +        Trb->Adma64Desc[Index].LowerLength  = 0;
> > +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > +      }
> >      }
> >
> > -    Remaining -= ADMA_MAX_DATA_PER_LINE;
> > -    Address   += ADMA_MAX_DATA_PER_LINE;
> > +    Remaining -= AdmaMaxDataPerLine;
> > +    Address   += AdmaMaxDataPerLine;
> >    }
> >
> >    //
> >    // Set the last descriptor line as end of descriptor table
> >    //
> > -  Trb->AdmaDesc[Index].End = 1;
> > +  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> > >Adma32Desc[Index].End = 1);
> >    return EFI_SUCCESS;
> >  }
> >
> > @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
> >        Trb->Mode = SdMmcNoData;
> >      } else if (Private->Capability[Slot].Adma2 != 0) {
> >        Trb->Mode = SdMmcAdmaMode;
> > -      Status = BuildAdmaDescTable (Trb);
> > +      Status = BuildAdmaDescTable (Trb, 
> > + Private->ControllerVersion[Slot]);
> >        if (EFI_ERROR (Status)) {
> >          PciIo->Unmap (PciIo, Trb->DataMap);
> >          goto Error;
> > @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
> >        Trb->AdmaMap
> >      );
> >    }
> > -  if (Trb->AdmaDesc != NULL) {
> > +  if (Trb->Adma32Desc != NULL) {
> > +    PciIo->FreeBuffer (
> > +      PciIo,
> > +      Trb->AdmaPages,
> > +      Trb->Adma32Desc
> > +    );
> > +  }
> > +  if (Trb->Adma64Desc != NULL) {
> >      PciIo->FreeBuffer (
> >        PciIo,
> >        Trb->AdmaPages,
> > -      Trb->AdmaDesc
> > +      Trb->Adma64Desc
> >      );
> >    }
> >    if (Trb->DataMap != NULL) {
> > @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
> >    UINT16                              Cmd;
> >    UINT16                              IntStatus;
> >    UINT32                              Argument;
> > -  UINT16                              BlkCount;
> > +  UINT32                              BlkCount;
> >    UINT16                              BlkSize;
> >    UINT16                              TransMode;
> >    UINT8                               HostCtrl1;
> > -  UINT32                              SdmaAddr;
> > +  UINT64                              SdmaAddr;
> >    UINT64                              AdmaAddr;
> > +  BOOLEAN                             AddressingMode64;
> > +
> > +  AddressingMode64 = FALSE;
> >
> >    Packet = Trb->Packet;
> >    PciIo  = Trb->Private->PciIo;
> > @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> >
> >    SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> >
> > +  if (Private->ControllerVersion[Trb->Slot] >= 
> > + SD_MMC_HC_CTRL_VER_400)
> > {
> > +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > +                                 
> > + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > +    if (!EFI_ERROR (Status)) {
> > +      AddressingMode64 = TRUE;
> > +    }
> > +  }
> > +
> >    if (Trb->Mode == SdMmcSdmaMode) {
> > -    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> > +    if ((!AddressingMode64) &&
> > +        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
> >        return EFI_INVALID_PARAMETER;
> >      }
> >
> > -    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> > -    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (SdmaAddr), &SdmaAddr);
> > +    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> > +
> > +    if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> > +    } else {
> > +      Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> > +    }
> > +
> >      if (EFI_ERROR (Status)) {
> >        return Status;
> >      }
> > @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
> >      //
> >      // Calcuate Block Count.
> >      //
> > -    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> > +    BlkCount = (Trb->DataLen / Trb->BlockSize);  }  if 
> > + (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> > {
> > +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (UINT32), &BlkCount);
> > +  } else {
> > +    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (UINT16), &BlkCount);
> >    }
> > -  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (BlkCount), &BlkCount);
> >    if (EFI_ERROR (Status)) {
> >      return Status;
> >    }
> > @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
> >    EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
> >    UINT16                              IntStatus;
> >    UINT32                              Response[4];
> > -  UINT32                              SdmaAddr;
> > +  UINT64                              SdmaAddr;
> >    UINT8                               Index;
> >    UINT8                               SwReset;
> >    UINT32                              PioLength;
> > @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
> >      //
> >      // Update SDMA Address register.
> >      //
> > -    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> > >DataPhy, SD_MMC_SDMA_BOUNDARY);
> > -    Status   = SdMmcHcRwMmio (
> > +    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> > SD_MMC_SDMA_BOUNDARY);
> > +
> > +    if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > +      Status = SdMmcHcRwMmio (
> > +                 Private->PciIo,
> > +                 Trb->Slot,
> > +                 SD_MMC_HC_ADMA_SYS_ADDR,
> > +                 FALSE,
> > +                 sizeof (UINT64),
> > +                 &SdmaAddr
> > +                 );
> > +    } else {
> > +      Status = SdMmcHcRwMmio (
> >                   Private->PciIo,
> >                   Trb->Slot,
> >                   SD_MMC_HC_SDMA_ADDR, @@ -1972,10 +2182,12 @@ 
> > SdMmcCheckTrbResult (
> >                   sizeof (UINT32),
> >                   &SdmaAddr
> >                   );
> > +    }
> > +
> >      if (EFI_ERROR (Status)) {
> >        goto Done;
> >      }
> > -    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> > +    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
> >    }
> >
> >    if ((Packet->SdMmcCmdBlk->CommandType !=
> SdMmcCommandTypeAdtc)
> > &&
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > index dd45cbd..d157f2c 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > @@ -2,6 +2,7 @@
> >
> >    Provides some data structure definitions used by the SD/MMC host 
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> >  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>  
> > This program and the accompanying materials  are licensed and made 
> > available under the terms and conditions of the
> BSD
> > License
> > @@ -91,18 +92,38 @@ typedef enum {
> >  //
> >  // The maximum data length of each descriptor line  //
> > -#define ADMA_MAX_DATA_PER_LINE     0x10000
> > +#define ADMA_MAX_DATA_PER_LINE_16B     SIZE_64KB
> > +#define ADMA_MAX_DATA_PER_LINE_26B     SIZE_64MB
> >
> > +//
> > +// ADMA descriptor for 32b addressing.
> > +//
> >  typedef struct {
> >    UINT32 Valid:1;
> >    UINT32 End:1;
> >    UINT32 Int:1;
> >    UINT32 Reserved:1;
> >    UINT32 Act:2;
> > -  UINT32 Reserved1:10;
> > -  UINT32 Length:16;
> > +  UINT32 UpperLength:10;
> > +  UINT32 LowerLength:16;
> >    UINT32 Address;
> > -} SD_MMC_HC_ADMA_DESC_LINE;
> > +} SD_MMC_HC_ADMA_32_DESC_LINE;
> > +
> > +//
> > +// ADMA descriptor for 64b addressing.
> > +//
> > +typedef struct {
> > +  UINT32 Valid:1;
> > +  UINT32 End:1;
> > +  UINT32 Int:1;
> > +  UINT32 Reserved:1;
> > +  UINT32 Act:2;
> > +  UINT32 UpperLength:10;
> > +  UINT32 LowerLength:16;
> > +  UINT32 LowerAddress;
> > +  UINT32 UpperAddress;
> > +  UINT32 Reserved1;
> > +} SD_MMC_HC_ADMA_64_DESC_LINE;
> >
> >  #define SD_MMC_SDMA_BOUNDARY          512 * 1024
> >  #define SD_MMC_SDMA_ROUND_UP(x, n)    (((x) + n) & ~(n - 1))
> > @@ -129,36 +150,43 @@ typedef struct {
> >    UINT32   Voltage33:1;       // bit 24
> >    UINT32   Voltage30:1;       // bit 25
> >    UINT32   Voltage18:1;       // bit 26
> > -  UINT32   Reserved3:1;       // bit 27
> > -  UINT32   SysBus64:1;        // bit 28
> > +  UINT32   SysBus64V4:1;      // bit 27
> > +  UINT32   SysBus64V3:1;      // bit 28
> >    UINT32   AsyncInt:1;        // bit 29
> >    UINT32   SlotType:2;        // bit 30:31
> >    UINT32   Sdr50:1;           // bit 32
> >    UINT32   Sdr104:1;          // bit 33
> >    UINT32   Ddr50:1;           // bit 34
> > -  UINT32   Reserved4:1;       // bit 35
> > +  UINT32   Reserved3:1;       // bit 35
> >    UINT32   DriverTypeA:1;     // bit 36
> >    UINT32   DriverTypeC:1;     // bit 37
> >    UINT32   DriverTypeD:1;     // bit 38
> >    UINT32   DriverType4:1;     // bit 39
> >    UINT32   TimerCount:4;      // bit 40:43
> > -  UINT32   Reserved5:1;       // bit 44
> > +  UINT32   Reserved4:1;       // bit 44
> >    UINT32   TuningSDR50:1;     // bit 45
> >    UINT32   RetuningMod:2;     // bit 46:47
> >    UINT32   ClkMultiplier:8;   // bit 48:55
> > -  UINT32   Reserved6:7;       // bit 56:62
> > +  UINT32   Reserved5:7;       // bit 56:62
> >    UINT32   Hs400:1;           // bit 63
> >  } SD_MMC_HC_SLOT_CAP;
> >
> >  //
> >  // SD Host controller version
> >  //
> > -#define SD_MMC_HC_CTRL_VER_100      0x00
> > -#define SD_MMC_HC_CTRL_VER_200      0x01
> > -#define SD_MMC_HC_CTRL_VER_300      0x02
> > -#define SD_MMC_HC_CTRL_VER_400      0x03
> > -#define SD_MMC_HC_CTRL_VER_410      0x04
> > -#define SD_MMC_HC_CTRL_VER_420      0x05
> > +#define SD_MMC_HC_CTRL_VER_100        0x00
> > +#define SD_MMC_HC_CTRL_VER_200        0x01
> > +#define SD_MMC_HC_CTRL_VER_300        0x02
> > +#define SD_MMC_HC_CTRL_VER_400        0x03
> > +#define SD_MMC_HC_CTRL_VER_410        0x04
> > +#define SD_MMC_HC_CTRL_VER_420        0x05
> > +
> > +//
> > +// SD Host controller V4 enhancements //
> > +#define SD_MMC_HC_V4_EN               BIT12
> > +#define SD_MMC_HC_64_ADDR_EN          BIT13
> > +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> >
> >  /**
> >    Dump the content of SD/MMC host controller's Capability Register.
> > @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
> >    );
> >
> >  /**
> > +  Get the controller version information from the specified slot.
> > +
> > +  @param[in]  PciIo           The PCI IO protocol instance.
> > +  @param[in]  Slot            The slot number of the SD card to send the
> > command to.
> > +  @param[out] Version         The buffer to store the version information.
> > +
> > +  @retval EFI_SUCCESS         The operation executes successfully.
> > +  @retval Others              The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > +  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
> > +  IN  UINT8                Slot,
> > +  OUT UINT16               *Version
> > +  );
> > +
> > +/**
> >    Set all interrupt status bits in Normal and Error Interrupt Status Enable
> >    register.
> >
> > @@ -424,6 +470,7 @@ SdMmcHcStopClock (
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] ClockFreq      The max clock frequency to be set. The unit is
> KHz.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> >    IN UINT64                 ClockFreq,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    );
> >
> >  /**
> > @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
> >    @param[in] PciIo          The PCI IO protocol instance.
> >    @param[in] Slot           The slot number of the SD card to send the
> command
> > to.
> >    @param[in] BaseClkFreq    The base clock frequency of host controller in
> > MHz.
> > +  @param[in] ControllerVer  The version of host controller.
> >
> >    @retval EFI_SUCCESS       The clock is supplied successfully.
> >    @retval Others            The clock isn't supplied successfully.
> > @@ -492,7 +541,8 @@ EFI_STATUS
> >  SdMmcHcInitClockFreq (
> >    IN EFI_PCI_IO_PROTOCOL    *PciIo,
> >    IN UINT8                  Slot,
> > -  IN UINT32                 BaseClkFreq
> > +  IN UINT32                 BaseClkFreq,
> > +  IN UINT16                 ControllerVer
> >    );
> >
> >  /**
> > --
> > 2.7.4
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-01-02 15:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-12-18 21:29 [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support Ashish Singhal
2018-12-19  1:46 ` Wu, Hao A
2018-12-19 20:00   ` Ashish Singhal
2018-12-26 21:24   ` Ashish Singhal
2019-01-02  6:28 ` Wu, Hao A
2019-01-02  6:36   ` Wu, Hao A
2019-01-02 15:47     ` Ashish Singhal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox