public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* Re: [patch_2] make EDK Driver Support BH720+EMMC chip
@ 2019-01-23 10:39 Mike Li (WH)
  2019-01-23 10:45 ` [patch_3] " Mike Li (WH)
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Li (WH) @ 2019-01-23 10:39 UTC (permalink / raw)
  To: Mike Li (WH), Xiaoguang Yu (WH), Ernest Zhang(WH), Andy Dai (WH)
  Cc: Shirley Her (SC), edk2-devel@lists.01.org

Hi, all

The following modifications are made to enable EDK Driver Support BH720 CHIP.

--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c            2019-01-21 15:36:12.186739600 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c           2019-01-10 14:34:23.072538900 -0800
@@ -1,7 +1,6 @@
/** @file
   This file provides some helper functions which are specific for EMMC device.
-  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -527,17 +526,35 @@ EmmcTuningClkForHs200 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
+
+  if(BhtHostPciSupport(PciIo)){
+                              //set data transfer with 4bit
+                              Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
+                              //enable hardware tuning
+                              HostCtrl2 = (~0x10);
+                              Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2);
+
+                Status = EmmcSendTuningBlk (PassThru, Slot, 4);
+                if (EFI_ERROR (Status)) {
+                              DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+                              return Status;
+                }
+
+  }
   //
   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
   //
   Retry = 0;
   do {
-    Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
-      return Status;
-    }
-
+              if(!BhtHostPciSupport(PciIo)){
+                  Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
+                  if (EFI_ERROR (Status)) {
+                    DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+                    return Status;
+                  }
+              } else {
+                              gBS->Stall(5000);
+              }
     Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
     if (EFI_ERROR (Status)) {
       return Status;
@@ -548,6 +565,10 @@ EmmcTuningClkForHs200 (
     }
     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
+                if(BhtHostPciSupport(PciIo)){
+                              //set data transfer with default
+                              Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
+                              }
       return EFI_SUCCESS;
     }
   } while (++Retry < 40);
@@ -652,7 +673,6 @@ EmmcSwitchBusWidth (
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] Rca            The relative device address to be assigned.
   @param[in] HsTiming       The value to be written to HS_TIMING field of EXT_CSD register.
-  @param[in] Timing         The bus mode timing indicator.
   @param[in] ClockFreq      The max clock frequency to be set, the unit is MHz.
   @retval EFI_SUCCESS       The operation is done correctly.
@@ -666,7 +686,6 @@ EmmcSwitchClockFreq (
   IN UINT8                              Slot,
   IN UINT16                             Rca,
   IN UINT8                              HsTiming,
-  IN SD_MMC_BUS_MODE                    Timing,
   IN UINT32                             ClockFreq
   )
{
@@ -708,28 +727,7 @@ EmmcSwitchClockFreq (
   //
   // Convert the clock freq unit from MHz to KHz.
   //
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
-    Status = mOverride->NotifyPhase (
-                          Private->ControllerHandle,
-                          Slot,
-                          EdkiiSdMmcSwitchClockFreqPost,
-                          &Timing
-                          );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
-        __FUNCTION__,
-        Status
-        ));
-      return Status;
-    }
-  }
+  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);
   return Status;
}
@@ -764,13 +762,10 @@ EmmcSwitchToHighSpeed (
   IN UINT8                              BusWidth
   )
{
-  EFI_STATUS              Status;
-  UINT8                   HsTiming;
-  UINT8                   HostCtrl1;
-  SD_MMC_BUS_MODE         Timing;
-  SD_MMC_HC_PRIVATE_DATA  *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl1;
+  UINT8               HostCtrl2;
   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
   if (EFI_ERROR (Status)) {
@@ -785,21 +780,31 @@ EmmcSwitchToHighSpeed (
     return Status;
   }
+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50
+  //
   if (IsDdr) {
-    Timing = SdMmcMmcHsDdr;
+    HostCtrl2 = BIT2;
   } else if (ClockFreq == 52) {
-    Timing = SdMmcMmcHsSdr;
+    HostCtrl2 = BIT0;
   } else {
-    Timing = SdMmcMmcLegacy;
+    HostCtrl2 = 0;
   }
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
   HsTiming = 1;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
   return Status;
}
@@ -831,13 +836,10 @@ EmmcSwitchToHS200 (
   IN UINT8                              BusWidth
   )
{
-  EFI_STATUS               Status;
-  UINT8                    HsTiming;
-  UINT16                   ClockCtrl;
-  SD_MMC_BUS_MODE          Timing;
-  SD_MMC_HC_PRIVATE_DATA  *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl2;
+  UINT16              ClockCtrl;
   if ((BusWidth != 4) && (BusWidth != 8)) {
     return EFI_INVALID_PARAMETER;
@@ -857,29 +859,60 @@ EmmcSwitchToHS200 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
-  Timing = SdMmcMmcHs200;
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to SDR104
+  //
+  HostCtrl2 = BIT0 | BIT1;
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
   //
   // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
   //
-  Status = SdMmcHcWaitMmioSet (
-             PciIo,
-             Slot,
-             SD_MMC_HC_CLOCK_CTRL,
-             sizeof (ClockCtrl),
-             BIT1,
-             BIT1,
-             SD_MMC_HC_GENERIC_TIMEOUT
+  if (BhtHostPciSupport(PciIo)) {
+                  Status = SdMmcHcWaitMmioSet (
+               PciIo,
+               Slot,
+               0x1cc,
+               sizeof (ClockCtrl),
+               BIT14,
+               BIT14,
+               SD_MMC_HC_GENERIC_TIMEOUT
+             );
+  }
+  else {
+    Status = SdMmcHcWaitMmioSet (
+               PciIo,
+               Slot,
+               SD_MMC_HC_CLOCK_CTRL,
+               sizeof (ClockCtrl),
+               BIT1,
+               BIT1,
+               SD_MMC_HC_GENERIC_TIMEOUT
              );
+  }
   if (EFI_ERROR (Status)) {
     return Status;
   }
+
+  if (BhtHostPciSupport(PciIo)){
+    //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
+    UINT32 value32;
+    while (1) {
+                Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
+                if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01))
+                  break;
+    }
+  }
   //
   // Set SD Clock Enable in the Clock Control register to 1
   //
@@ -887,12 +920,33 @@ EmmcSwitchToHS200 (
   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
   HsTiming = 2;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
+  if (BhtHostPciSupport(PciIo)){
+    Status = SdMmcHcWaitMmioSet (
+                                                PciIo,
+                                                 Slot,
+               0x1cc,
+                                                 sizeof (ClockCtrl),
+                                                 BIT11,
+                                                 BIT11,
+                                                 SD_MMC_CLOCK_STABLE_TIMEOUT
+                                                 );
+    if (EFI_ERROR(Status)) {
+                DbgMsg(L"Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
+                return Status;
+      }
+  }
+
+  if (EFI_ERROR(Status)) {
+              DbgMsg(L"Emmc tuning failed\n");
+              return Status;
+  }
+
+
   return Status;
}
@@ -922,12 +976,9 @@ EmmcSwitchToHS400 (
   IN UINT32                             ClockFreq
   )
{
-  EFI_STATUS                 Status;
-  UINT8                      HsTiming;
-  SD_MMC_BUS_MODE            Timing;
-  SD_MMC_HC_PRIVATE_DATA     *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl2;
   Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
   if (EFI_ERROR (Status)) {
@@ -937,7 +988,7 @@ EmmcSwitchToHS400 (
   // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.
   //
   HsTiming = 1;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -948,16 +999,25 @@ EmmcSwitchToHS400 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
-  Timing = SdMmcMmcHs400;
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to HS400
+  //
+  HostCtrl2 = BIT0 | BIT2;
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
   HsTiming = 3;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
   return Status;
}
@@ -1008,7 +1068,7 @@ EmmcSetBusMode (
     return Status;
   }
-  ASSERT (Private->BaseClkFreq[Slot] != 0);
+  ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
   //
   // Check if the Host Controller support 8bits bus width.
   //
@@ -1080,6 +1140,42 @@ EmmcSetBusMode (
     // Execute HS200 timing switch procedure
     //
     Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+              if (EFI_ERROR(Status)) {
+      if (BhtHostPciSupport(PciIo)) {
+                                UINT32 val32;
+                                DbgMsg(L"switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
+                                ClockFreq = 100;
+
+                                SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32);
+                                val32 &= ~BIT22;
+                    SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32);
+                                val32 = (BIT26 | BIT25);
+                    SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32);
+
+                                Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+                                if (EFI_ERROR(Status)) {
+                                              if (((ExtCsd.DeviceType & BIT1)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+                                               DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n");
+
+                                    HsTiming  = 1;
+              IsDdr     = FALSE;
+              ClockFreq = 52;
+                                                Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+                                              }
+                                              else if (((ExtCsd.DeviceType & BIT0)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+                                                DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n");
+
+                                                HsTiming  = 1;
+              IsDdr     = FALSE;
+              ClockFreq = 26;
+                                                Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+                                              }
+                                              else {
+                                               DbgMsg(L"switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
+                                              }
+                                }
+                              }
+    }
   } else {
     //
     // Execute High Speed timing switch procedure

Please check it!
Br,
Mike

From: Mike Li (WH)
Sent: 2019年1月23日 17:29
To: Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); 'edk2-devel@lists.01.org'
Subject: [edk2] [patch_1] make EDK Driver Support BH720+EMMC chip


Hi, all

The following modifications are made to enable EDK Driver Support BH720 CHIP.

--- /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c            2019-01-10 14:35:21.342736200 -0800
+++ /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c         2019-01-21 15:36:12.195715300 -0800
@@ -4,6 +4,7 @@

   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.

+  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -16,8 +17,6 @@
**/

 #include "SdMmcPciHcDxe.h"
-int g_deviceId = 0;
-

 /**
   Dump the content of SD/MMC host controller's Capability Register.
@@ -47,7 +46,8 @@ DumpCapabilityReg (
   DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
-  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   SlotType          "));
   if (Capability->SlotType == 0x00) {
@@ -419,9 +419,39 @@ SdMmcHcWaitMmioSet (
}

 /**
+  Get the controller version information from the specified slot.
+
+  @param[in]  PciIo           The PCI IO protocol instance.
+  @param[in]  Slot            The slot number of the SD card to send the command to.
+  @param[out] Version         The buffer to store the version information.
+
+  @retval EFI_SUCCESS         The operation executes successfully.
+  @retval Others              The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN     UINT8                Slot,
+  OUT    UINT16               *Version
+  )
+{
+  EFI_STATUS                Status;
+
+  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *Version &= 0xFF;
+
+  return EFI_SUCCESS;
+}
+
+/**
   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.
@@ -430,18 +460,38 @@ 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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC pre reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+      return Status;
+    }
+  }

-  SwReset = 0xFF;
-  Status  = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
+  PciIo   = Private->PciIo;
+  SwReset = BIT0;
+  Status  = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);

   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status));
+    DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));
     return Status;
   }

@@ -450,7 +500,7 @@ SdMmcHcReset (
              Slot,
              SD_MMC_HC_SW_RST,
              sizeof (SwReset),
-             0xFF,
+             BIT0,
              0x00,
              SD_MMC_HC_GENERIC_TIMEOUT
              );
@@ -458,10 +508,33 @@ 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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }

   return Status;
}
@@ -680,7 +753,8 @@ SdMmcHcStopClock (
   @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] ClockFreq      The max clock frequency to be set. The unit is KHz.
-  @param[in] Capability     The capability of the slot.
+  @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -691,23 +765,21 @@ SdMmcHcClockSupply (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
   IN UINT64                 ClockFreq,
-  IN SD_MMC_HC_SLOT_CAP     Capability
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
{
   EFI_STATUS                Status;
-  UINT32                    BaseClkFreq;
   UINT32                    SettingFreq;
   UINT32                    Divisor;
   UINT32                    Remainder;
-  UINT16                    ControllerVer;
   UINT16                    ClockCtrl;

   //
   // Calculate a divisor for SD clock frequency
   //
-  ASSERT (Capability.BaseClkFreq != 0);
+  ASSERT (BaseClkFreq != 0);

-  BaseClkFreq = Capability.BaseClkFreq;
   if (ClockFreq == 0) {
     return EFI_INVALID_PARAMETER;
   }
@@ -736,17 +808,15 @@ SdMmcHcClockSupply (

   DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));

-  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
   //
   // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
   //
-  if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
+  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
     ASSERT (Divisor <= 0x3FF);
     ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
-  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
     //
     // Only the most significant bit can be used as divisor.
     //
@@ -894,11 +964,62 @@ SdMmcHcSetBusWidth (
}

 /**
-  Supply SD/MMC card with lowest clock frequency at initialization.
+  Configure V4 controller enhancements 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.
+  @param[in] ControllerVer  The version of host controller.
+
+  @retval EFI_SUCCESS       The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_HC_SLOT_CAP     Capability,
+  IN UINT16                 ControllerVer
+  )
+{
+  EFI_STATUS                Status;
+  UINT16                    HostCtrl2;
+
+  //
+  // Check if controller version V4 or higher
+  //
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    HostCtrl2 = SD_MMC_HC_V4_EN;
+    //
+    // Check if V4 64bit support is available
+    //
+    if (Capability.SysBus64V4 != 0) {
+      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+    }
+    //
+    // Check if controller version V4.10 or higher
+    //
+    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+    }
+    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Supply SD/MMC card with lowest clock frequency 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] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -908,16 +1029,20 @@ EFI_STATUS
SdMmcHcInitClockFreq (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
-  IN SD_MMC_HC_SLOT_CAP     Capability
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
{
   EFI_STATUS                Status;
   UINT32                    InitFreq;

   //
-  // Calculate a divisor for SD clock frequency
+  // According to SDHCI specification ver. 4.2, BaseClkFreq field value of
+  // the Capability Register 1 can be zero, which means a need for obtaining
+  // the clock frequency via another method. Fail in case it is not updated
+  // by SW at this point.
   //
-  if (Capability.BaseClkFreq == 0) {
+  if (BaseClkFreq == 0) {
     //
     // Don't support get Base Clock Frequency information via another method
     //
@@ -927,7 +1052,7 @@ SdMmcHcInitClockFreq (
   // Supply 400KHz clock frequency at initialization phase.
   //
   InitFreq = 400;
-  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);
+  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
   return Status;
}

@@ -988,15 +1113,6 @@ SdMmcHcInitPowerVoltage (
   // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
   //
   Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);
-  if (BhtHostPciSupport(PciIo)){
-                // 1.8V signaling enable
-                HostCtrl2  = BIT3;
-                Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
-                gBS->Stall (5000);
-                if (EFI_ERROR (Status)) {
-                              return Status;
-                }
-  }

   return Status;
}
@@ -1032,9 +1148,8 @@ 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.

   @retval EFI_SUCCESS       The host controller is initialized successfully.
   @retval Others            The host controller isn't initialized successfully.
@@ -1042,96 +1157,164 @@ 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;
-  UINT32           value32;
-
-  if (BhtHostPciSupport(PciIo)){
-
-                              DbgMsg(L"find bht emmc chip\n");
-                              /* FET on */
-                              PciBhtOr32(PciIo, 0xEC, 0x3);
-                              /* Led on */
-                              //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13);
-                              PciBhtOr32(PciIo, 0xD4, BIT6);
-                              /* Set 1.8v emmc signaling flag */
-                              PciBhtOr32(PciIo, 0x308, BIT4);
-                              /* Set 200MBaseClock */
-                              value32 = PciBhtRead32(PciIo, 0x304);
-                              value32 &= 0x0000FFFF;
-                              value32 |= 0x25100000;
-                              PciBhtWrite32(PciIo, 0x304, value32);
-                              PciBhtOr32(PciIo, 0x3E4, BIT22);
-                              PciBhtWrite32(PciIo, 0x300, 0x21400033);
-
-                              //enable internal clk
-                              value32 = BIT0;
-                              Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32);
-
-                              //reset pll start
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                              value32 |= BIT12;
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-                              gBS->Stall(1);
-
-                              //reset pll end
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32);
-                              value32 &= ~BIT12;
-                              value32 |= BIT18;
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-
-                              //wait BaseClk stable 0x1CC bit14
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                              while(!(value32&BIT14)){
-                                              gBS->Stall(100);
-                                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                                              DbgMsg(L"1CC=0x%08x\n", value32);
-                              }
-
-                              if (value32 & BIT18)
-                              {
-                                //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
-                                while (1) {
-                                  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
-            if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01))
-              break;
-                                }
-                                //force pll active end
-                                Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                                value32 &= ~BIT18;
-                                Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-                              }
-
-                              Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
-                              if (EFI_ERROR (Status)) {
-                                  DbgMsg(L"emmc host init failure\n");
-                                  return Status;
-                              }
-
-
-  }
-
-  Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (!BhtHostPciSupport(PciIo)){
-                Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
-                if (EFI_ERROR (Status)) {
-                  return 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,
+                          NULL);
+    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 = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
-
+
+  Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
   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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post init notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }
   return Status;
}

 /**
+  Set SD Host Controler control 2 registry according to selected speed.
+
+  @param[in] ControllerHandle The handle of the controller.
+  @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] Timing           The timing to select.
+
+  @retval EFI_SUCCESS         The timing is set successfully.
+  @retval Others              The timing isn't set successfully.
+**/
+EFI_STATUS
+SdMmcHcUhsSignaling (
+  IN EFI_HANDLE             ControllerHandle,
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_BUS_MODE        Timing
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      HostCtrl2;
+
+  HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  switch (Timing) {
+    case SdMmcUhsSdr12:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;
+      break;
+    case SdMmcUhsSdr25:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;
+      break;
+    case SdMmcUhsSdr50:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;
+      break;
+    case SdMmcUhsSdr104:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;
+      break;
+    case SdMmcUhsDdr50:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;
+      break;
+    case SdMmcMmcLegacy:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;
+      break;
+    case SdMmcMmcHsSdr:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;
+      break;
+    case SdMmcMmcHsDdr:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;
+      break;
+    case SdMmcMmcHs200:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;
+      break;
+    case SdMmcMmcHs400:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;
+      break;
+    default:
+     HostCtrl2 = 0;
+     break;
+  }
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcUhsSignaling,
+                          &Timing
+                          );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: SD/MMC uhs signaling notifier callback failed - %r\n",
+        __FUNCTION__,
+        Status
+        ));
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Turn on/off LED.

   @param[in] PciIo          The PCI IO protocol instance.
@@ -1166,9 +1349,10 @@ SdMmcHcLedOnOff (
/**
   Build ADMA descriptor table for transfer.

-  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.

   @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
   @retval Others            The ADMA descriptor table isn't created successfully.
@@ -1176,7 +1360,8 @@ SdMmcHcLedOnOff (
**/
EFI_STATUS
BuildAdmaDescTable (
-  IN SD_MMC_HC_TRB          *Trb
+  IN SD_MMC_HC_TRB          *Trb,
+  IN UINT16                 ControllerVer
   )
{
   EFI_PHYSICAL_ADDRESS      Data;
@@ -1184,49 +1369,93 @@ BuildAdmaDescTable (
   UINT64                    Entries;
   UINT32                    Index;
   UINT64                    Remaining;
-  UINT32                    Address;
+  UINT64                    Address;
   UINTN                     TableSize;
   EFI_PCI_IO_PROTOCOL       *PciIo;
   EFI_STATUS                Status;
   UINTN                     Bytes;
+  BOOLEAN                   AddressingMode64;
+  BOOLEAN                   DataLength26;
+  UINT32                    AdmaMaxDataPerLine;
+  UINT32                    DescSize;
+  VOID                      *AdmaDesc;
+
+  AddressingMode64   = FALSE;
+  DataLength26       = FALSE;
+  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
+  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+  AdmaDesc           = NULL;

   Data    = Trb->DataPhy;
   DataLen = Trb->DataLen;
   PciIo   = Trb->Private->PciIo;
+
   //
-  // Only support 32bit ADMA Descriptor Table
+  // Detect whether 64bit addressing is supported.
   //
-  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
+    }
+  }
+  //
+  // Check for valid ranges in 32bit ADMA Descriptor Table
+  //
+  if (!AddressingMode64 &&
+      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
     return EFI_INVALID_PARAMETER;
   }
   //
-  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
-  // for 32-bit address descriptor table.
+  // Check address field alignment
   //
-  if ((Data & (BIT0 | BIT1)) != 0) {
-    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+  if (AddressingMode64) {
+    //
+    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+    }
+  } else {
+    //
+    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+    }
+  }
+  //
+  // Detect whether 26bit data length is supported.
+  //
+  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                               SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
+  if (!EFI_ERROR (Status)) {
+    DataLength26 = TRUE;
+    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
   }

-  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
-  TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
   Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
   Status = PciIo->AllocateBuffer (
                     PciIo,
                     AllocateAnyPages,
                     EfiBootServicesData,
                     EFI_SIZE_TO_PAGES (TableSize),
-                    (VOID **)&Trb->AdmaDesc,
+                    (VOID **)&AdmaDesc,
                     0
                     );
   if (EFI_ERROR (Status)) {
     return EFI_OUT_OF_RESOURCES;
   }
-  ZeroMem (Trb->AdmaDesc, TableSize);
+  ZeroMem (AdmaDesc, TableSize);
   Bytes  = TableSize;
   Status = PciIo->Map (
                     PciIo,
                     EfiPciIoOperationBusMasterCommonBuffer,
-                    Trb->AdmaDesc,
+                    AdmaDesc,
                     &Bytes,
                     &Trb->AdmaDescPhy,
                     &Trb->AdmaMap
@@ -1239,12 +1468,13 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
              PciIo,
              EFI_SIZE_TO_PAGES (TableSize),
-             Trb->AdmaDesc
+             AdmaDesc
              );
     return EFI_OUT_OF_RESOURCES;
   }

-  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+  if ((!AddressingMode64) &&
+      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
     //
     // The ADMA doesn't support 64bit addressing.
     //
@@ -1255,35 +1485,71 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
       PciIo,
       EFI_SIZE_TO_PAGES (TableSize),
-      Trb->AdmaDesc
+      AdmaDesc
     );
     return EFI_DEVICE_ERROR;
   }

   Remaining = DataLen;
-  Address   = (UINT32)Data;
+  Address   = Data;
+  if (!AddressingMode64) {
+    Trb->Adma32Desc = AdmaDesc;
+    Trb->Adma64Desc = NULL;
+  } else {
+    Trb->Adma64Desc = AdmaDesc;
+    Trb->Adma32Desc = NULL;
+  }
   for (Index = 0; Index < Entries; Index++) {
-    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
-      Trb->AdmaDesc[Index].Address = Address;
-      break;
+    if (!AddressingMode64) {
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+        }
+        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+        break;
+      } else {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma32Desc[Index].LowerLength  = 0;
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+      }
     } else {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = 0;
-      Trb->AdmaDesc[Index].Address = Address;
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = (UINT16)RShiftU64 (Remaining, 16);
+        }
+        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+        break;
+      } else {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma64Desc[Index].LowerLength  = 0;
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+      }
     }

-    Remaining -= ADMA_MAX_DATA_PER_LINE;
-    Address   += ADMA_MAX_DATA_PER_LINE;
+    Remaining -= AdmaMaxDataPerLine;
+    Address   += AdmaMaxDataPerLine;
   }

   //
   // Set the last descriptor line as end of descriptor table
   //
-  Trb->AdmaDesc[Index].End = 1;
+  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
   return EFI_SUCCESS;
}

@@ -1381,7 +1647,7 @@ SdMmcCreateTrb (
       Trb->Mode = SdMmcNoData;
     } else if (Private->Capability[Slot].Adma2 != 0) {
       Trb->Mode = SdMmcAdmaMode;
-      Status = BuildAdmaDescTable (Trb);
+      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
       if (EFI_ERROR (Status)) {
         PciIo->Unmap (PciIo, Trb->DataMap);
         goto Error;
@@ -1427,11 +1693,18 @@ SdMmcFreeTrb (
       Trb->AdmaMap
     );
   }
-  if (Trb->AdmaDesc != NULL) {
+  if (Trb->Adma32Desc != NULL) {
+    PciIo->FreeBuffer (
+      PciIo,
+      Trb->AdmaPages,
+      Trb->Adma32Desc
+    );
+  }
+  if (Trb->Adma64Desc != NULL) {
     PciIo->FreeBuffer (
       PciIo,
       Trb->AdmaPages,
-      Trb->AdmaDesc
+      Trb->Adma64Desc
     );
   }
   if (Trb->DataMap != NULL) {
@@ -1571,12 +1844,15 @@ SdMmcExecTrb (
   UINT16                              Cmd;
   UINT16                              IntStatus;
   UINT32                              Argument;
-  UINT16                              BlkCount;
+  UINT32                              BlkCount;
   UINT16                              BlkSize;
   UINT16                              TransMode;
   UINT8                               HostCtrl1;
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT64                              AdmaAddr;
+  BOOLEAN                             AddressingMode64;
+
+  AddressingMode64 = FALSE;

   Packet = Trb->Packet;
   PciIo  = Trb->Private->PciIo;
@@ -1609,13 +1885,28 @@ SdMmcExecTrb (

   SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);

+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+    }
+  }
+
   if (Trb->Mode == SdMmcSdmaMode) {
-    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+    if ((!AddressingMode64) &&
+        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
       return EFI_INVALID_PARAMETER;
     }

-    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
-    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+    } else {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+    }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
@@ -1645,9 +1936,13 @@ SdMmcExecTrb (
     //
     // Calcuate Block Count.
     //
-    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+    BlkCount = (Trb->DataLen / Trb->BlockSize);
+  }
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+  } else {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
   }
-  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1743,7 +2038,7 @@ SdMmcCheckTrbResult (
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
   UINT16                              IntStatus;
   UINT32                              Response[4];
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT8                               Index;
   UINT8                               SwReset;
   UINT32                              PioLength;
@@ -1867,8 +2162,19 @@ SdMmcCheckTrbResult (
     //
     // Update SDMA Address register.
     //
-    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
-    Status   = SdMmcHcRwMmio (
+    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (
+                 Private->PciIo,
+                 Trb->Slot,
+                 SD_MMC_HC_ADMA_SYS_ADDR,
+                 FALSE,
+                 sizeof (UINT64),
+                 &SdmaAddr
+                 );
+    } else {
+      Status = SdMmcHcRwMmio (
                  Private->PciIo,
                  Trb->Slot,
                  SD_MMC_HC_SDMA_ADDR,
@@ -1876,10 +2182,12 @@ SdMmcCheckTrbResult (
                  sizeof (UINT32),
                  &SdmaAddr
                  );
+    }
+
     if (EFI_ERROR (Status)) {
       goto Done;
     }
-    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
   }

   if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
@@ -2000,281 +2308,3 @@ SdMmcWaitTrbResult (
   return EFI_TIMEOUT;
}

-BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo)
-{
-              PCI_TYPE00                         Pci;
-
-              PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,
-                                                                0, sizeof Pci / sizeof (UINT32), &Pci);
-
-              DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId));
-
-              if (Pci.Hdr.VendorId != 0x1217)
-                              goto end;
-
-              switch (Pci.Hdr.DeviceId)
-              {
-                              case 0x8420:       //PCI_DEV_ID_SDS0
-                              case 0x8421:       //PCI_DEV_ID_SDS1
-                              case 0x8520:       //PCI_DEV_ID_FJ2
-                              case 0x8620:       //PCI_DEV_ID_SB0
-                              case 0x8621:       //PCI_DEV_ID_SB1
-                                              g_deviceId = Pci.Hdr.DeviceId;
-                                              return 1;
-                              default:
-                                              break;
-              }
-
-              end:
-              return 0;
-}
-
-void DbgNull(IN CONST CHAR16 * fmt, ...)
-{
-}
-
-UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
-              UINT32 arg;
-              PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg);
-              return arg;
-}
-
-void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value);
-}
-
-
-UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
-              UINT32 i = 0;
-              UINT32 tmp[3] = {0};
-
-              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                              (g_deviceId == PCI_DEV_ID_SDS1) ||
-                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                              (g_deviceId == PCI_DEV_ID_SB1))
-              {
-                              // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
-                              // Enable mapping
-
-                              // Check function conflict
-                              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB1))
-                              {
-                                              i = 0;
-                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-                                              while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
-                                              {
-                                                              if(i == 5)
-                                                              {
-                                                                              //DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                                                                              goto RD_DIS_MAPPING;
-                                                              }
-                                                                                              gBS->Stall(1000);
-                                                              i++;
-                                                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-
-                                              }
-                              }
-                              else if(g_deviceId == PCI_DEV_ID_SDS1)
-                              {
-                                              i = 0;
-                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-                                              while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
-                                              {
-                                                              if(i == 5)
-                                                              {
-                                                                              //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__));
-                                                                              goto RD_DIS_MAPPING;
-                                                              }
-                                                              gBS->Stall(1000);
-                                                              i++;
-                                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-                                              }
-                              }
-
-                              // Check last operation is complete
-                              i = 0;
-                              while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-                              {
-                                              if(i == 5)
-                                              {
-                                                              //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl)));
-                                                              //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn)));
-                                                              //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                                                              goto RD_DIS_MAPPING;
-                                              }
-                                              gBS->Stall(1000);
-                                              i += 1;
-                              }
-
-                              // Set register address
-                              tmp[0] |= 0x40000000;
-                              tmp[0] |= offset;
-                              bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]);
-
-                              // Check read is complete
-                              i = 0;
-                              while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000)
-                              {
-                                              if(i == 5)
-                                              {
-                                                              //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__));
-                                                              goto RD_DIS_MAPPING;
-                                              }
-                                              gBS->Stall(1000);
-                                              i += 1;
-                              }
-
-                              // Get PCIR value
-                              tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal);
-
-RD_DIS_MAPPING:
-                              // Disable mapping
-                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-
-                              //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]);
-                              return tmp[1];
-              }
-
-              //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]);
-              return tmp[0];
-}
-
-void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 tmp = 0;
-    UINT32 i = 0;
-
-              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                              (g_deviceId == PCI_DEV_ID_SDS1) ||
-                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                              (g_deviceId == PCI_DEV_ID_SB1))
-    {
-        // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
-        // Upper caller doesn't need to set 0xD0.
-
-        // Enable mapping
-
-        // Check function conflict
-                              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB1))
-        {
-            i = 0;
-            bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-            while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
-            {
-                if(i == 5)
-                {
-                    //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                    goto WR_DIS_MAPPING;
-                }
-
-                gBS->Stall(1000);
-                i++;
-                bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-            }
-        }
-        else if(g_deviceId == PCI_DEV_ID_SDS1)
-        {
-            i = 0;
-            bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-
-            while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
-            {
-                if(i == 5)
-                {
-                    //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                    goto WR_DIS_MAPPING;
-                }
-
-                gBS->Stall(1000);
-                i++;
-                bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-            }
-        }
-
-        // Enable MEM access
-        bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000);
-        bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
-        // Check last operation is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                goto WR_DIS_MAPPING;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-        // Set write value
-        bht_writel(PciIo, BHT_PCIRMappingVal, value);
-        // Set register address
-        tmp |= 0x80000000;
-        tmp |= offset;
-        bht_writel(PciIo, BHT_PCIRMappingCtl, tmp);
-
-        // Check write is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__));
-                goto WR_DIS_MAPPING;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-WR_DIS_MAPPING:
-        // Disable MEM access
-        bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001);
-        bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
-        // Check last operation is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                break;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-        // Disable function conflict
-
-        // Disable mapping
-        bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-    }
-}
-
-void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 arg;
-              arg = PciBhtRead32(PciIo, offset);
-              PciBhtWrite32(PciIo, offset, value | arg);
-}
-
-void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 arg;
-              arg = PciBhtRead32(PciIo, offset);
-              PciBhtWrite32(PciIo, offset, value & arg);
-}
-


Please check it!
Br,
Mike

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [patch_3] make EDK Driver Support BH720+EMMC chip
  2019-01-23 10:39 [patch_2] make EDK Driver Support BH720+EMMC chip Mike Li (WH)
@ 2019-01-23 10:45 ` Mike Li (WH)
  0 siblings, 0 replies; 2+ messages in thread
