]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/SdMmcPciHcDxe: Add V3 64b DMA Support
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHci.c
index d73fa10a3510726a2da36bdaa3e72a5433d23514..6fefed12ff33a73bdcb570aab91e718155fa21fc 100644 (file)
@@ -6,7 +6,7 @@
 \r
   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.\r
 \r
-  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
+  Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\r
   Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -1010,16 +1010,28 @@ SdMmcHcInitV4Enhancements (
   if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
     HostCtrl2 = SD_MMC_HC_V4_EN;\r
     //\r
-    // Check if V4 64bit support is available\r
+    // Check if controller version V4.0\r
     //\r
-    if (Capability.SysBus64V4 != 0) {\r
-      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
-      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
+    if (ControllerVer == SD_MMC_HC_CTRL_VER_400) {\r
+      //\r
+      // Check if 64bit support is available\r
+      //\r
+      if (Capability.SysBus64V3 != 0) {\r
+        HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
+        DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
+      }\r
     }\r
     //\r
     // Check if controller version V4.10 or higher\r
     //\r
-    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {\r
+    else if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {\r
+      //\r
+      // Check if 64bit support is available\r
+      //\r
+      if (Capability.SysBus64V4 != 0) {\r
+        HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
+        DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
+      }\r
       HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;\r
       DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));\r
     }\r
@@ -1393,14 +1405,10 @@ BuildAdmaDescTable (
   EFI_PCI_IO_PROTOCOL       *PciIo;\r
   EFI_STATUS                Status;\r
   UINTN                     Bytes;\r
-  BOOLEAN                   AddressingMode64;\r
-  BOOLEAN                   DataLength26;\r
   UINT32                    AdmaMaxDataPerLine;\r
   UINT32                    DescSize;\r
   VOID                      *AdmaDesc;\r
 \r
-  AddressingMode64   = FALSE;\r
-  DataLength26       = FALSE;\r
   AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;\r
   DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);\r
   AdmaDesc           = NULL;\r
@@ -1409,28 +1417,17 @@ BuildAdmaDescTable (
   DataLen = Trb->DataLen;\r
   PciIo   = Trb->Private->PciIo;\r
 \r
-  //\r
-  // Detect whether 64bit addressing is supported.\r
-  //\r
-  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
-    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
-                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
-    if (!EFI_ERROR (Status)) {\r
-      AddressingMode64 = TRUE;\r
-      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);\r
-    }\r
-  }\r
   //\r
   // Check for valid ranges in 32bit ADMA Descriptor Table\r
   //\r
