]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
MdeModulePkg/SdMmcPciHcDxe: Send SEND_STATUS at lower frequency
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHcDxe.c
index bf9869dbb5f055d53bb16e0bbe9ebb3227072dfa..57f4cf329a1adcc42eaa706f61a7448426a71a71 100644 (file)
@@ -1,17 +1,14 @@
 /** @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
-  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
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\r
+  Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -31,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciHcDriverBinding = {
   NULL\r
 };\r
 \r
+#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, 0, \\r
+                               {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\\r
+                               EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\\r
+                               {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}\r
+\r
 //\r
 // Template for SD/MMC host controller private data.\r
 //\r
@@ -53,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
                                     // Queue\r
   INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),\r
   {                                 // Slot\r
-    {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0},\r
-    {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}\r
+    SLOT_INIT_TEMPLATE,\r
+    SLOT_INIT_TEMPLATE,\r
+    SLOT_INIT_TEMPLATE,\r
+    SLOT_INIT_TEMPLATE,\r
+    SLOT_INIT_TEMPLATE,\r
+    SLOT_INIT_TEMPLATE\r
   },\r
   {                                 // Capability\r
     {0},\r
@@ -62,7 +68,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
@@ -203,8 +211,10 @@ Done:
       gBS->SignalEvent (TrbEvent);\r
       return;\r
     }\r
-  }\r
-  if ((Trb != NULL) && (Status != EFI_NOT_READY)) {\r
+  } else if ((Trb != NULL) && (Status == EFI_CRC_ERROR) && (Trb->Retries > 0)) {\r
+    Trb->Retries--;\r
+    Trb->Started = FALSE;\r
+  } else if ((Trb != NULL)) {\r
     RemoveEntryList (Link);\r
     Trb->Packet->TransactionStatus = Status;\r
     TrbEvent = Trb->Event;\r
@@ -329,6 +339,7 @@ SdMmcPciHcEnumerateDevice (
 \r
   return;\r
 }\r
+\r
 /**\r
   Tests to see if this driver supports a given controller. If a child device is provided,\r
   it further tests to see if this driver supports creating a handle for the specified child device.\r
@@ -620,25 +631,69 @@ SdMmcPciHcDriverBindingStart (
   Support64BitDma = TRUE;\r
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {\r
     Private->Slot[Slot].Enable = TRUE;\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
-    if (mOverride != NULL && mOverride->Capability != NULL) {\r
-      Status = mOverride->Capability (\r
-                            Controller,\r
-                            Slot,\r
-                            &Private->Capability[Slot]);\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",\r
-          __FUNCTION__, Status));\r
-        continue;\r
+\r
+    Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;\r
+\r
+    if (mOverride != NULL) {\r
+      if (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
+\r
+      if (mOverride->NotifyPhase != NULL) {\r
+        Status = mOverride->NotifyPhase (\r
+                              Controller,\r
+                              Slot,\r
+                              EdkiiSdMmcGetOperatingParam,\r
+                              (VOID*)&Private->Slot[Slot].OperatingParameters\r
+                              );\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using defaults\n", __FUNCTION__));\r
+        }\r
       }\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
-    Support64BitDma &= Private->Capability[Slot].SysBus64;\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->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300 &&\r
+         Private->Capability[Slot].SysBus64V3 == 0) ||\r
+        (Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400 &&\r
+         Private->Capability[Slot].SysBus64V3 == 0) ||\r
+        (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410 &&\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
@@ -921,6 +976,58 @@ SdMmcPciHcDriverBindingStop (
   return Status;\r
 }\r
 \r
+/**\r
+  Execute TRB synchronously.\r
+\r
+  @param[in] Private  Pointer to driver private data.\r
+  @param[in] Trb      Pointer to TRB to execute.\r
+\r
+  @retval EFI_SUCCESS  TRB executed successfully.\r
+  @retval Other        TRB failed.\r
+**/\r
+EFI_STATUS\r
+SdMmcPassThruExecSyncTrb (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_TPL     OldTpl;\r
+\r
+  //\r
+  // Wait async I/O list is empty before execute sync I/O operation.\r
+  //\r
+  while (TRUE) {\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    if (IsListEmpty (&Private->Queue)) {\r
+      gBS->RestoreTPL (OldTpl);\r
+      break;\r
+    }\r
+    gBS->RestoreTPL (OldTpl);\r
+  }\r
+\r
+  while (Trb->Retries) {\r
+    Status = SdMmcWaitTrbEnv (Private, Trb);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = SdMmcExecTrb (Private, Trb);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = SdMmcWaitTrbResult (Private, Trb);\r
+    if (Status == EFI_CRC_ERROR) {\r
+      Trb->Retries--;\r
+    } else {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Sends SD command to an SD card that is attached to the SD controller.\r
 \r
@@ -970,7 +1077,6 @@ SdMmcPassThruPassThru (
   EFI_STATUS                      Status;\r
   SD_MMC_HC_PRIVATE_DATA          *Private;\r
   SD_MMC_HC_TRB                   *Trb;\r
-  EFI_TPL                         OldTpl;\r
 \r
   if ((This == NULL) || (Packet == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1013,34 +1119,8 @@ SdMmcPassThruPassThru (
     return EFI_SUCCESS;\r
   }\r
 \r
-  //\r
-  // Wait async I/O list is empty before execute sync I/O operation.\r
-  //\r
-  while (TRUE) {\r
-    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-    if (IsListEmpty (&Private->Queue)) {\r
-      gBS->RestoreTPL (OldTpl);\r
-      break;\r
-    }\r
-    gBS->RestoreTPL (OldTpl);\r
-  }\r
-\r
-  Status = SdMmcWaitTrbEnv (Private, Trb);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
-\r
-  Status = SdMmcExecTrb (Private, Trb);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
+  Status = SdMmcPassThruExecSyncTrb (Private, Trb);\r
 \r
-  Status = SdMmcWaitTrbResult (Private, Trb);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
-\r
-Done:\r
   SdMmcFreeTrb (Trb);\r
 \r
   return Status;\r