From: Mike Li (WH) @ 2019-01-23 10:45 UTC (permalink / raw)
  To: Mike Li (WH), Xiaoguang Yu (WH), Ernest Zhang(WH), Andy Dai (WH)
  Cc: Shirley Her (SC), edk2-devel@lists.01.org

Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.

--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c   2019-01-21 15:36:12.188734400 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c   2018-08-13 22:40:04.802226200 -0700
@@ -1,7 +1,6 @@
/** @file
   This file provides some helper functions which are specific for SD card device.
-  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -319,9 +318,116 @@ SdCardSetRca (
   return Status;
}
+/**
+  Send command SEND_CSD to the SD device to get the data of the CSD register.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+  @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
+  @param[in]  Slot          The slot number of the SD card to send the command to.
+  @param[in]  Rca           The relative device address of selected device.
+  @param[out] Csd           The buffer to store the content of the CSD register.
+                            Note the caller should ignore the lowest byte of this
+                            buffer as the content of this byte is meaningless even
+                            if the operation succeeds.
+
+  @retval EFI_SUCCESS       The operation is done correctly.
+  @retval Others            The operation fails.
+
+**/
+EFI_STATUS
+SdCardGetCsd (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
+  IN     UINT8                          Slot,
+  IN     UINT16                         Rca,
+     OUT SD_CSD                         *Csd
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS                            Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+  Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
+  Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
+  SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;
+  SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
+  SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
+  SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
+  Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+  if (!EFI_ERROR (Status)) {
+    //
+    // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
+    //
+    CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);
+  }
+
+  return Status;
+}
+
+/**
+  Send command SEND_CSD to the SD device to get the data of the CSD register.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+  @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
+  @param[in]  Slot          The slot number of the SD card to send the command to.
+  @param[in]  Rca           The relative device address of selected device.
+  @param[out] Scr           The buffer to store the content of the SCR register.
+
+  @retval EFI_SUCCESS       The operation is done correctly.
+  @retval Others            The operation fails.
+
+**/
+EFI_STATUS
+SdCardGetScr (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
+  IN     UINT8                          Slot,
+  IN     UINT16                         Rca,
+     OUT SD_SCR                         *Scr
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS                            Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
+  Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
+  SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
+  SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+  SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
+
+  Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;
+  SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
+  SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+
+  Packet.InDataBuffer     = Scr;
+  Packet.InTransferLength = sizeof (SD_SCR);
+
+  Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+
+  return Status;
+}
 /**
   Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.
@@ -785,8 +891,8 @@ SdCardSetBusMode (
   UINT8                        BusWidth;
   UINT8                        AccessMode;
   UINT8                        HostCtrl1;
+  UINT8                        HostCtrl2;
   UINT8                        SwitchResp[64];
-  SD_MMC_BUS_MODE              Timing;
   SD_MMC_HC_PRIVATE_DATA       *Private;
   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
@@ -818,23 +924,18 @@ SdCardSetBusMode (
   if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
     ClockFreq = 208;
     AccessMode = 3;
-    Timing = SdMmcUhsSdr104;
   } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
     ClockFreq = 100;
     AccessMode = 2;
-    Timing = SdMmcUhsSdr50;
   } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
     ClockFreq = 50;
     AccessMode = 4;
-    Timing = SdMmcUhsDdr50;
   } else if ((SwitchResp[13] & BIT1) != 0) {
     ClockFreq = 50;
     AccessMode = 1;
-    Timing = SdMmcUhsSdr25;
   } else {
     ClockFreq = 25;
     AccessMode = 0;
-    Timing = SdMmcUhsSdr12;
   }
   Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
@@ -860,32 +961,20 @@ SdCardSetBusMode (
     }
   }
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+  HostCtrl2 = AccessMode;
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
-    Status = mOverride->NotifyPhase (
-                          Private->ControllerHandle,
-                          Slot,
-                          EdkiiSdMmcSwitchClockFreqPost,
-                          &Timing
-                          );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
-        __FUNCTION__,
-        Status
-        ));
-      return Status;
-    }
+  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
   if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {
@@ -996,10 +1085,9 @@ SdCardIdentification (
     return Status;
   }
-  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
-      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
+  if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
     S18r = TRUE;
-  } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {
+  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
     S18r = FALSE;
   } else {
     ASSERT (FALSE);
@@ -1065,7 +1153,7 @@ SdCardIdentification (
         goto Error;
       }
-      SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+      SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]);
       gBS->Stall (1000);

please check it!
Br,
Mike

From: Mike Li (WH)
Sent: 2019年1月23日 18:39
To: Mike Li (WH); Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); edk2-devel@lists.01.org
Subject: RE: [edk2] [patch_2] make EDK Driver Support BH720+EMMC chip

Hi, all

The following modifications are made to enable EDK Driver Support BH720 CHIP.

--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c            2019-01-21 15:36:12.186739600 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c           2019-01-10 14:34:23.072538900 -0800
@@ -1,7 +1,6 @@
/** @file
   This file provides some helper functions which are specific for EMMC device.

-  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -527,17 +526,35 @@ EmmcTuningClkForHs200 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
+
+  if(BhtHostPciSupport(PciIo)){
+                              //set data transfer with 4bit
+                              Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
+                              //enable hardware tuning
+                              HostCtrl2 = (~0x10);
+                              Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2);
+
+                Status = EmmcSendTuningBlk (PassThru, Slot, 4);
+                if (EFI_ERROR (Status)) {
+                              DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+                              return Status;
+                }
+
+  }
   //
   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
   //
   Retry = 0;
   do {
-    Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
-      return Status;
-    }
-
+              if(!BhtHostPciSupport(PciIo)){
+                  Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
+                  if (EFI_ERROR (Status)) {
+                    DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+                    return Status;
+                  }
+              } else {
+                              gBS->Stall(5000);
+              }
     Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
     if (EFI_ERROR (Status)) {
       return Status;
@@ -548,6 +565,10 @@ EmmcTuningClkForHs200 (
     }

     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
+                if(BhtHostPciSupport(PciIo)){
+                              //set data transfer with default
+                              Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
+                              }
       return EFI_SUCCESS;
     }
   } while (++Retry < 40);
@@ -652,7 +673,6 @@ EmmcSwitchBusWidth (
   @param[in] Slot           The slot number of the SD card to send the command to.
   @param[in] Rca            The relative device address to be assigned.
   @param[in] HsTiming       The value to be written to HS_TIMING field of EXT_CSD register.
-  @param[in] Timing         The bus mode timing indicator.
   @param[in] ClockFreq      The max clock frequency to be set, the unit is MHz.

   @retval EFI_SUCCESS       The operation is done correctly.
@@ -666,7 +686,6 @@ EmmcSwitchClockFreq (
   IN UINT8                              Slot,
   IN UINT16                             Rca,
   IN UINT8                              HsTiming,
-  IN SD_MMC_BUS_MODE                    Timing,
   IN UINT32                             ClockFreq
   )
{
@@ -708,28 +727,7 @@ EmmcSwitchClockFreq (
   //
   // Convert the clock freq unit from MHz to KHz.
   //
-  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
-    Status = mOverride->NotifyPhase (
-                          Private->ControllerHandle,
-                          Slot,
-                          EdkiiSdMmcSwitchClockFreqPost,
-                          &Timing
-                          );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
-        __FUNCTION__,
-        Status
-        ));
-      return Status;
-    }
-  }
+  Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);

   return Status;
}
@@ -764,13 +762,10 @@ EmmcSwitchToHighSpeed (
   IN UINT8                              BusWidth
   )
{
-  EFI_STATUS              Status;
-  UINT8                   HsTiming;
-  UINT8                   HostCtrl1;
-  SD_MMC_BUS_MODE         Timing;
-  SD_MMC_HC_PRIVATE_DATA  *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl1;
+  UINT8               HostCtrl2;

   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
   if (EFI_ERROR (Status)) {
@@ -785,21 +780,31 @@ EmmcSwitchToHighSpeed (
     return Status;
   }

+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50
+  //
   if (IsDdr) {
-    Timing = SdMmcMmcHsDdr;
+    HostCtrl2 = BIT2;
   } else if (ClockFreq == 52) {
-    Timing = SdMmcMmcHsSdr;
+    HostCtrl2 = BIT0;
   } else {
-    Timing = SdMmcMmcLegacy;
+    HostCtrl2 = 0;
   }
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }

   HsTiming = 1;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);

   return Status;
}
@@ -831,13 +836,10 @@ EmmcSwitchToHS200 (
   IN UINT8                              BusWidth
   )
{
-  EFI_STATUS               Status;
-  UINT8                    HsTiming;
-  UINT16                   ClockCtrl;
-  SD_MMC_BUS_MODE          Timing;
-  SD_MMC_HC_PRIVATE_DATA  *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl2;
+  UINT16              ClockCtrl;

   if ((BusWidth != 4) && (BusWidth != 8)) {
     return EFI_INVALID_PARAMETER;
@@ -857,29 +859,60 @@ EmmcSwitchToHS200 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
-  Timing = SdMmcMmcHs200;
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to SDR104
+  //
+  HostCtrl2 = BIT0 | BIT1;
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
   //
   // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
   //
-  Status = SdMmcHcWaitMmioSet (
-             PciIo,
-             Slot,
-             SD_MMC_HC_CLOCK_CTRL,
-             sizeof (ClockCtrl),
-             BIT1,
-             BIT1,
-             SD_MMC_HC_GENERIC_TIMEOUT
+  if (BhtHostPciSupport(PciIo)) {
+                  Status = SdMmcHcWaitMmioSet (
+               PciIo,
+               Slot,
+               0x1cc,
+               sizeof (ClockCtrl),
+               BIT14,
+               BIT14,
+               SD_MMC_HC_GENERIC_TIMEOUT
+             );
+  }
+  else {
+    Status = SdMmcHcWaitMmioSet (
+               PciIo,
+               Slot,
+               SD_MMC_HC_CLOCK_CTRL,
+               sizeof (ClockCtrl),
+               BIT1,
+               BIT1,
+               SD_MMC_HC_GENERIC_TIMEOUT
              );
+  }
   if (EFI_ERROR (Status)) {
     return Status;
   }
+
+  if (BhtHostPciSupport(PciIo)){
+    //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
+    UINT32 value32;
+    while (1) {
+                Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
+                if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01))
+                  break;
+    }
+  }
   //
   // Set SD Clock Enable in the Clock Control register to 1
   //
@@ -887,12 +920,33 @@ EmmcSwitchToHS200 (
   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);

   HsTiming = 2;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
   if (EFI_ERROR (Status)) {
     return Status;
   }

-  Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
+  if (BhtHostPciSupport(PciIo)){
+    Status = SdMmcHcWaitMmioSet (
+                                                PciIo,
+                                                 Slot,
+               0x1cc,
+                                                 sizeof (ClockCtrl),
+                                                 BIT11,
+                                                 BIT11,
+                                                 SD_MMC_CLOCK_STABLE_TIMEOUT
+                                                 );
+    if (EFI_ERROR(Status)) {
+                DbgMsg(L"Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
+                return Status;
+      }
+  }
+
+  if (EFI_ERROR(Status)) {
+              DbgMsg(L"Emmc tuning failed\n");
+              return Status;
+  }
+
+

   return Status;
}
@@ -922,12 +976,9 @@ EmmcSwitchToHS400 (
   IN UINT32                             ClockFreq
   )
{
-  EFI_STATUS                 Status;
-  UINT8                      HsTiming;
-  SD_MMC_BUS_MODE            Timing;
-  SD_MMC_HC_PRIVATE_DATA     *Private;
-
-  Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  EFI_STATUS          Status;
+  UINT8               HsTiming;
+  UINT8               HostCtrl2;

   Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
   if (EFI_ERROR (Status)) {
@@ -937,7 +988,7 @@ EmmcSwitchToHS400 (
   // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.
   //
   HsTiming = 1;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -948,16 +999,25 @@ EmmcSwitchToHS400 (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-
-  Timing = SdMmcMmcHs400;
-
-  Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+  //
+  // Clean UHS Mode Select field of Host Control 2 reigster before update
+  //
+  HostCtrl2 = (UINT8)~0x7;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Set UHS Mode Select field of Host Control 2 reigster to HS400
+  //
+  HostCtrl2 = BIT0 | BIT2;
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   if (EFI_ERROR (Status)) {
     return Status;
   }

   HsTiming = 3;
-  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+  Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);

   return Status;
}
@@ -1008,7 +1068,7 @@ EmmcSetBusMode (
     return Status;
   }

-  ASSERT (Private->BaseClkFreq[Slot] != 0);
+  ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
   //
   // Check if the Host Controller support 8bits bus width.
   //
@@ -1080,6 +1140,42 @@ EmmcSetBusMode (
     // Execute HS200 timing switch procedure
     //
     Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+              if (EFI_ERROR(Status)) {
+      if (BhtHostPciSupport(PciIo)) {
+                                UINT32 val32;
+                                DbgMsg(L"switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
+                                ClockFreq = 100;
+
+                                SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32);
+                                val32 &= ~BIT22;
+                    SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32);
+                                val32 = (BIT26 | BIT25);
+                    SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32);
+
+                                Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+                                if (EFI_ERROR(Status)) {
+                                              if (((ExtCsd.DeviceType & BIT1)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+                                               DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n");
+
+                                    HsTiming  = 1;
+              IsDdr     = FALSE;
+              ClockFreq = 52;
+                                                Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+                                              }
+                                              else if (((ExtCsd.DeviceType & BIT0)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+                                                DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n");
+
+                                                HsTiming  = 1;
+              IsDdr     = FALSE;
+              ClockFreq = 26;
+                                                Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+                                              }
+                                              else {
+                                               DbgMsg(L"switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
+                                              }
+                                }
+                              }
+    }
   } else {
     //
     // Execute High Speed timing switch procedure

Please check it!
Br,
Mike

From: Mike Li (WH)
Sent: 2019年1月23日 17:29
To: Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); 'edk2-devel@lists.01.org'
Subject: [edk2] [patch_1] make EDK Driver Support BH720+EMMC chip


Hi, all

The following modifications are made to enable EDK Driver Support BH720 CHIP.

--- /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c            2019-01-10 14:35:21.342736200 -0800
+++ /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c         2019-01-21 15:36:12.195715300 -0800
@@ -4,6 +4,7 @@

   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.

+  Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -16,8 +17,6 @@
**/

 #include "SdMmcPciHcDxe.h"
