diff mbox series

[edk2,v4,2/2] MdeModulePkg/SdMmcPciHcDxe: allow HC capabilities to be overridden

Message ID 20171207224322.20362-3-ard.biesheuvel@linaro.org
State Accepted
Commit b23fc39cd3c32663a0fa5ae11676e4ad4a2dddf9
Headers show
Series quirks handling for SDHCI controllers | expand

Commit Message

Ard Biesheuvel Dec. 7, 2017, 10:43 p.m. UTC
Invoke the newly introduced SD/MMC override protocol to override
the capabilities register after reading it from the device registers,
and to call the pre/post host init and reset hooks at the appropriate
times.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c   | 35 +++++++-
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h   | 36 ++++++++
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf |  2 +
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c     | 95 ++++++++++++++++++--
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h     | 35 --------
 5 files changed, 157 insertions(+), 46 deletions(-)

-- 
2.11.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox series

Patch

diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
index 0be8828abfcc..f923930bbae9 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
@@ -17,6 +17,8 @@ 
 
 #include "SdMmcPciHcDxe.h"
 
+EDKII_SD_MMC_OVERRIDE           *mOverride;
+
 //
 // Driver Global Variables
 //
@@ -281,14 +283,14 @@  SdMmcPciHcEnumerateDevice (
         //
         // Reset the specified slot of the SD/MMC Pci Host Controller
         //
-        Status = SdMmcHcReset (Private->PciIo, Slot);
+        Status = SdMmcHcReset (Private, Slot);
         if (EFI_ERROR (Status)) {
           continue;
         }
         //
         // Reinitialize slot and restart identification process for the new attached device
         //
-        Status = SdMmcHcInitHost (Private->PciIo, Slot, Private->Capability[Slot]);
+        Status = SdMmcHcInitHost (Private, Slot);
         if (EFI_ERROR (Status)) {
           continue;
         }
@@ -601,6 +603,20 @@  SdMmcPciHcDriverBindingStart (
     goto Done;
   }
 
+  //
+  // Attempt to locate the singleton instance of the SD/MMC override protocol,
+  // which implements platform specific workarounds for non-standard SDHCI
+  // implementations.
+  //
+  if (mOverride == NULL) {
+    Status = gBS->LocateProtocol (&gEdkiiSdMmcOverrideProtocolGuid, NULL,
+                    (VOID **)&mOverride);
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "%a: found SD/MMC override protocol\n",
+        __FUNCTION__));
+    }
+  }
+
   Support64BitDma = TRUE;
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
     Private->Slot[Slot].Enable = TRUE;
@@ -609,6 +625,17 @@  SdMmcPciHcDriverBindingStart (
     if (EFI_ERROR (Status)) {
       continue;
     }
+    if (mOverride != NULL && mOverride->Capability != NULL) {
+      Status = mOverride->Capability (
+                            Controller,
+                            Slot,
+                            &Private->Capability[Slot]);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
+          __FUNCTION__, Status));
+        continue;
+      }
+    }
     DumpCapabilityReg (Slot, &Private->Capability[Slot]);
 
     Support64BitDma &= Private->Capability[Slot].SysBus64;
@@ -627,7 +654,7 @@  SdMmcPciHcDriverBindingStart (
     //
     // Reset the specified slot of the SD/MMC Pci Host Controller
     //
-    Status = SdMmcHcReset (PciIo, Slot);
+    Status = SdMmcHcReset (Private, Slot);
     if (EFI_ERROR (Status)) {
       continue;
     }
@@ -642,7 +669,7 @@  SdMmcPciHcDriverBindingStart (
       continue;
     }
 
-    Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]);
+    Status = SdMmcHcInitHost (Private, Slot);
     if (EFI_ERROR (Status)) {
       continue;
     }
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
index 6a2a27969936..c683600f2ef2 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
@@ -35,6 +35,7 @@  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/DriverBinding.h>
 #include <Protocol/ComponentName.h>
 #include <Protocol/ComponentName2.h>
+#include <Protocol/SdMmcOverride.h>
 #include <Protocol/SdMmcPassThru.h>
 
 #include "SdMmcPciHci.h"
@@ -43,6 +44,8 @@  extern EFI_COMPONENT_NAME_PROTOCOL  gSdMmcPciHcComponentName;
 extern EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciHcComponentName2;
 extern EFI_DRIVER_BINDING_PROTOCOL  gSdMmcPciHcDriverBinding;
 
+extern EDKII_SD_MMC_OVERRIDE        *mOverride;
+
 #define SD_MMC_HC_PRIVATE_SIGNATURE  SIGNATURE_32 ('s', 'd', 't', 'f')
 
 #define SD_MMC_HC_PRIVATE_FROM_THIS(a) \
@@ -782,4 +785,37 @@  SdCardIdentification (
   IN UINT8                              Slot
   );
 
