MdeModulePkg/SdMmcPciHcDxe: allow HC capabilities to be overridden
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 7 Dec 2017 22:43:22 +0000 (22:43 +0000)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 30 Jan 2018 09:25:13 +0000 (09:25 +0000)
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>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h

index 0be8828..f923930 100644 (file)
@@ -17,6 +17,8 @@
 \r
 #include "SdMmcPciHcDxe.h"\r
 \r
+EDKII_SD_MMC_OVERRIDE           *mOverride;\r
+\r
 //\r
 // Driver Global Variables\r
 //\r
@@ -281,14 +283,14 @@ SdMmcPciHcEnumerateDevice (
         //\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
@@ -601,6 +603,20 @@ 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
@@ -609,6 +625,17 @@ SdMmcPciHcDriverBindingStart (
     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
+    }\r
     DumpCapabilityReg (Slot, &Private->Capability[Slot]);\r
 \r
     Support64BitDma &= Private->Capability[Slot].SysBus64;\r
@@ -627,7 +654,7 @@ SdMmcPciHcDriverBindingStart (
     //\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
@@ -642,7 +669,7 @@ SdMmcPciHcDriverBindingStart (
       continue;\r
     }\r
 \r
-    Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]);\r
+    Status = SdMmcHcInitHost (Private, Slot);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
index 6a2a279..c683600 100644 (file)
@@ -35,6 +35,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/DriverBinding.h>\r
 #include <Protocol/ComponentName.h>\r
 #include <Protocol/ComponentName2.h>\r
+#include <Protocol/SdMmcOverride.h>\r
 #include <Protocol/SdMmcPassThru.h>\r
 \r
 #include "SdMmcPciHci.h"\r
@@ -43,6 +44,8 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gSdMmcPciHcComponentName;
 extern EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciHcComponentName2;\r
 extern EFI_DRIVER_BINDING_PROTOCOL  gSdMmcPciHcDriverBinding;\r
 \r
+extern EDKII_SD_MMC_OVERRIDE        *mOverride;\r
+\r
 #define SD_MMC_HC_PRIVATE_SIGNATURE  SIGNATURE_32 ('s', 'd', 't', 'f')\r
 \r
 #define SD_MMC_HC_PRIVATE_FROM_THIS(a) \\r
@@ -782,4 +785,37 @@ SdCardIdentification (
   IN UINT8                              Slot\r
   );\r
 \r
+/**\r
+  Software reset the specified SD/MMC host controller.\r
+\r
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Slot           The slot number of the SD card to send the command to.\r
+\r
+  @retval EFI_SUCCESS       The software reset executes successfully.\r
+  @retval Others            The software reset fails.\r
+\r
+**/\r
+EFI_STATUS\r
+SdMmcHcReset (\r
+  IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+  IN UINT8                  Slot\r
+  );\r
+\r
+/**\r
+  Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value\r
+  at initialization.\r
+\r
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Slot           The slot number of the SD card to send the command to.\r
+\r
+  @retval EFI_SUCCESS       The host controller is initialized successfully.\r
+  @retval Others            The host controller isn't initialized successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdMmcHcInitHost (\r
+  IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+  IN UINT8                  Slot\r
+  );\r
+\r
 #endif\r
index e26e6a0..154ce45 100644 (file)
@@ -48,6 +48,7 @@
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
 \r
 [LibraryClasses]\r
   DevicePathLib\r
@@ -61,6 +62,7 @@
   DebugLib\r
 \r
 [Protocols]\r
+  gEdkiiSdMmcOverrideProtocolGuid               ## SOMETIMES_CONSUMES\r
   gEfiDevicePathProtocolGuid                    ## TO_START\r
   gEfiPciIoProtocolGuid                         ## TO_START\r
   gEfiSdMmcPassThruProtocolGuid                 ## BY_START\r
index aa75aa8..9672b5b 100644 (file)
@@ -419,7 +419,7 @@ SdMmcHcWaitMmioSet (
 /**\r
   Software reset the specified SD/MMC host controller and enable all interrupts.\r
 \r
-  @param[in] PciIo          The PCI IO protocol instance.\r
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
   @param[in] Slot           The slot number of the SD card to send the command to.\r
 \r
   @retval EFI_SUCCESS       The software reset executes successfully.\r
@@ -428,13 +428,32 @@ SdMmcHcWaitMmioSet (
 **/\r
 EFI_STATUS\r
 SdMmcHcReset (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
+  IN SD_MMC_HC_PRIVATE_DATA *Private,\r
   IN UINT8                  Slot\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   UINT8                     SwReset;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+\r
+  //\r
+  // Notify the SD/MMC override protocol that we are about to reset\r
+  // the SD/MMC host controller.\r
+  //\r
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcResetPre);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a: SD/MMC pre reset notifier callback failed - %r\n",\r
+        __FUNCTION__, Status));\r
+      return Status;\r
+    }\r
+  }\r
 \r