-int g_deviceId = 0;
-

 /**
   Dump the content of SD/MMC host controller's Capability Register.
@@ -47,7 +46,8 @@ DumpCapabilityReg (
   DEBUG ((DEBUG_INFO, "   Voltage 3.3       %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 3.0       %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Voltage 1.8       %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
-  DEBUG ((DEBUG_INFO, "   64-bit Sys Bus    %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+  DEBUG ((DEBUG_INFO, "   V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   Async Interrupt   %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
   DEBUG ((DEBUG_INFO, "   SlotType          "));
   if (Capability->SlotType == 0x00) {
@@ -419,9 +419,39 @@ SdMmcHcWaitMmioSet (
}

 /**
+  Get the controller version information from the specified slot.
+
+  @param[in]  PciIo           The PCI IO protocol instance.
+  @param[in]  Slot            The slot number of the SD card to send the command to.
+  @param[out] Version         The buffer to store the version information.
+
+  @retval EFI_SUCCESS         The operation executes successfully.
+  @retval Others              The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+  IN     EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN     UINT8                Slot,
+  OUT    UINT16               *Version
+  )
+{
+  EFI_STATUS                Status;
+
+  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *Version &= 0xFF;
+
+  return EFI_SUCCESS;
+}
+
+/**
   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.
@@ -430,18 +460,38 @@ 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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC pre reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+      return Status;
+    }
+  }

-  SwReset = 0xFF;
-  Status  = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
+  PciIo   = Private->PciIo;
+  SwReset = BIT0;
+  Status  = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);

   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status));
+    DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));
     return Status;
   }

@@ -450,7 +500,7 @@ SdMmcHcReset (
              Slot,
              SD_MMC_HC_SW_RST,
              sizeof (SwReset),
-             0xFF,
+             BIT0,
              0x00,
              SD_MMC_HC_GENERIC_TIMEOUT
              );
@@ -458,10 +508,33 @@ 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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post reset notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }

   return Status;
}
@@ -680,7 +753,8 @@ SdMmcHcStopClock (
   @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] ClockFreq      The max clock frequency to be set. The unit is KHz.
-  @param[in] Capability     The capability of the slot.
+  @param[in] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -691,23 +765,21 @@ SdMmcHcClockSupply (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
   IN UINT64                 ClockFreq,
-  IN SD_MMC_HC_SLOT_CAP     Capability
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
{
   EFI_STATUS                Status;
-  UINT32                    BaseClkFreq;
   UINT32                    SettingFreq;
   UINT32                    Divisor;
   UINT32                    Remainder;
-  UINT16                    ControllerVer;
   UINT16                    ClockCtrl;

   //
   // Calculate a divisor for SD clock frequency
   //
-  ASSERT (Capability.BaseClkFreq != 0);
+  ASSERT (BaseClkFreq != 0);

-  BaseClkFreq = Capability.BaseClkFreq;
   if (ClockFreq == 0) {
     return EFI_INVALID_PARAMETER;
   }
@@ -736,17 +808,15 @@ SdMmcHcClockSupply (

   DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));

-  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
   //
   // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
   //
-  if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
+  if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+      (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
     ASSERT (Divisor <= 0x3FF);
     ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
-  } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+  } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+             (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
     //
     // Only the most significant bit can be used as divisor.
     //
@@ -894,11 +964,62 @@ SdMmcHcSetBusWidth (
}

 /**
-  Supply SD/MMC card with lowest clock frequency at initialization.
+  Configure V4 controller enhancements 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.
+  @param[in] ControllerVer  The version of host controller.
+
+  @retval EFI_SUCCESS       The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_HC_SLOT_CAP     Capability,
+  IN UINT16                 ControllerVer
+  )
+{
+  EFI_STATUS                Status;
+  UINT16                    HostCtrl2;
+
+  //
+  // Check if controller version V4 or higher
+  //
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    HostCtrl2 = SD_MMC_HC_V4_EN;
+    //
+    // Check if V4 64bit support is available
+    //
+    if (Capability.SysBus64V4 != 0) {
+      HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+    }
+    //
+    // Check if controller version V4.10 or higher
+    //
+    if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+      HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+      DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+    }
+    Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Supply SD/MMC card with lowest clock frequency 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] BaseClkFreq    The base clock frequency of host controller in MHz.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The clock is supplied successfully.
   @retval Others            The clock isn't supplied successfully.
@@ -908,16 +1029,20 @@ EFI_STATUS
SdMmcHcInitClockFreq (
   IN EFI_PCI_IO_PROTOCOL    *PciIo,
   IN UINT8                  Slot,
-  IN SD_MMC_HC_SLOT_CAP     Capability
+  IN UINT32                 BaseClkFreq,
+  IN UINT16                 ControllerVer
   )
{
   EFI_STATUS                Status;
   UINT32                    InitFreq;

   //
-  // Calculate a divisor for SD clock frequency
+  // According to SDHCI specification ver. 4.2, BaseClkFreq field value of
+  // the Capability Register 1 can be zero, which means a need for obtaining
+  // the clock frequency via another method. Fail in case it is not updated
+  // by SW at this point.
   //
-  if (Capability.BaseClkFreq == 0) {
+  if (BaseClkFreq == 0) {
     //
     // Don't support get Base Clock Frequency information via another method
     //
@@ -927,7 +1052,7 @@ SdMmcHcInitClockFreq (
   // Supply 400KHz clock frequency at initialization phase.
   //
   InitFreq = 400;
-  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);
+  Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
   return Status;
}

@@ -988,15 +1113,6 @@ SdMmcHcInitPowerVoltage (
   // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
   //
   Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);
-  if (BhtHostPciSupport(PciIo)){
-                // 1.8V signaling enable
-                HostCtrl2  = BIT3;
-                Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
-                gBS->Stall (5000);
-                if (EFI_ERROR (Status)) {
-                              return Status;
-                }
-  }

   return Status;
}
@@ -1032,9 +1148,8 @@ 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.

   @retval EFI_SUCCESS       The host controller is initialized successfully.
   @retval Others            The host controller isn't initialized successfully.
@@ -1042,96 +1157,164 @@ 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;
-  UINT32           value32;
-
-  if (BhtHostPciSupport(PciIo)){
-
-                              DbgMsg(L"find bht emmc chip\n");
-                              /* FET on */
-                              PciBhtOr32(PciIo, 0xEC, 0x3);
-                              /* Led on */
-                              //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13);
-                              PciBhtOr32(PciIo, 0xD4, BIT6);
-                              /* Set 1.8v emmc signaling flag */
-                              PciBhtOr32(PciIo, 0x308, BIT4);
-                              /* Set 200MBaseClock */
-                              value32 = PciBhtRead32(PciIo, 0x304);
-                              value32 &= 0x0000FFFF;
-                              value32 |= 0x25100000;
-                              PciBhtWrite32(PciIo, 0x304, value32);
-                              PciBhtOr32(PciIo, 0x3E4, BIT22);
-                              PciBhtWrite32(PciIo, 0x300, 0x21400033);
-
-                              //enable internal clk
-                              value32 = BIT0;
-                              Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32);
-
-                              //reset pll start
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                              value32 |= BIT12;
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-                              gBS->Stall(1);
-
-                              //reset pll end
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32);
-                              value32 &= ~BIT12;
-                              value32 |= BIT18;
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-
-                              //wait BaseClk stable 0x1CC bit14
-                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                              while(!(value32&BIT14)){
-                                              gBS->Stall(100);
-                                              Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                                              DbgMsg(L"1CC=0x%08x\n", value32);
-                              }
-
-                              if (value32 & BIT18)
-                              {
-                                //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
-                                while (1) {
-                                  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
-            if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01))
-              break;
-                                }
-                                //force pll active end
-                                Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
-                                value32 &= ~BIT18;
-                                Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-                              }
-
-                              Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
-                              if (EFI_ERROR (Status)) {
-                                  DbgMsg(L"emmc host init failure\n");
-                                  return Status;
-                              }
-
-
-  }
-
-  Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (!BhtHostPciSupport(PciIo)){
-                Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
-                if (EFI_ERROR (Status)) {
-                  return 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,
+                          NULL);
+    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 = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
-
+
+  Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
   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,
+                          NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN,
+        "%a: SD/MMC post init notifier callback failed - %r\n",
+        __FUNCTION__, Status));
+    }
+  }
   return Status;
}

 /**
+  Set SD Host Controler control 2 registry according to selected speed.
+
+  @param[in] ControllerHandle The handle of the controller.
+  @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] Timing           The timing to select.
+
+  @retval EFI_SUCCESS         The timing is set successfully.
+  @retval Others              The timing isn't set successfully.
+**/
+EFI_STATUS
+SdMmcHcUhsSignaling (
+  IN EFI_HANDLE             ControllerHandle,
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8                  Slot,
+  IN SD_MMC_BUS_MODE        Timing
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      HostCtrl2;
+
+  HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;
+  Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  switch (Timing) {
+    case SdMmcUhsSdr12:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;
+      break;
+    case SdMmcUhsSdr25:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;
+      break;
+    case SdMmcUhsSdr50:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;
+      break;
+    case SdMmcUhsSdr104:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;
+      break;
+    case SdMmcUhsDdr50:
+      HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;
+      break;
+    case SdMmcMmcLegacy:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;
+      break;
+    case SdMmcMmcHsSdr:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;
+      break;
+    case SdMmcMmcHsDdr:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;
+      break;
+    case SdMmcMmcHs200:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;
+      break;
+    case SdMmcMmcHs400:
+      HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;
+      break;
+    default:
+     HostCtrl2 = 0;
+     break;
+  }
+  Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+    Status = mOverride->NotifyPhase (
+                          ControllerHandle,
+                          Slot,
+                          EdkiiSdMmcUhsSignaling,
+                          &Timing
+                          );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: SD/MMC uhs signaling notifier callback failed - %r\n",
+        __FUNCTION__,
+        Status
+        ));
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Turn on/off LED.

   @param[in] PciIo          The PCI IO protocol instance.
