]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/SdMmcPciHcDxe: Hook SwitchClockFreq after SD clock start
authorAlbecki, Mateusz <mateusz.albecki@intel.com>
Fri, 20 Dec 2019 17:13:11 +0000 (01:13 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 6 Jan 2020 06:07:30 +0000 (06:07 +0000)
For eMMC modules we used to notify the platform about frequency
change only after sending CMD13 which meant that platform
might not get a chance to apply required post frequency
change fixes to get the clock stable. To fix this
notification has been moved to SdMmcHcClockSupply function
just after we start the SD clock. During first time setup
the notification won't be sent to avoid changing old behavior.

Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Marcin Wojtas <mw@semihalf.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Mateusz Albecki <mateusz.albecki@intel.com>
Tested-by: Marcin Wojtas <mw@semihalf.com>
Tested-by: Hao A Wu <hao.a.wu@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h

index 082904ccc5df5b7d3b220653480a8e2ecb5ee55b..776c0e796c56cbd6bf4f1babc5d2e273dcde1261 100644 (file)
@@ -727,7 +727,7 @@ EmmcSwitchBusTiming (
   //\r
   // Convert the clock freq unit from MHz to KHz.\r
   //\r
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+  Status = SdMmcHcClockSupply (Private, Slot, BusTiming, FALSE, ClockFreq * 1000);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -745,24 +745,6 @@ EmmcSwitchBusTiming (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
-    Status = mOverride->NotifyPhase (\r
-                          Private->ControllerHandle,\r
-                          Slot,\r
-                          EdkiiSdMmcSwitchClockFreqPost,\r
-                          &BusTiming\r
-                          );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((\r
-        DEBUG_ERROR,\r
-        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
-        __FUNCTION__,\r
-        Status\r
-        ));\r
-      return Status;\r
-    }\r
-  }\r
-\r
   return Status;\r
 }\r
 \r
index 336baade9e58070c140395500c5cc9cbac77900e..d63dc54e8c3a02e21215978c57672e37c6a450f3 100644 (file)
@@ -1145,29 +1145,11 @@ SdCardSetBusMode (
     return Status;\r
   }\r
 \r