+  PciIo   = Private->PciIo;\r
   SwReset = 0xFF;\r
   Status  = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);\r
 \r
@@ -456,10 +475,32 @@ SdMmcHcReset (
     DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));\r
     return Status;\r
   }\r
+\r
   //\r
   // Enable all interrupt after reset all.\r
   //\r
   Status = SdMmcHcEnableInterrupt (PciIo, Slot);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",\r
+      Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Notify the SD/MMC override protocol that we have just reset\r
+  // the SD/MMC host controller.\r
+  //\r
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcResetPost);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a: SD/MMC post reset notifier callback failed - %r\n",\r
+        __FUNCTION__, Status));\r
+    }\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -1021,9 +1062,8 @@ SdMmcHcInitTimeoutCtrl (
   Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value\r
   at initialization.\r
 \r
-  @param[in] PciIo          The PCI IO protocol instance.\r
+  @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
   @param[in] Slot           The slot number of the SD card to send the command to.\r
-  @param[in] Capability     The capability of the slot.\r
 \r
   @retval EFI_SUCCESS       The host controller is initialized successfully.\r
   @retval Others            The host controller isn't initialized successfully.\r
@@ -1031,12 +1071,33 @@ SdMmcHcInitTimeoutCtrl (
 **/\r
 EFI_STATUS\r
 SdMmcHcInitHost (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN SD_MMC_HC_SLOT_CAP     Capability\r
+  IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+  IN UINT8                  Slot\r
   )\r
 {\r
-  EFI_STATUS       Status;\r
+  EFI_STATUS                Status;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+  SD_MMC_HC_SLOT_CAP        Capability;\r
+\r
+  //\r
+  // Notify the SD/MMC override protocol that we are about to initialize\r
+  // the SD/MMC host controller.\r
+  //\r
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcInitHostPre);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a: SD/MMC pre init notifier callback failed - %r\n",\r
+        __FUNCTION__, Status));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  PciIo = Private->PciIo;\r
+  Capability = Private->Capability[Slot];\r
 \r
   Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);\r
   if (EFI_ERROR (Status)) {\r
@@ -1049,6 +1110,25 @@ SdMmcHcInitHost (
   }\r
 \r
   Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Notify the SD/MMC override protocol that we are have just initialized\r
+  // the SD/MMC host controller.\r
+  //\r
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcInitHostPost);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a: SD/MMC post init notifier callback failed - %r\n",\r
+        __FUNCTION__, Status));\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
index fb62758..e389d52 100644 (file)
@@ -297,22 +297,6 @@ SdMmcHcWaitMmioSet (
   IN  UINT64                    Timeout\r
   );\r
 \r
-/**\r
-  Software reset the specified SD/MMC host controller.\r
-\r
-  @param[in] PciIo          The PCI IO protocol instance.\r
-  @param[in] Slot           The slot number of the SD card to send the command to.\r
-\r
-  @retval EFI_SUCCESS       The software reset executes successfully.\r
-  @retval Others            The software reset fails.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcReset (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot\r
-  );\r
-\r
 /**\r
   Set all interrupt status bits in Normal and Error Interrupt Status Enable\r
   register.\r
@@ -524,23 +508,4 @@ SdMmcHcInitTimeoutCtrl (
   IN UINT8                  Slot\r
   );\r
 \r
-/**\r
-  Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value\r
-  at initialization.\r
-\r
-  @param[in] PciIo          The PCI IO protocol instance.\r
-  @param[in] Slot           The slot number of the SD card to send the command to.\r
-  @param[in] Capability     The capability of the slot.\r
-\r
-  @retval EFI_SUCCESS       The host controller is initialized successfully.\r
-  @retval Others            The host controller isn't initialized successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcInitHost (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN SD_MMC_HC_SLOT_CAP     Capability\r
-  );\r
-\r
 #endif\r