@@ -1166,9 +1349,10 @@ SdMmcHcLedOnOff (
/**
   Build ADMA descriptor table for transfer.

-  Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+  Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.

   @param[in] Trb            The pointer to the SD_MMC_HC_TRB instance.
+  @param[in] ControllerVer  The version of host controller.

   @retval EFI_SUCCESS       The ADMA descriptor table is created successfully.
   @retval Others            The ADMA descriptor table isn't created successfully.
@@ -1176,7 +1360,8 @@ SdMmcHcLedOnOff (
**/
EFI_STATUS
BuildAdmaDescTable (
-  IN SD_MMC_HC_TRB          *Trb
+  IN SD_MMC_HC_TRB          *Trb,
+  IN UINT16                 ControllerVer
   )
{
   EFI_PHYSICAL_ADDRESS      Data;
@@ -1184,49 +1369,93 @@ BuildAdmaDescTable (
   UINT64                    Entries;
   UINT32                    Index;
   UINT64                    Remaining;
-  UINT32                    Address;
+  UINT64                    Address;
   UINTN                     TableSize;
   EFI_PCI_IO_PROTOCOL       *PciIo;
   EFI_STATUS                Status;
   UINTN                     Bytes;
+  BOOLEAN                   AddressingMode64;
+  BOOLEAN                   DataLength26;
+  UINT32                    AdmaMaxDataPerLine;
+  UINT32                    DescSize;
+  VOID                      *AdmaDesc;
+
+  AddressingMode64   = FALSE;
+  DataLength26       = FALSE;
+  AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
+  DescSize           = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+  AdmaDesc           = NULL;

   Data    = Trb->DataPhy;
   DataLen = Trb->DataLen;
   PciIo   = Trb->Private->PciIo;
+
   //
-  // Only support 32bit ADMA Descriptor Table
+  // Detect whether 64bit addressing is supported.
   //
-  if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+  if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+      DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
+    }
+  }
+  //
+  // Check for valid ranges in 32bit ADMA Descriptor Table
+  //
+  if (!AddressingMode64 &&
+      ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
     return EFI_INVALID_PARAMETER;
   }
   //
-  // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
-  // for 32-bit address descriptor table.
+  // Check address field alignment
   //
-  if ((Data & (BIT0 | BIT1)) != 0) {
-    DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+  if (AddressingMode64) {
+    //
+    // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+    }
+  } else {
+    //
+    // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+    //
+    if ((Data & (BIT0 | BIT1)) != 0) {
+      DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+    }
+  }
+  //
+  // Detect whether 26bit data length is supported.
+  //
+  Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                               SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
+  if (!EFI_ERROR (Status)) {
+    DataLength26 = TRUE;
+    AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
   }

-  Entries   = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
-  TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+  Entries   = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+  TableSize = (UINTN)MultU64x32 (Entries, DescSize);
   Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
   Status = PciIo->AllocateBuffer (
                     PciIo,
                     AllocateAnyPages,
                     EfiBootServicesData,
                     EFI_SIZE_TO_PAGES (TableSize),
-                    (VOID **)&Trb->AdmaDesc,
+                    (VOID **)&AdmaDesc,
                     0
                     );
   if (EFI_ERROR (Status)) {
     return EFI_OUT_OF_RESOURCES;
   }
-  ZeroMem (Trb->AdmaDesc, TableSize);
+  ZeroMem (AdmaDesc, TableSize);
   Bytes  = TableSize;
   Status = PciIo->Map (
                     PciIo,
                     EfiPciIoOperationBusMasterCommonBuffer,
-                    Trb->AdmaDesc,
+                    AdmaDesc,
                     &Bytes,
                     &Trb->AdmaDescPhy,
                     &Trb->AdmaMap
@@ -1239,12 +1468,13 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
              PciIo,
              EFI_SIZE_TO_PAGES (TableSize),
-             Trb->AdmaDesc
+             AdmaDesc
              );
     return EFI_OUT_OF_RESOURCES;
   }

-  if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+  if ((!AddressingMode64) &&
+      (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
     //
     // The ADMA doesn't support 64bit addressing.
     //
@@ -1255,35 +1485,71 @@ BuildAdmaDescTable (
     PciIo->FreeBuffer (
       PciIo,
       EFI_SIZE_TO_PAGES (TableSize),
-      Trb->AdmaDesc
+      AdmaDesc
     );
     return EFI_DEVICE_ERROR;
   }

   Remaining = DataLen;
-  Address   = (UINT32)Data;
+  Address   = Data;
+  if (!AddressingMode64) {
+    Trb->Adma32Desc = AdmaDesc;
+    Trb->Adma64Desc = NULL;
+  } else {
+    Trb->Adma64Desc = AdmaDesc;
+    Trb->Adma32Desc = NULL;
+  }
   for (Index = 0; Index < Entries; Index++) {
-    if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = (UINT16)Remaining;
-      Trb->AdmaDesc[Index].Address = Address;
-      break;
+    if (!AddressingMode64) {
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+        }
+        Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+        break;
+      } else {
+        Trb->Adma32Desc[Index].Valid = 1;
+        Trb->Adma32Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma32Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma32Desc[Index].LowerLength  = 0;
+        Trb->Adma32Desc[Index].Address = (UINT32)Address;
+      }
     } else {
-      Trb->AdmaDesc[Index].Valid = 1;
-      Trb->AdmaDesc[Index].Act   = 2;
-      Trb->AdmaDesc[Index].Length  = 0;
-      Trb->AdmaDesc[Index].Address = Address;
+      if (Remaining <= AdmaMaxDataPerLine) {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = (UINT16)RShiftU64 (Remaining, 16);
+        }
+        Trb->Adma64Desc[Index].LowerLength  = (UINT16)(Remaining & MAX_UINT16);
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+        break;
+      } else {
+        Trb->Adma64Desc[Index].Valid = 1;
+        Trb->Adma64Desc[Index].Act   = 2;
+        if (DataLength26) {
+          Trb->Adma64Desc[Index].UpperLength  = 0;
+        }
+        Trb->Adma64Desc[Index].LowerLength  = 0;
+        Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+        Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+      }
     }

-    Remaining -= ADMA_MAX_DATA_PER_LINE;
-    Address   += ADMA_MAX_DATA_PER_LINE;
+    Remaining -= AdmaMaxDataPerLine;
+    Address   += AdmaMaxDataPerLine;
   }

   //
   // Set the last descriptor line as end of descriptor table
   //