-  Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+  Status = SdMmcHcClockSupply (Private, Slot, BusMode.BusTiming, FALSE, BusMode.ClockFreq * 1000);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
-    Status = mOverride->NotifyPhase (\r
-                          Private->ControllerHandle,\r
-                          Slot,\r
-                          EdkiiSdMmcSwitchClockFreqPost,\r
-                          &BusMode.BusTiming\r
-                          );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((\r
-        DEBUG_ERROR,\r
-        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
-        __FUNCTION__,\r
-        Status\r
-        ));\r
-      return Status;\r
-    }\r
-  }\r
-\r
   if ((BusMode.BusTiming == SdMmcUhsSdr104) || ((BusMode.BusTiming == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {\r
     Status = SdCardTuningClock (PciIo, PassThru, Slot);\r
     if (EFI_ERROR (Status)) {\r
@@ -1345,7 +1327,13 @@ SdCardIdentification (
         goto Error;\r
       }\r
 \r
-      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+      //\r
+      // Restart the clock with first time parameters.\r
+      // NOTE: it is not required to actually restart the clock\r
+      // and go through internal clock setup again. Some time\r
+      // could be saved if we simply started the SD clock.\r
+      //\r
+      SdMmcHcClockSupply (Private, Slot, 0, TRUE, 400);\r
 \r
       gBS->Stall (1000);\r
 \r
index c29e48767ec70b69ef162737e1cf48a63aabec4e..0304960132415b53137f8c862e31a4085850c8a3 100644 (file)
@@ -796,6 +796,30 @@ SdCardIdentification (
   IN UINT8                              Slot\r
   );\r
 \r
+/**\r
+  SD/MMC card clock supply.\r
+\r
+  Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\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
+  @param[in] BusTiming       BusTiming at which the frequency change is done.\r
+  @param[in] FirstTimeSetup  Flag to indicate whether the clock is being setup for the first time.\r
+  @param[in] ClockFreq       The max clock frequency to be set. The unit is KHz.\r
+\r
+  @retval EFI_SUCCESS       The clock is supplied successfully.\r
+  @retval Others            The clock isn't supplied successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdMmcHcClockSupply (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN UINT8                   Slot,\r
+  IN SD_MMC_BUS_MODE         BusTiming,\r
+  IN BOOLEAN                 FirstTimeSetup,\r
+  IN UINT64                  ClockFreq\r
+  );\r
+\r
 /**\r
   Software reset the specified SD/MMC host controller.\r
 \r
index b9d04e0f17a20d6212860f654b6d78f4eeaefcdb..f667264c5e7177d762c3e7eb06b38a46ccb105c1 100644 (file)
@@ -763,11 +763,11 @@ SdMmcHcStopClock (
 \r
   Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\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] ClockFreq      The max clock frequency to be set. The unit is KHz.\r
-  @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.\r
-  @param[in] ControllerVer  The version of host controller.\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] BusTiming       BusTiming at which the frequency change is done.\r
+  @param[in] FirstTimeSetup  Flag to indicate whether the clock is being setup for the first time.\r
+  @param[in] ClockFreq       The max clock frequency to be set. The unit is KHz.\r
 \r
   @retval EFI_SUCCESS       The clock is supplied successfully.\r
   @retval Others            The clock isn't supplied successfully.\r
@@ -775,11 +775,11 @@ SdMmcHcStopClock (
 **/\r
 EFI_STATUS\r
 SdMmcHcClockSupply (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN UINT64                 ClockFreq,\r
-  IN UINT32                 BaseClkFreq,\r
-  IN UINT16                 ControllerVer\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN UINT8                   Slot,\r
+  IN SD_MMC_BUS_MODE         BusTiming,\r
+  IN BOOLEAN                 FirstTimeSetup,\r
+  IN UINT64                  ClockFreq\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -787,13 +787,15 @@ SdMmcHcClockSupply (
   UINT32                    Divisor;\r
   UINT32                    Remainder;\r
   UINT16                    ClockCtrl;\r
+  UINT32                    BaseClkFreq;\r
+  UINT16                    ControllerVer;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
 \r
-  //\r
-  // Calculate a divisor for SD clock frequency\r
-  //\r
-  ASSERT (BaseClkFreq != 0);\r
+  PciIo = Private->PciIo;\r
+  BaseClkFreq = Private->BaseClkFreq[Slot];\r
+  ControllerVer = Private->ControllerVersion[Slot];\r
 \r
-  if (ClockFreq == 0) {\r
+  if (BaseClkFreq == 0 || ClockFreq == 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -883,6 +885,29 @@ SdMmcHcClockSupply (
   ClockCtrl = BIT2;\r
   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
 \r
+  //\r
+  // We don't notify the platform on first time setup to avoid changing\r
+  // legacy behavior. During first time setup we also don't know what type\r
+  // of the card slot it is and which enum value of BusTiming applies.\r
+  //\r
+  if (!FirstTimeSetup && mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcSwitchClockFreqPost,\r
+                          &BusTiming\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
+        __FUNCTION__,\r
+        Status\r
+        ));\r
+      return Status;\r
+    }\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1038,49 +1063,6 @@ SdMmcHcInitV4Enhancements (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Supply SD/MMC card with lowest clock frequency 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] BaseClkFreq    The base clock frequency of host controller in MHz.\r
-  @param[in] ControllerVer  The version of host controller.\r
-\r
-  @retval EFI_SUCCESS       The clock is supplied successfully.\r
-  @retval Others            The clock isn't supplied successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcInitClockFreq (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN UINT32                 BaseClkFreq,\r
-  IN UINT16                 ControllerVer\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  UINT32                    InitFreq;\r
-\r
-  //\r
-  // According to SDHCI specification ver. 4.2, BaseClkFreq field value of\r
-  // the Capability Register 1 can be zero, which means a need for obtaining\r
-  // the clock frequency via another method. Fail in case it is not updated\r
-  // by SW at this point.\r
-  //\r
-  if (BaseClkFreq == 0) {\r
-    //\r
-    // Don't support get Base Clock Frequency information via another method\r
-    //\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-  //\r
-  // Supply 400KHz clock frequency at initialization phase.\r
-  //\r
-  InitFreq = 400;\r
-  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);\r
-  return Status;\r
-}\r
-\r
 /**\r
   Supply SD/MMC card with maximum voltage at initialization.\r
 \r
@@ -1216,7 +1198,14 @@ SdMmcHcInitHost (
     return Status;\r
   }\r
 \r
-  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+  //\r
+  // Perform first time clock setup with 400 KHz frequency.\r
+  // We send the 0 as the BusTiming value because at this time\r
+  // we still do not know the slot type and which enum value will apply.\r
+  // Since it is a first time setup SdMmcHcClockSupply won't notify\r
+  // the platofrm driver anyway so it doesn't matter.\r
+  //\r
+  Status = SdMmcHcClockSupply (Private, Slot, 0, TRUE, 400);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
index 088c70451cd18ffcfaef5f574399cc1989f35b41..826e851b04536edfc5609f9dd35161c466df9f10 100644 (file)
@@ -478,30 +478,6 @@ SdMmcHcStopClock (
   IN UINT8                  Slot\r
   );\r
 \r
-/**\r
-  SD/MMC card clock supply.\r
-\r
-  Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\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] ClockFreq      The max clock frequency to be set. The unit is KHz.\r
-  @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.\r
-  @param[in] ControllerVer  The version of host controller.\r
-\r
-  @retval EFI_SUCCESS       The clock is supplied successfully.\r
-  @retval Others            The clock isn't supplied successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcClockSupply (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN UINT64                 ClockFreq,\r
-  IN UINT32                 BaseClkFreq,\r
-  IN UINT16                 ControllerVer\r
-  );\r
-\r
 /**\r
   SD/MMC bus power control.\r
 \r
@@ -542,26 +518,6 @@ SdMmcHcSetBusWidth (
   IN UINT16                 BusWidth\r
   );\r
 \r
-/**\r
-  Supply SD/MMC card with lowest clock frequency 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] BaseClkFreq    The base clock frequency of host controller in MHz.\r
-  @param[in] ControllerVer  The version of host controller.\r
-\r
-  @retval EFI_SUCCESS       The clock is supplied successfully.\r
-  @retval Others            The clock isn't supplied successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcInitClockFreq (\r
-  IN EFI_PCI_IO_PROTOCOL    *PciIo,\r
-  IN UINT8                  Slot,\r
-  IN UINT32                 BaseClkFreq,\r
-  IN UINT16                 ControllerVer\r
-  );\r
-\r
 /**\r
   Supply SD/MMC card with maximum voltage at initialization.\r
 \r