]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
MdeModulePkg/SdMmcPciHcDxe: Add V3 64b DMA Support
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / EmmcDevice.c
old mode 100755 (executable)
new mode 100644 (file)
index c5fd214..15db8a8
@@ -1,6 +1,7 @@
 /** @file\r
   This file provides some helper functions which are specific for EMMC device.\r
 \r
+  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\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
@@ -641,7 +642,7 @@ EmmcSwitchBusWidth (
 }\r
 \r
 /**\r
-  Switch the clock frequency to the specified value.\r
+  Switch the bus timing and clock frequency.\r
 \r
   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller\r
   Simplified Spec 3.0 Figure 3-3 for details.\r
@@ -651,6 +652,7 @@ EmmcSwitchBusWidth (
   @param[in] Slot           The slot number of the SD card to send the command to.\r
   @param[in] Rca            The relative device address to be assigned.\r
   @param[in] HsTiming       The value to be written to HS_TIMING field of EXT_CSD register.\r
+  @param[in] Timing         The bus mode timing indicator.\r
   @param[in] ClockFreq      The max clock frequency to be set, the unit is MHz.\r
 \r
   @retval EFI_SUCCESS       The operation is done correctly.\r
@@ -658,12 +660,13 @@ EmmcSwitchBusWidth (
 \r
 **/\r
 EFI_STATUS\r
-EmmcSwitchClockFreq (\r
+EmmcSwitchBusTiming (\r
   IN EFI_PCI_IO_PROTOCOL                *PciIo,\r
   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,\r
   IN UINT8                              Slot,\r
   IN UINT16                             Rca,\r
   IN UINT8                              HsTiming,\r
+  IN SD_MMC_BUS_MODE                    Timing,\r
   IN UINT32                             ClockFreq\r
   )\r
 {\r
@@ -686,26 +689,48 @@ EmmcSwitchClockFreq (
 \r
   Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming, Status));\r
+    DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to hstiming %d fails with %r\n", HsTiming, Status));\r
+    return Status;\r
+  }\r
+\r
+  //\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
+  if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Send status fails with %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Send status fails with %r\n", Status));\r
     return Status;\r
   }\r
   //\r
   // Check the switch operation is really successful or not.\r
   //\r
   if ((DevStatus & BIT7) != 0) {\r
-    DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
+    DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
     return EFI_DEVICE_ERROR;\r
   }\r
-  //\r
-  // Convert the clock freq unit from MHz to KHz.\r
-  //\r
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);\r
+\r
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+    Status = mOverride->NotifyPhase (\r
+                          Private->ControllerHandle,\r
+                          Slot,\r
+                          EdkiiSdMmcSwitchClockFreqPost,\r
+                          &Timing\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
@@ -740,10 +765,13 @@ EmmcSwitchToHighSpeed (
   IN UINT8                              BusWidth\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  UINT8               HsTiming;\r
-  UINT8               HostCtrl1;\r
-  UINT8               HostCtrl2;\r
+  EFI_STATUS              Status;\r
+  UINT8                   HsTiming;\r
+  UINT8                   HostCtrl1;\r
+  SD_MMC_BUS_MODE         Timing;\r
+  SD_MMC_HC_PRIVATE_DATA  *Private;\r
+\r
+  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
 \r
   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);\r
   if (EFI_ERROR (Status)) {\r
@@ -758,31 +786,21 @@ EmmcSwitchToHighSpeed (
     return Status;\r
   }\r
 \r
-  //\r
-  // Clean UHS Mode Select field of Host Control 2 reigster before update\r
-  //\r
-  HostCtrl2 = (UINT8)~0x7;\r
-  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50\r
-  //\r
   if (IsDdr) {\r
-    HostCtrl2 = BIT2;\r
+    Timing = SdMmcMmcHsDdr;\r
   } else if (ClockFreq == 52) {\r
-    HostCtrl2 = BIT0;\r
+    Timing = SdMmcMmcHsSdr;\r
   } else {\r
-    HostCtrl2 = 0;\r
+    Timing = SdMmcMmcLegacy;\r
   }\r
-  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   HsTiming = 1;\r
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+  Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
 \r
   return Status;\r
 }\r
@@ -814,10 +832,13 @@ EmmcSwitchToHS200 (
   IN UINT8                              BusWidth\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  UINT8               HsTiming;\r
-  UINT8               HostCtrl2;\r
-  UINT16              ClockCtrl;\r
+  EFI_STATUS               Status;\r
+  UINT8                    HsTiming;\r
+  UINT16                   ClockCtrl;\r
+  SD_MMC_BUS_MODE          Timing;\r
+  SD_MMC_HC_PRIVATE_DATA  *Private;\r
+\r
+  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
 \r
   if ((BusWidth != 4) && (BusWidth != 8)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -837,22 +858,14 @@ EmmcSwitchToHS200 (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  //\r
-  // Clean UHS Mode Select field of Host Control 2 reigster before update\r
-  //\r
-  HostCtrl2 = (UINT8)~0x7;\r
-  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // Set UHS Mode Select field of Host Control 2 reigster to SDR104\r
-  //\r
-  HostCtrl2 = BIT0 | BIT1;\r
-  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+  Timing = SdMmcMmcHs200;\r
+\r
+  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
   // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit\r
   //\r
@@ -875,7 +888,7 @@ EmmcSwitchToHS200 (
   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
 \r
   HsTiming = 2;\r
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+  Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -910,9 +923,12 @@ EmmcSwitchToHS400 (
   IN UINT32                             ClockFreq\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  UINT8               HsTiming;\r
-  UINT8               HostCtrl2;\r
+  EFI_STATUS                 Status;\r
+  UINT8                      HsTiming;\r
+  SD_MMC_BUS_MODE            Timing;\r
+  SD_MMC_HC_PRIVATE_DATA     *Private;\r
+\r
+  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
 \r
   Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);\r
   if (EFI_ERROR (Status)) {\r
@@ -922,7 +938,7 @@ EmmcSwitchToHS400 (
   // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.\r
   //\r
   HsTiming = 1;\r
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);\r
+  Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -933,25 +949,16 @@ EmmcSwitchToHS400 (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  //\r
-  // Clean UHS Mode Select field of Host Control 2 reigster before update\r
-  //\r
-  HostCtrl2 = (UINT8)~0x7;\r
-  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // Set UHS Mode Select field of Host Control 2 reigster to HS400\r
-  //\r
-  HostCtrl2 = BIT0 | BIT2;\r
-  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+  Timing = SdMmcMmcHs400;\r
+\r
+  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   HsTiming = 3;\r
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+  Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
 \r
   return Status;\r
 }\r
@@ -1002,7 +1009,7 @@ EmmcSetBusMode (
     return Status;\r
   }\r
 \r
-  ASSERT (Private->Capability[Slot].BaseClkFreq != 0);\r
+  ASSERT (Private->BaseClkFreq[Slot] != 0);\r
   //\r
   // Check if the Host Controller support 8bits bus width.\r
   //\r