+/**
+  Software reset the specified SD/MMC host controller.
+
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
+  @param[in] Slot           The slot number of the SD card to send the command to.
+
+  @retval EFI_SUCCESS       The software reset executes successfully.
+  @retval Others            The software reset fails.
+
+**/
+EFI_STATUS
+SdMmcHcReset (
+  IN SD_MMC_HC_PRIVATE_DATA *Private,
+  IN UINT8                  Slot
+  );
+
+/**
+  Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
+  at initialization.
+
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
+  @param[in] Slot           The slot number of the SD card to send the command to.
+
+  @retval EFI_SUCCESS       The host controller is initialized successfully.
+  @retval Others            The host controller isn't initialized successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitHost (
+  IN SD_MMC_HC_PRIVATE_DATA *Private,
+  IN UINT8                  Slot
+  );
+
 #endif
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
index e26e6a098c17..154ce45d8223 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
@@ -48,6 +48,7 @@  [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
 
 [LibraryClasses]
   DevicePathLib
@@ -61,6 +62,7 @@  [LibraryClasses]
   DebugLib
 
 [Protocols]
+  gEdkiiSdMmcOverrideProtocolGuid               ## SOMETIMES_CONSUMES
   gEfiDevicePathProtocolGuid                    ## TO_START
   gEfiPciIoProtocolGuid                         ## TO_START
   gEfiSdMmcPassThruProtocolGuid                 ## BY_START
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
index aa75aa8d2434..385a50b12079 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
@@ -419,7 +419,7 @@  SdMmcHcWaitMmioSet (
 /**
   Software reset the specified SD/MMC host controller and enable all interrupts.
 
-  @param[in] PciIo          The PCI IO protocol instance.
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
   @param[in] Slot           The slot number of the SD card to send the command to.
 
   @retval EFI_SUCCESS       The software reset executes successfully.
@@ -428,13 +428,32 @@  SdMmcHcWaitMmioSet (
 **/
 EFI_STATUS
 SdMmcHcReset (
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN SD_MMC_HC_PRIVATE_DATA *Private,
   IN UINT8                  Slot
   )
 {
   EFI_STATUS                Status;
   UINT8                     SwReset;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+
+  //
+  // Notify the SD/MMC override protocol that we are about to reset
+  // the SD/MMC host controller.
+  //
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          Private->ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcResetPre);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC pre reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+      return Status;
+    }
+  }
 
+  PciIo   = Private->PciIo;
   SwReset = 0xFF;
   Status  = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
 
@@ -456,10 +475,32 @@  SdMmcHcReset (
     DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));
     return Status;
   }
+
   //
   // Enable all interrupt after reset all.
   //
   Status = SdMmcHcEnableInterrupt (PciIo, Slot);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",
+      Status));
+    return Status;
+  }
+
+  //
+  // Notify the SD/MMC override protocol that we have just reset
+  // the SD/MMC host controller.
+  //
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          Private->ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcResetPost);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }
 
   return Status;
 }
@@ -1021,7 +1062,7 @@  SdMmcHcInitTimeoutCtrl (
   Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
   at initialization.
 
-  @param[in] PciIo          The PCI IO protocol instance.
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] Capability     The capability of the slot.
 
@@ -1031,12 +1072,33 @@  SdMmcHcInitTimeoutCtrl (
 **/
 EFI_STATUS
 SdMmcHcInitHost (
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,
-  IN UINT8                  Slot,
-  IN SD_MMC_HC_SLOT_CAP     Capability
+  IN SD_MMC_HC_PRIVATE_DATA *Private,
+  IN UINT8                  Slot
   )
 {
-  EFI_STATUS       Status;
+  EFI_STATUS                Status;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  SD_MMC_HC_SLOT_CAP        Capability;
+
+  //
+  // Notify the SD/MMC override protocol that we are about to initialize
+  // the SD/MMC host controller.
+  //
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          Private->ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcInitHostPre);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC pre init notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+      return Status;
+    }
+  }
+
+  PciIo = Private->PciIo;
+  Capability = Private->Capability[Slot];
 
   Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
   if (EFI_ERROR (Status)) {
@@ -1049,6 +1111,25 @@  SdMmcHcInitHost (
   }
 
   Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Notify the SD/MMC override protocol that we are have just initialized
+  // the SD/MMC host controller.
+  //
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          Private->ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcInitHostPost);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post init notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }
   return Status;
 }
 
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index fb627586022c..e389d52184f4 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
@@ -298,22 +298,6 @@  SdMmcHcWaitMmioSet (
   );
 
 /**
-  Software reset the specified SD/MMC host controller.
-
-  @param[in] PciIo          The PCI IO protocol instance.
-  @param[in] Slot           The slot number of the SD card to send the command to.
-
-  @retval EFI_SUCCESS       The software reset executes successfully.
-  @retval Others            The software reset fails.
-
-**/
-EFI_STATUS
-SdMmcHcReset (
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,
-  IN UINT8                  Slot
-  );
-
-/**
   Set all interrupt status bits in Normal and Error Interrupt Status Enable
   register.
 
@@ -524,23 +508,4 @@  SdMmcHcInitTimeoutCtrl (
   IN UINT8                  Slot
   );
 
-/**
-  Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
-  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 host controller is initialized successfully.
-  @retval Others            The host controller isn't initialized successfully.
-
-**/
-EFI_STATUS
-SdMmcHcInitHost (
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,
-  IN UINT8                  Slot,
-  IN SD_MMC_HC_SLOT_CAP     Capability
-  );
-
 #endif