]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
MdeModulePkg/SdMmcPciHcDxe: Update comment for spec compliance status
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHcDxe.c
index ed6b557347ead7fe7735eeabb92a829f521bb469..b474f8decdb40aacc72a8dc737906337c2ec1cfa 100644 (file)
@@ -1,10 +1,13 @@
 /** @file\r
   This driver is used to manage SD/MMC PCI host controllers which are compliance\r
-  with SD Host Controller Simplified Specification version 3.00.\r
+  with SD Host Controller Simplified Specification version 3.00 plus the 64-bit\r
+  System Addressing support in SD Host Controller Simplified Specification version\r
+  4.20.\r
 \r
   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.\r
 \r
-  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2018, 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
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -17,6 +20,8 @@
 \r
 #include "SdMmcPciHcDxe.h"\r
 \r
+EDKII_SD_MMC_OVERRIDE           *mOverride;\r
+\r
 //\r
 // Driver Global Variables\r
 //\r
@@ -60,7 +65,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
   {                                 // MaxCurrent\r
     0,\r
   },\r
-  0                                 // ControllerVersion\r
+  {\r
+    0                               // ControllerVersion\r
+  }\r
 };\r
 \r
 SD_DEVICE_PATH    mSdDpTemplate = {\r
@@ -197,7 +204,7 @@ Done:
       Trb->Packet->TransactionStatus = EFI_TIMEOUT;\r
       TrbEvent = Trb->Event;\r
       SdMmcFreeTrb (Trb);\r
-      DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
+      DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
       gBS->SignalEvent (TrbEvent);\r
       return;\r
     }\r
@@ -207,7 +214,7 @@ Done:
     Trb->Packet->TransactionStatus = Status;\r
     TrbEvent = Trb->Event;\r
     SdMmcFreeTrb (Trb);\r
-    DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
+    DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
     gBS->SignalEvent (TrbEvent);\r
   }\r
   return;\r
@@ -238,6 +245,7 @@ SdMmcPciHcEnumerateDevice (
   LIST_ENTRY                          *Link;\r
   LIST_ENTRY                          *NextLink;\r
   SD_MMC_HC_TRB                       *Trb;\r
+  EFI_TPL                             OldTpl;\r
 \r
   Private = (SD_MMC_HC_PRIVATE_DATA*)Context;\r
 \r
@@ -245,12 +253,13 @@ SdMmcPciHcEnumerateDevice (
     if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {\r
       Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);\r
       if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {\r
-        DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+        DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
         Private->Slot[Slot].MediaPresent = FALSE;\r
         Private->Slot[Slot].Initialized  = FALSE;\r
         //\r
         // Signal all async task events at the slot with EFI_NO_MEDIA status.\r
         //\r
+        OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
         for (Link = GetFirstNode (&Private->Queue);\r
              !IsNull (&Private->Queue, Link);\r
              Link = NextLink) {\r
@@ -263,6 +272,7 @@ SdMmcPciHcEnumerateDevice (
             SdMmcFreeTrb (Trb);\r
           }\r
         }\r
+        gBS->RestoreTPL (OldTpl);\r
         //\r
         // Notify the upper layer the connect state change through ReinstallProtocolInterface.\r
         //\r
@@ -274,18 +284,18 @@ SdMmcPciHcEnumerateDevice (
               );\r
       }\r
       if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {\r
-        DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+        DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
         //\r
         // Reset the specified slot of the SD/MMC Pci Host Controller\r
         //\r
-        Status = SdMmcHcReset (Private->PciIo, Slot);\r
+        Status = SdMmcHcReset (Private, Slot);\r
         if (EFI_ERROR (Status)) {\r
           continue;\r
         }\r
         //\r
         // Reinitialize slot and restart identification process for the new attached device\r
         //\r
-        Status = SdMmcHcInitHost (Private->PciIo, Slot, Private->Capability[Slot]);\r
+        Status = SdMmcHcInitHost (Private, Slot);\r
         if (EFI_ERROR (Status)) {\r
           continue;\r
         }\r
@@ -524,8 +534,9 @@ SdMmcPciHcDriverBindingStart (
   CARD_TYPE_DETECT_ROUTINE        *Routine;\r
   UINT32                          RoutineNum;\r
   BOOLEAN                         MediaPresent;\r
+  BOOLEAN                         Support64BitDma;\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
 \r
   //\r
   // Open PCI I/O Protocol and save pointer to open protocol\r
@@ -597,14 +608,68 @@ SdMmcPciHcDriverBindingStart (
     goto Done;\r
   }\r
 \r
+  //\r
+  // Attempt to locate the singleton instance of the SD/MMC override protocol,\r
+  // which implements platform specific workarounds for non-standard SDHCI\r
+  // implementations.\r
+  //\r
+  if (mOverride == NULL) {\r
+    Status = gBS->LocateProtocol (&gEdkiiSdMmcOverrideProtocolGuid, NULL,\r
+                    (VOID **)&mOverride);\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_INFO, "%a: found SD/MMC override protocol\n",\r
+        __FUNCTION__));\r
+    }\r
+  }\r
+\r
+  Support64BitDma = TRUE;\r
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {\r
     Private->Slot[Slot].Enable = TRUE;\r
 \r
+    //\r
+    // Get SD/MMC Pci Host Controller Version\r
+    //\r
+    Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
     Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
+\r
+    Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;\r
+\r
+    if (mOverride != NULL && mOverride->Capability != NULL) {\r
+      Status = mOverride->Capability (\r
+                            Controller,\r
+                            Slot,\r
+                            &Private->Capability[Slot],\r
+                            &Private->BaseClkFreq[Slot]\r
+                            );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",\r
+          __FUNCTION__, Status));\r
+        continue;\r
+      }\r
+    }\r
     DumpCapabilityReg (Slot, &Private->Capability[Slot]);\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "Slot[%d] Base Clock Frequency: %dMHz\n",\r
+      Slot,\r
+      Private->BaseClkFreq[Slot]\r
+      ));\r
+\r
+    //\r
+    // If any of the slots does not support 64b system bus\r
+    // do not enable 64b DMA in the PCI layer.\r
+    //\r
+    if (Private->Capability[Slot].SysBus64V3 == 0 &&\r
+        Private->Capability[Slot].SysBus64V4 == 0) {\r
+      Support64BitDma = FALSE;\r
+    }\r
 \r
     Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);\r
     if (EFI_ERROR (Status)) {\r
@@ -613,29 +678,35 @@ SdMmcPciHcDriverBindingStart (
 \r
     Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;\r
     if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {\r
-      DEBUG ((EFI_D_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
+      DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
       continue;\r
     }\r
 \r
     //\r
     // Reset the specified slot of the SD/MMC Pci Host Controller\r
     //\r
-    Status = SdMmcHcReset (PciIo, Slot);\r
+    Status = SdMmcHcReset (Private, Slot);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
     //\r
     // Check whether there is a SD/MMC card attached\r
     //\r
-    Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);\r
-    if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {\r
-      continue;\r
-    } else if (!MediaPresent) {\r
-      DEBUG ((EFI_D_ERROR, "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n", Slot));\r
-      continue;\r
+    if (Private->Slot[Slot].SlotType == RemovableSlot) {\r
+      Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);\r
+      if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {\r
+        continue;\r
+      } else if (!MediaPresent) {\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n",\r
+          Slot\r
+          ));\r
+        continue;\r
+      }\r
     }\r
 \r
-    Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]);\r
+    Status = SdMmcHcInitHost (Private, Slot);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
@@ -660,12 +731,28 @@ SdMmcPciHcDriverBindingStart (
     }\r
   }\r
 \r
+  //\r
+  // Enable 64-bit DMA support in the PCI layer if this controller\r
+  // supports it.\r
+  //\r
+  if (Support64BitDma) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+                      NULL\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));\r
+    }\r
+  }\r
+\r
   //\r
   // Start the asynchronous I/O monitor\r
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   ProcessAsyncTaskList,\r
                   Private,\r
                   &Private->TimerEvent\r
@@ -705,7 +792,7 @@ SdMmcPciHcDriverBindingStart (
                   NULL\r
                   );\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
 \r
 Done:\r
   if (EFI_ERROR (Status)) {\r
@@ -786,7 +873,7 @@ SdMmcPciHcDriverBindingStop (
   LIST_ENTRY                          *NextLink;\r
   SD_MMC_HC_TRB                       *Trb;\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
 \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
@@ -860,7 +947,7 @@ SdMmcPciHcDriverBindingStop (
 \r
   FreePool (Private);\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
 \r
   return Status;\r
 }\r
@@ -961,7 +1048,7 @@ SdMmcPassThruPassThru (
   // Wait async I/O list is empty before execute sync I/O operation.\r
   //\r
   while (TRUE) {\r
-    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
     if (IsListEmpty (&Private->Queue)) {\r
       gBS->RestoreTPL (OldTpl);\r
       break;\r
@@ -985,13 +1072,7 @@ SdMmcPassThruPassThru (
   }\r
 \r
 Done:\r
-  if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {\r
-    FreePages (Trb->AdmaDesc, Trb->AdmaPages);\r
-  }\r
-\r
-  if (Trb != NULL) {\r
-    FreePool (Trb);\r
-  }\r
+  SdMmcFreeTrb (Trb);\r
 \r
   return Status;\r
 }\r
@@ -1273,7 +1354,7 @@ SdMmcPassThruResetDevice (
   //\r
   // Free all async I/O requests in the queue\r
   //\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
   for (Link = GetFirstNode (&Private->Queue);\r
        !IsNull (&Private->Queue, Link);\r