-  Trb->AdmaDesc[Index].End = 1;
+  AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
   return EFI_SUCCESS;
}

@@ -1381,7 +1647,7 @@ SdMmcCreateTrb (
       Trb->Mode = SdMmcNoData;
     } else if (Private->Capability[Slot].Adma2 != 0) {
       Trb->Mode = SdMmcAdmaMode;
-      Status = BuildAdmaDescTable (Trb);
+      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
       if (EFI_ERROR (Status)) {
         PciIo->Unmap (PciIo, Trb->DataMap);
         goto Error;
@@ -1427,11 +1693,18 @@ SdMmcFreeTrb (
       Trb->AdmaMap
     );
   }
-  if (Trb->AdmaDesc != NULL) {
+  if (Trb->Adma32Desc != NULL) {
+    PciIo->FreeBuffer (
+      PciIo,
+      Trb->AdmaPages,
+      Trb->Adma32Desc
+    );
+  }
+  if (Trb->Adma64Desc != NULL) {
     PciIo->FreeBuffer (
       PciIo,
       Trb->AdmaPages,
-      Trb->AdmaDesc
+      Trb->Adma64Desc
     );
   }
   if (Trb->DataMap != NULL) {
@@ -1571,12 +1844,15 @@ SdMmcExecTrb (
   UINT16                              Cmd;
   UINT16                              IntStatus;
   UINT32                              Argument;
-  UINT16                              BlkCount;
+  UINT32                              BlkCount;
   UINT16                              BlkSize;
   UINT16                              TransMode;
   UINT8                               HostCtrl1;
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT64                              AdmaAddr;
+  BOOLEAN                             AddressingMode64;
+
+  AddressingMode64 = FALSE;

   Packet = Trb->Packet;
   PciIo  = Trb->Private->PciIo;
@@ -1609,13 +1885,28 @@ SdMmcExecTrb (

   SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);

+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+    Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+                                 SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+    if (!EFI_ERROR (Status)) {
+      AddressingMode64 = TRUE;
+    }
+  }
+
   if (Trb->Mode == SdMmcSdmaMode) {
-    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+    if ((!AddressingMode64) &&
+        ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
       return EFI_INVALID_PARAMETER;
     }

-    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
-    Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+    SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+    } else {
+      Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+    }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
@@ -1645,9 +1936,13 @@ SdMmcExecTrb (
     //
     // Calcuate Block Count.
     //
-    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+    BlkCount = (Trb->DataLen / Trb->BlockSize);
+  }
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+  } else {
+    Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
   }
-  Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1743,7 +2038,7 @@ SdMmcCheckTrbResult (
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
   UINT16                              IntStatus;
   UINT32                              Response[4];
-  UINT32                              SdmaAddr;
+  UINT64                              SdmaAddr;
   UINT8                               Index;
   UINT8                               SwReset;
   UINT32                              PioLength;
@@ -1867,8 +2162,19 @@ SdMmcCheckTrbResult (
     //
     // Update SDMA Address register.
     //
-    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
-    Status   = SdMmcHcRwMmio (
+    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+      Status = SdMmcHcRwMmio (
+                 Private->PciIo,
+                 Trb->Slot,
+                 SD_MMC_HC_ADMA_SYS_ADDR,
+                 FALSE,
+                 sizeof (UINT64),
+                 &SdmaAddr
+                 );
+    } else {
+      Status = SdMmcHcRwMmio (
                  Private->PciIo,
                  Trb->Slot,
                  SD_MMC_HC_SDMA_ADDR,
@@ -1876,10 +2182,12 @@ SdMmcCheckTrbResult (
                  sizeof (UINT32),
                  &SdmaAddr
                  );
+    }
+
     if (EFI_ERROR (Status)) {
       goto Done;
     }
-    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
   }

   if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
@@ -2000,281 +2308,3 @@ SdMmcWaitTrbResult (
   return EFI_TIMEOUT;
}

-BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo)
-{
-              PCI_TYPE00                         Pci;
-
-              PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,
-                                                                0, sizeof Pci / sizeof (UINT32), &Pci);
-
-              DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId));
-
-              if (Pci.Hdr.VendorId != 0x1217)
-                              goto end;
-
-              switch (Pci.Hdr.DeviceId)
-              {
-                              case 0x8420:       //PCI_DEV_ID_SDS0
-                              case 0x8421:       //PCI_DEV_ID_SDS1
-                              case 0x8520:       //PCI_DEV_ID_FJ2
-                              case 0x8620:       //PCI_DEV_ID_SB0
-                              case 0x8621:       //PCI_DEV_ID_SB1
-                                              g_deviceId = Pci.Hdr.DeviceId;
-                                              return 1;
-                              default:
-                                              break;
-              }
-
-              end:
-              return 0;
-}
-
-void DbgNull(IN CONST CHAR16 * fmt, ...)
-{
-}
-
-UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
-              UINT32 arg;
-              PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg);
-              return arg;
-}
-
-void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value);
-}
-
-
-UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
-              UINT32 i = 0;
-              UINT32 tmp[3] = {0};
-
-              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                              (g_deviceId == PCI_DEV_ID_SDS1) ||
-                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                              (g_deviceId == PCI_DEV_ID_SB1))
-              {
-                              // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
-                              // Enable mapping
-
-                              // Check function conflict
-                              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB1))
-                              {
-                                              i = 0;
-                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-                                              while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
-                                              {
-                                                              if(i == 5)
-                                                              {
-                                                                              //DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                                                                              goto RD_DIS_MAPPING;
-                                                              }
-                                                                                              gBS->Stall(1000);
-                                                              i++;
-                                                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-
-                                              }
-                              }
-                              else if(g_deviceId == PCI_DEV_ID_SDS1)
-                              {
-                                              i = 0;
-                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-                                              while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
-                                              {
-                                                              if(i == 5)
-                                                              {
-                                                                              //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__));
-                                                                              goto RD_DIS_MAPPING;
-                                                              }
-                                                              gBS->Stall(1000);
-                                                              i++;
-                                                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-                                              }
-                              }
-
-                              // Check last operation is complete
-                              i = 0;
-                              while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-                              {
-                                              if(i == 5)
-                                              {
-                                                              //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl)));
-                                                              //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn)));
-                                                              //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                                                              goto RD_DIS_MAPPING;
-                                              }
-                                              gBS->Stall(1000);
-                                              i += 1;
-                              }
-
-                              // Set register address
-                              tmp[0] |= 0x40000000;
-                              tmp[0] |= offset;
-                              bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]);
-
-                              // Check read is complete
-                              i = 0;
-                              while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000)
-                              {
-                                              if(i == 5)
-                                              {
-                                                              //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__));
-                                                              goto RD_DIS_MAPPING;
-                                              }
-                                              gBS->Stall(1000);
-                                              i += 1;
-                              }
-
-                              // Get PCIR value
-                              tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal);
-
-RD_DIS_MAPPING:
-                              // Disable mapping
-                              bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-
-                              //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]);
-                              return tmp[1];
-              }
-
-              //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]);
-              return tmp[0];
-}
-
-void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 tmp = 0;
-    UINT32 i = 0;
-
-              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                              (g_deviceId == PCI_DEV_ID_SDS1) ||
-                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                              (g_deviceId == PCI_DEV_ID_SB1))
-    {
-        // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
-        // Upper caller doesn't need to set 0xD0.
-
-        // Enable mapping
-
-        // Check function conflict
-                              if((g_deviceId == PCI_DEV_ID_SDS0) ||
-                                                              (g_deviceId == PCI_DEV_ID_FJ2) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB0) ||
-                                                              (g_deviceId == PCI_DEV_ID_SB1))
-        {
-            i = 0;
-            bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-            while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
-            {
-                if(i == 5)
-                {
-                    //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                    goto WR_DIS_MAPPING;
-                }
-
-                gBS->Stall(1000);
-                i++;
-                bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-            }
-        }
-        else if(g_deviceId == PCI_DEV_ID_SDS1)
-        {
-            i = 0;
-            bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-
-            while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
-            {
-                if(i == 5)
-                {
-                    //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
-                    goto WR_DIS_MAPPING;
-                }
-
-                gBS->Stall(1000);
-                i++;
-                bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-            }
-        }
-
-        // Enable MEM access
-        bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000);
-        bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
-        // Check last operation is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                goto WR_DIS_MAPPING;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-        // Set write value
-        bht_writel(PciIo, BHT_PCIRMappingVal, value);
-        // Set register address
-        tmp |= 0x80000000;
-        tmp |= offset;
-        bht_writel(PciIo, BHT_PCIRMappingCtl, tmp);
-
-        // Check write is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__));
-                goto WR_DIS_MAPPING;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-WR_DIS_MAPPING:
-        // Disable MEM access
-        bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001);
-        bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
-        // Check last operation is complete
-        i = 0;
-        while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
-        {
-            if(i == 5)
-            {
-                //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
-                break;
-            }
-            gBS->Stall(1000);
-            i += 1;
-        }
-
-        // Disable function conflict
-
-        // Disable mapping
-        bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-    }
-}
-
-void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 arg;
-              arg = PciBhtRead32(PciIo, offset);
-              PciBhtWrite32(PciIo, offset, value | arg);
-}
-
-void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
-              UINT32 arg;
-              arg = PciBhtRead32(PciIo, offset);
-              PciBhtWrite32(PciIo, offset, value & arg);
-}
-


Please check it!
Br,
Mike

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-01-23 10:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-23 10:39 [patch_2] make EDK Driver Support BH720+EMMC chip Mike Li (WH)
2019-01-23 10:45 ` [patch_3] " Mike Li (WH)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox