public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/2] MdeModulePkg/SdMmcPciHcDxe: Declare V4 64 bit address capability
@ 2018-11-08 18:58 Ashish Singhal
  2018-11-08 18:58 ` [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support Ashish Singhal
  0 siblings, 1 reply; 4+ messages in thread
From: Ashish Singhal @ 2018-11-08 18:58 UTC (permalink / raw)
  To: edk2-devel; +Cc: Ashish Singhal

Add capability declaration for V4.x 64 bit system address support.
This would be used for host controllers working in version 4. Enable
64 bit DMA support in PCI layer if V3 or V4 64 bit support is
enabled in host capability register.

The usage of this new field does not need a guard for version check as
spec for previous SDMMC versions defines this field as reserved with
default value of 0.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
---
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c |  4 ++--
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   |  3 ++-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   | 10 +++++-----
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
index bf9869d..1c18ea4 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
@@ -617,7 +617,6 @@ SdMmcPciHcDriverBindingStart (
     }
   }
 
-  Support64BitDma = TRUE;
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
     Private->Slot[Slot].Enable = TRUE;
 
@@ -638,7 +637,8 @@ SdMmcPciHcDriverBindingStart (
     }
     DumpCapabilityReg (Slot, &Private->Capability[Slot]);
 
-    Support64BitDma &= Private->Capability[Slot].SysBus64;
+    Support64BitDma = (Private->Capability[Slot].SysBus64V3 |
+                       Private->Capability[Slot].SysBus64V4);
 
     Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
     if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
index bedc968..e506875 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
@@ -45,7 +45,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) {
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index 7e3f588..cc138fc 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
@@ -114,24 +114,24 @@ 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;
 
-- 
2.7.4



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

* [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support.
  2018-11-08 18:58 [PATCH 1/2] MdeModulePkg/SdMmcPciHcDxe: Declare V4 64 bit address capability Ashish Singhal
@ 2018-11-08 18:58 ` Ashish Singhal
  2018-11-16  8:26   ` Wu, Hao A
  0 siblings, 1 reply; 4+ messages in thread
From: Ashish Singhal @ 2018-11-08 18:58 UTC (permalink / raw)
  To: edk2-devel; +Cc: Ashish Singhal

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.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
---
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   4 +-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 183 +++++++++++++++++----
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  28 +++-
 3 files changed, 183 insertions(+), 32 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
index c683600..22795df 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
@@ -144,7 +145,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 e506875..bcd2707 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
@@ -418,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.
@@ -776,18 +807,18 @@ 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);
+  Status = SdMmcHcGetControllerVersion (PciIo, Slot, &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 == 0) || (ControllerVer == 1)) {
     //
     // Only the most significant bit can be used as divisor.
     //
@@ -935,6 +966,41 @@ SdMmcHcSetBusWidth (
 }
 
 /**
+  Configure V4 64 bit system address support 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.
+
+  @retval EFI_SUCCESS       The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcV4Init64BitSupport (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_HC_SLOT_CAP     Capability
+  )
+{
+  EFI_STATUS                Status;
+  UINT16                    HostCtrl2;
+
+  //
+  // Check if V4 64bit support is available
+  //
+  if (Capability.SysBus64V4 == TRUE) {
+    HostCtrl2 = SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN;
+    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Supply SD/MMC card with lowest clock frequency at initialization.
 
   @param[in] PciIo          The PCI IO protocol instance.
@@ -1101,6 +1167,11 @@ SdMmcHcInitHost (
   PciIo = Private->PciIo;
   Capability = Private->Capability[Slot];
 
+  Status = SdMmcHcV4Init64BitSupport (PciIo, Slot, Capability);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
   Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
   if (EFI_ERROR (Status)) {
     return Status;
@@ -1169,7 +1240,7 @@ 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.
 
@@ -1187,49 +1258,69 @@ BuildAdmaDescTable (
   UINT64                    Entries;
   UINT32                    Index;
   UINT64                    Remaining;
-  UINT32                    Address;
+  UINT64                    Address;
   UINTN                     TableSize;
   EFI_PCI_IO_PROTOCOL       *PciIo;
   EFI_STATUS                Status;
   UINTN                     Bytes;
+  UINT16                    ControllerVer;
+  BOOLEAN                   AddressingMode64 = FALSE;
+  UINTN                     DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+  VOID                      *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)) {
+  Status = SdMmcHcGetControllerVersion (PciIo, Trb->Slot, &ControllerVer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, 0x2,
+                                 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 == FALSE &&
+      ((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.
   //
   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));
   }
 
   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));
+  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
@@ -1242,12 +1333,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 == FALSE) &&
+      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
     //
     // The ADMA doesn't support 64bit addressing.
     //
@@ -1258,25 +1350,49 @@ 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 == FALSE) {
+    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 == FALSE) {
+      if (Remaining < ADMA_MAX_DATA_PER_LINE) {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        Trb->Adma32Desc[Index].Length  = (UINT16)Remaining;
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+        break;
+      } else {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        Trb->Adma32Desc[Index].Length  = 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 < ADMA_MAX_DATA_PER_LINE) {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        Trb->Adma64Desc[Index].Length  = (UINT16)Remaining;
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address & MAX_UINT32);
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
+        break;
+      } else {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        Trb->Adma64Desc[Index].Length  = 0;
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address & MAX_UINT32);
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
+      }
     }
 
     Remaining -= ADMA_MAX_DATA_PER_LINE;
@@ -1286,7 +1402,7 @@ BuildAdmaDescTable (
   //
   // 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;
 }
 
@@ -1430,11 +1546,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) {
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index cc138fc..a6234f1 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
@@ -78,6 +79,9 @@ typedef enum {
 //
 #define ADMA_MAX_DATA_PER_LINE     0x10000
 
+//
+// ADMA descriptor for 32b addressing.
+//
 typedef struct {
   UINT32 Valid:1;
   UINT32 End:1;
@@ -87,7 +91,23 @@ typedef struct {
   UINT32 Reserved1:10;
   UINT32 Length: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 Reserved1:10;
+  UINT32 Length:16;
+  UINT32 LowerAddress;
+  UINT32 UpperAddress;
+  UINT32 Reserved2;
+} 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))
@@ -145,6 +165,12 @@ typedef struct {
 #define SD_MMC_HC_CTRL_VER_410      0x04
 #define SD_MMC_HC_CTRL_VER_420      0x05
 
+//
+// SD Host controller V4 Support
+//
+#define SD_MMC_HC_V4_EN             BIT12
+#define SD_MMC_HC_64_ADDR_EN        BIT13
+
 /**
   Dump the content of SD/MMC host controller's Capability Register.
 
-- 
2.7.4



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

* Re: [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support.
  2018-11-08 18:58 ` [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support Ashish Singhal
@ 2018-11-16  8:26   ` Wu, Hao A
  2018-11-19 20:32     ` Ashish Singhal
  0 siblings, 1 reply; 4+ messages in thread
From: Wu, Hao A @ 2018-11-16  8:26 UTC (permalink / raw)
  To: Ashish Singhal, edk2-devel@lists.01.org

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ashish Singhal
> Sent: Friday, November 09, 2018 2:58 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit
> ADMA2 support.
> 
> 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.

Hi,

I have a quick check on the SD Host Controller Simplified Specification Version
4.20. When the 'Host Version 4 Enable' bit in the HC2 Register is set, for host
controller with version newer than 3.0:

SDMA mode transfer no longer use SDMA System Address Register for system
address, and this SDMA System Address Register will be used as 32-bit Block
Count instead under certain case.

So I think the way to start an SDMA mode transfer is not the same between host
controllers with different versions. However, I do not see this patch handle
this potential behavior change. Please correct me if my understanding is
incorrect here.

Also, could you help to provide information on what tests have been performed
on this series?

Thanks in advance.

Best Regards,
Hao Wu

> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 183
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  28 +++-
>  3 files changed, 183 insertions(+), 32 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index c683600..22795df 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
> @@ -144,7 +145,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 e506875..bcd2707 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
> @@ -418,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.
> @@ -776,18 +807,18 @@ 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);
> +  Status = SdMmcHcGetControllerVersion (PciIo, Slot, &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 == 0) || (ControllerVer == 1)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -935,6 +966,41 @@ SdMmcHcSetBusWidth (
>  }
> 
>  /**
> +  Configure V4 64 bit system address support 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.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcV4Init64BitSupport (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if V4 64bit support is available
> +  //
> +  if (Capability.SysBus64V4 == TRUE) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN;
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +    DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
> 
>    @param[in] PciIo          The PCI IO protocol instance.
> @@ -1101,6 +1167,11 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
> 
> +  Status = SdMmcHcV4Init64BitSupport (PciIo, Slot, Capability);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
>    Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
>    if (EFI_ERROR (Status)) {
>      return Status;
> @@ -1169,7 +1240,7 @@ 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.
> 
> @@ -1187,49 +1258,69 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  UINT16                    ControllerVer;
> +  BOOLEAN                   AddressingMode64 = FALSE;
> +  UINTN                     DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  VOID                      *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)) {
> +  Status = SdMmcHcGetControllerVersion (PciIo, Trb->Slot, &ControllerVer);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, 0x2,
> +                                 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 == FALSE &&
> +      ((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.
>    //
>    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));
>    }
> 
>    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));
> +  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
> @@ -1242,12 +1333,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 == FALSE) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1258,25 +1350,49 @@ 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 == FALSE) {
> +    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 == FALSE) {
> +      if (Remaining < ADMA_MAX_DATA_PER_LINE) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        Trb->Adma32Desc[Index].Length  = (UINT16)Remaining;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        Trb->Adma32Desc[Index].Length  = 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 < ADMA_MAX_DATA_PER_LINE) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        Trb->Adma64Desc[Index].Length  = (UINT16)Remaining;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address &
> MAX_UINT32);
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        Trb->Adma64Desc[Index].Length  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address &
> MAX_UINT32);
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
> +      }
>      }
> 
>      Remaining -= ADMA_MAX_DATA_PER_LINE;
> @@ -1286,7 +1402,7 @@ BuildAdmaDescTable (
>    //
>    // 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;
>  }
> 
> @@ -1430,11 +1546,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) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index cc138fc..a6234f1 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
> @@ -78,6 +79,9 @@ typedef enum {
>  //
>  #define ADMA_MAX_DATA_PER_LINE     0x10000
> 
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
> @@ -87,7 +91,23 @@ typedef struct {
>    UINT32 Reserved1:10;
>    UINT32 Length: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 Reserved1:10;
> +  UINT32 Length:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved2;
> +} 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))
> @@ -145,6 +165,12 @@ typedef struct {
>  #define SD_MMC_HC_CTRL_VER_410      0x04
>  #define SD_MMC_HC_CTRL_VER_420      0x05
> 
> +//
> +// SD Host controller V4 Support
> +//
> +#define SD_MMC_HC_V4_EN             BIT12
> +#define SD_MMC_HC_64_ADDR_EN        BIT13
> +
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> 
> --
> 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] 4+ messages in thread

* Re: [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support.
  2018-11-16  8:26   ` Wu, Hao A
@ 2018-11-19 20:32     ` Ashish Singhal
  0 siblings, 0 replies; 4+ messages in thread
From: Ashish Singhal @ 2018-11-19 20:32 UTC (permalink / raw)
  To: Wu, Hao A, edk2-devel@lists.01.org

Hi,

I was planning on submitting SDMA changes as a separate patch but that would have broken SDMA if only ADMA2 patch would have been picked. I have sent V2 patches which combine SDMA as well as ADMA2 changes. I have tested the changes to be working on V3 as well V4 mode usage both with and without enabling 64b addressing support.

Thanks
Ashish

-----Original Message-----
From: Wu, Hao A <hao.a.wu@intel.com> 
Sent: Friday, November 16, 2018 1:27 AM
To: Ashish Singhal <ashishsingha@nvidia.com>; edk2-devel@lists.01.org
Subject: RE: [edk2] [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support.

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Ashish Singhal
> Sent: Friday, November 09, 2018 2:58 AM
> To: edk2-devel@lists.01.org
> Cc: Ashish Singhal
> Subject: [edk2] [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit
> ADMA2 support.
> 
> 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.

Hi,

I have a quick check on the SD Host Controller Simplified Specification Version 4.20. When the 'Host Version 4 Enable' bit in the HC2 Register is set, for host controller with version newer than 3.0:

SDMA mode transfer no longer use SDMA System Address Register for system address, and this SDMA System Address Register will be used as 32-bit Block Count instead under certain case.

So I think the way to start an SDMA mode transfer is not the same between host controllers with different versions. However, I do not see this patch handle this potential behavior change. Please correct me if my understanding is incorrect here.

Also, could you help to provide information on what tests have been performed on this series?

Thanks in advance.

Best Regards,
Hao Wu

> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> ---
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h |   4 +-
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c   | 183
> +++++++++++++++++----
>  MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h   |  28 +++-
>  3 files changed, 183 insertions(+), 32 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> index c683600..22795df 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 @@ -144,7 
> +145,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 e506875..bcd2707 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 @@ -418,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.
> @@ -776,18 +807,18 @@ 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);
> +  Status = SdMmcHcGetControllerVersion (PciIo, Slot, &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 == 0) || (ControllerVer == 1)) {
>      //
>      // Only the most significant bit can be used as divisor.
>      //
> @@ -935,6 +966,41 @@ SdMmcHcSetBusWidth (  }
> 
>  /**
> +  Configure V4 64 bit system address support 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.
> +
> +  @retval EFI_SUCCESS       The clock is supplied successfully.
> +
> +**/
> +EFI_STATUS
> +SdMmcHcV4Init64BitSupport (
> +  IN EFI_PCI_IO_PROTOCOL    *PciIo,
> +  IN UINT8                  Slot,
> +  IN SD_MMC_HC_SLOT_CAP     Capability
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT16                    HostCtrl2;
> +
> +  //
> +  // Check if V4 64bit support is available  //  if 
> + (Capability.SysBus64V4 == TRUE) {
> +    HostCtrl2 = SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN;
> +    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof
> (HostCtrl2), &HostCtrl2);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +    DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));  
> + }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Supply SD/MMC card with lowest clock frequency at initialization.
> 
>    @param[in] PciIo          The PCI IO protocol instance.
> @@ -1101,6 +1167,11 @@ SdMmcHcInitHost (
>    PciIo = Private->PciIo;
>    Capability = Private->Capability[Slot];
> 
> +  Status = SdMmcHcV4Init64BitSupport (PciIo, Slot, Capability);  if 
> + (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
>    Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
>    if (EFI_ERROR (Status)) {
>      return Status;
> @@ -1169,7 +1240,7 @@ 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.
> 
> @@ -1187,49 +1258,69 @@ BuildAdmaDescTable (
>    UINT64                    Entries;
>    UINT32                    Index;
>    UINT64                    Remaining;
> -  UINT32                    Address;
> +  UINT64                    Address;
>    UINTN                     TableSize;
>    EFI_PCI_IO_PROTOCOL       *PciIo;
>    EFI_STATUS                Status;
>    UINTN                     Bytes;
> +  UINT16                    ControllerVer;
> +  BOOLEAN                   AddressingMode64 = FALSE;
> +  UINTN                     DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> +  VOID                      *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)) 
> {
> +  Status = SdMmcHcGetControllerVersion (PciIo, Trb->Slot, 
> + &ControllerVer);  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> +    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> SD_MMC_HC_HOST_CTRL2, 0x2,
> +                                 
> + 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 == FALSE &&
> +      ((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.
>    //
>    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));
>    }
> 
>    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));
> +  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
> @@ -1242,12 +1333,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 == FALSE) &&
> +      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
>      //
>      // The ADMA doesn't support 64bit addressing.
>      //
> @@ -1258,25 +1350,49 @@ 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 == FALSE) {
> +    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 == FALSE) {
> +      if (Remaining < ADMA_MAX_DATA_PER_LINE) {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        Trb->Adma32Desc[Index].Length  = (UINT16)Remaining;
> +        Trb->Adma32Desc[Index].Address = (UINT32)Address;
> +        break;
> +      } else {
> +        Trb->Adma32Desc[Index].Valid = 1;
> +        Trb->Adma32Desc[Index].Act   = 2;
> +        Trb->Adma32Desc[Index].Length  = 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 < ADMA_MAX_DATA_PER_LINE) {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        Trb->Adma64Desc[Index].Length  = (UINT16)Remaining;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address &
> MAX_UINT32);
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
> +        break;
> +      } else {
> +        Trb->Adma64Desc[Index].Valid = 1;
> +        Trb->Adma64Desc[Index].Act   = 2;
> +        Trb->Adma64Desc[Index].Length  = 0;
> +        Trb->Adma64Desc[Index].LowerAddress = (UINT32)(Address &
> MAX_UINT32);
> +        Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address>>32);
> +      }
>      }
> 
>      Remaining -= ADMA_MAX_DATA_PER_LINE; @@ -1286,7 +1402,7 @@ 
> BuildAdmaDescTable (
>    //
>    // 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;
>  }
> 
> @@ -1430,11 +1546,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) {
> diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> index cc138fc..a6234f1 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 @@ -78,6 
> +79,9 @@ typedef enum {  //
>  #define ADMA_MAX_DATA_PER_LINE     0x10000
> 
> +//
> +// ADMA descriptor for 32b addressing.
> +//
>  typedef struct {
>    UINT32 Valid:1;
>    UINT32 End:1;
> @@ -87,7 +91,23 @@ typedef struct {
>    UINT32 Reserved1:10;
>    UINT32 Length: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 Reserved1:10;
> +  UINT32 Length:16;
> +  UINT32 LowerAddress;
> +  UINT32 UpperAddress;
> +  UINT32 Reserved2;
> +} 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))
> @@ -145,6 +165,12 @@ typedef struct {
>  #define SD_MMC_HC_CTRL_VER_410      0x04
>  #define SD_MMC_HC_CTRL_VER_420      0x05
> 
> +//
> +// SD Host controller V4 Support
> +//
> +#define SD_MMC_HC_V4_EN             BIT12
> +#define SD_MMC_HC_64_ADDR_EN        BIT13
> +
>  /**
>    Dump the content of SD/MMC host controller's Capability Register.
> 
> --
> 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] 4+ messages in thread

end of thread, other threads:[~2018-11-19 20:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-08 18:58 [PATCH 1/2] MdeModulePkg/SdMmcPciHcDxe: Declare V4 64 bit address capability Ashish Singhal
2018-11-08 18:58 ` [PATCH 2/2] MdeModulePkg/SdMmcPciHcDxe: Add V4 64bit ADMA2 support Ashish Singhal
2018-11-16  8:26   ` Wu, Hao A
2018-11-19 20:32     ` Ashish Singhal

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