-  if (!AddressingMode64 &&\r
+  if ((Trb->Mode == SdMmcAdma32bMode) &&\r
       ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   //\r
   // Check address field alignment\r
   //\r
-  if (AddressingMode64) {\r
+  if (Trb->Mode != SdMmcAdma32bMode) {\r
     //\r
     // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)\r
     //\r
@@ -1445,13 +1442,19 @@ BuildAdmaDescTable (
       DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
     }\r
   }\r
+\r
   //\r
-  // Detect whether 26bit data length is supported.\r
+  // Configure 64b ADMA.\r
   //\r
-  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
-                               SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);\r
-  if (!EFI_ERROR (Status)) {\r
-    DataLength26 = TRUE;\r
+  if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+    DescSize = sizeof (SD_MMC_HC_ADMA_64_V3_DESC_LINE);\r
+  }else if (Trb->Mode == SdMmcAdma64bV4Mode) {\r
+    DescSize = sizeof (SD_MMC_HC_ADMA_64_V4_DESC_LINE);\r
+  }\r
+  //\r
+  // Configure 26b data length.\r
+  //\r
+  if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
     AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;\r
   }\r
 \r
@@ -1492,7 +1495,7 @@ BuildAdmaDescTable (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  if ((!AddressingMode64) &&\r
+  if ((Trb->Mode == SdMmcAdma32bMode) &&\r
       (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {\r
     //\r
     // The ADMA doesn't support 64bit addressing.\r
@@ -1511,19 +1514,20 @@ BuildAdmaDescTable (
 \r
   Remaining = DataLen;\r
   Address   = Data;\r
-  if (!AddressingMode64) {\r
+  if (Trb->Mode == SdMmcAdma32bMode) {\r
     Trb->Adma32Desc = AdmaDesc;\r
-    Trb->Adma64Desc = NULL;\r
+  } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+    Trb->Adma64V3Desc = AdmaDesc;\r
   } else {\r
-    Trb->Adma64Desc = AdmaDesc;\r
-    Trb->Adma32Desc = NULL;\r
+    Trb->Adma64V4Desc = AdmaDesc;\r
   }\r
+\r
   for (Index = 0; Index < Entries; Index++) {\r
-    if (!AddressingMode64) {\r
+    if (Trb->Mode == SdMmcAdma32bMode) {\r
       if (Remaining <= AdmaMaxDataPerLine) {\r
         Trb->Adma32Desc[Index].Valid = 1;\r
         Trb->Adma32Desc[Index].Act   = 2;\r
-        if (DataLength26) {\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
           Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);\r
         }\r
         Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
@@ -1532,32 +1536,53 @@ BuildAdmaDescTable (
       } else {\r
         Trb->Adma32Desc[Index].Valid = 1;\r
         Trb->Adma32Desc[Index].Act   = 2;\r
-        if (DataLength26) {\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
           Trb->Adma32Desc[Index].UpperLength  = 0;\r
         }\r
         Trb->Adma32Desc[Index].LowerLength  = 0;\r
         Trb->Adma32Desc[Index].Address = (UINT32)Address;\r
       }\r
+    } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+      if (Remaining <= AdmaMaxDataPerLine) {\r
+        Trb->Adma64V3Desc[Index].Valid = 1;\r
+        Trb->Adma64V3Desc[Index].Act   = 2;\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+          Trb->Adma64V3Desc[Index].UpperLength  = (UINT16)RShiftU64 (Remaining, 16);\r
+        }\r
+        Trb->Adma64V3Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);\r
+        Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;\r
+        Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+        break;\r
+      } else {\r
+        Trb->Adma64V3Desc[Index].Valid = 1;\r
+        Trb->Adma64V3Desc[Index].Act   = 2;\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+          Trb->Adma64V3Desc[Index].UpperLength  = 0;\r
+        }\r
+        Trb->Adma64V3Desc[Index].LowerLength  = 0;\r
+        Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;\r
+        Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+      }\r
     } else {\r
       if (Remaining <= AdmaMaxDataPerLine) {\r
-        Trb->Adma64Desc[Index].Valid = 1;\r
-        Trb->Adma64Desc[Index].Act   = 2;\r
-        if (DataLength26) {\r
-          Trb->Adma64Desc[Index].UpperLength  = (UINT16)RShiftU64 (Remaining, 16);\r
+        Trb->Adma64V4Desc[Index].Valid = 1;\r
+        Trb->Adma64V4Desc[Index].Act   = 2;\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+          Trb->Adma64V4Desc[Index].UpperLength  = (UINT16)RShiftU64 (Remaining, 16);\r
         }\r
-        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);\r
-        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
-        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+        Trb->Adma64V4Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);\r
+        Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;\r
+        Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
         break;\r
       } else {\r
-        Trb->Adma64Desc[Index].Valid = 1;\r
-        Trb->Adma64Desc[Index].Act   = 2;\r
-        if (DataLength26) {\r
-          Trb->Adma64Desc[Index].UpperLength  = 0;\r
+        Trb->Adma64V4Desc[Index].Valid = 1;\r
+        Trb->Adma64V4Desc[Index].Act   = 2;\r
+        if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+          Trb->Adma64V4Desc[Index].UpperLength  = 0;\r
         }\r
-        Trb->Adma64Desc[Index].LowerLength  = 0;\r
-        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
-        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+        Trb->Adma64V4Desc[Index].LowerLength  = 0;\r
+        Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;\r
+        Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
       }\r
     }\r
 \r
@@ -1568,7 +1593,13 @@ BuildAdmaDescTable (
   //\r
   // Set the last descriptor line as end of descriptor table\r
   //\r
-  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);\r
+  if (Trb->Mode == SdMmcAdma32bMode) {\r
+    Trb->Adma32Desc[Index].End = 1;\r
+  } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+    Trb->Adma64V3Desc[Index].End = 1;\r
+  } else {\r
+    Trb->Adma64V4Desc[Index].End = 1;\r
+  }\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1665,7 +1696,20 @@ SdMmcCreateTrb (
     if (Trb->DataLen == 0) {\r
       Trb->Mode = SdMmcNoData;\r
     } else if (Private->Capability[Slot].Adma2 != 0) {\r
-      Trb->Mode = SdMmcAdmaMode;\r
+      Trb->Mode = SdMmcAdma32bMode;\r
+      Trb->AdmaLengthMode = SdMmcAdmaLen16b;\r
+      if ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300) &&\r
+          (Private->Capability[Slot].SysBus64V3 == 1)) {\r
+        Trb->Mode = SdMmcAdma64bV3Mode;\r
+      } else if (((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400) &&\r
+                  (Private->Capability[Slot].SysBus64V3 == 1)) ||\r
+                 ((Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) &&\r
+                  (Private->Capability[Slot].SysBus64V4 == 1))) {\r
+        Trb->Mode = SdMmcAdma64bV4Mode;\r
+      }\r
+      if (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
+        Trb->AdmaLengthMode = SdMmcAdmaLen26b;\r
+      }\r
       Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
       if (EFI_ERROR (Status)) {\r
         PciIo->Unmap (PciIo, Trb->DataMap);\r
@@ -1719,11 +1763,18 @@ SdMmcFreeTrb (
       Trb->Adma32Desc\r
     );\r
   }\r
-  if (Trb->Adma64Desc != NULL) {\r
+  if (Trb->Adma64V3Desc != NULL) {\r
+    PciIo->FreeBuffer (\r
+      PciIo,\r
+      Trb->AdmaPages,\r
+      Trb->Adma64V3Desc\r
+    );\r
+  }\r
+  if (Trb->Adma64V4Desc != NULL) {\r
     PciIo->FreeBuffer (\r
       PciIo,\r
       Trb->AdmaPages,\r
-      Trb->Adma64Desc\r
+      Trb->Adma64V4Desc\r
     );\r
   }\r
   if (Trb->DataMap != NULL) {\r
@@ -1891,27 +1942,35 @@ SdMmcExecTrb (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
+                                 SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_64_ADDR_EN);\r
+    if (!EFI_ERROR (Status)) {\r
+      AddressingMode64 = TRUE;\r
+    }\r
+  }\r
+\r
   //\r
   // Set Host Control 1 register DMA Select field\r
   //\r
-  if (Trb->Mode == SdMmcAdmaMode) {\r
+  if ((Trb->Mode == SdMmcAdma32bMode) ||\r
+      (Trb->Mode == SdMmcAdma64bV4Mode)) {\r
     HostCtrl1 = BIT4;\r
     Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+  } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+    HostCtrl1 = BIT4|BIT3;\r
+    Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);\r
 \r
-  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
-    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
-                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
-    if (!EFI_ERROR (Status)) {\r
-      AddressingMode64 = TRUE;\r
-    }\r
-  }\r
-\r
   if (Trb->Mode == SdMmcSdmaMode) {\r
     if ((!AddressingMode64) &&\r
         ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {\r
@@ -1929,7 +1988,9 @@ SdMmcExecTrb (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-  } else if (Trb->Mode == SdMmcAdmaMode) {\r
+  } else if ((Trb->Mode == SdMmcAdma32bMode) ||\r
+             (Trb->Mode == SdMmcAdma64bV3Mode) ||\r
+             (Trb->Mode == SdMmcAdma64bV4Mode)) {\r
     AdmaAddr = (UINT64)(UINTN)Trb->AdmaDescPhy;\r
     Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);\r
     if (EFI_ERROR (Status)) {\r