[edk2-devel] [PATCH v3 3/8] Sophgo/SG2042Pkg: Add Sophgo SDHCI driver.

caiyuqing_hz@163.com posted 8 patches 1 year ago
There is a newer version of this series
[edk2-devel] [PATCH v3 3/8] Sophgo/SG2042Pkg: Add Sophgo SDHCI driver.
Posted by caiyuqing_hz@163.com 1 year ago
From: caiyuqing379 <202235273@mail.sdu.edu.cn>

This driver implements Sophgo SDHCI controller, which provides
the necessary interfaces for handling communication and data
transfer with SD cards.

Signed-off-by: caiyuqing379 <202235273@mail.sdu.edu.cn>
Co-authored-by: USER0FISH <libing1202@outlook.com>
Cc: dahogn <dahogn@hotmail.com>
Cc: meng-cz <mengcz1126@gmail.com>
Cc: yli147 <yong.li@intel.com>
Cc: ChaiEvan <evan.chai@intel.com>
Cc: Sunil V L <sunilvl@ventanamicro.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
---
 .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf |  47 +
 .../SG2042Pkg/Drivers/SdHostDxe/SdHci.h       | 309 ++++++
 .../SG2042Pkg/Drivers/SdHostDxe/SdHci.c       | 929 ++++++++++++++++++
 .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c   | 450 +++++++++
 4 files changed, 1735 insertions(+)
 create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
 create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
 create mode 100755 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
 create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c

diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
new file mode 100644
index 000000000000..f4f51d8fde74
--- /dev/null
+++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
@@ -0,0 +1,47 @@
+## @file
+#  Component description file for the SD Host Controller DXE driver module.
+#
+#  Copyright (c) 2019, ARM Limited. All rights reserved.
+#  Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+#  Copyright (c) Microsoft Corporation. All rights reserved.
+#  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = SdHostDxe
+  FILE_GUID                      = 11322596-DD4F-47FA-9E6C-CE787E11E4B1
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SdHostInitialize
+
+[Sources]
+  SdHci.c
+  SdHci.h
+  SdHostDxe.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Silicon/Sophgo/SG2042Pkg/SG2042Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  UefiRuntimeServicesTableLib
+
+[Protocols]
+  gSophgoMmcHostProtocolGuid        ## PRODUCES
+
+[FixedPcd]
+  gSophgoSG2042PlatformPkgTokenSpaceGuid.PcdSG2042SDIOBase        ## CONSUMES
+  gSophgoSG2042PlatformPkgTokenSpaceGuid.PcdForceNoMMU            ## CONSUMES
diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
new file mode 100644
index 000000000000..d9a9c88674e6
--- /dev/null
+++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
@@ -0,0 +1,309 @@
+/** @file
+  The header file that provides definitions and function declarations
+  related to the SD Host Controller Interface (SDHCI) for SD card host controllers.
+
+  Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-3-Clause
+
+**/
+
+#ifndef _SD_HCI_H_
+#define _SD_HCI_H_
+
+#define SDIO_BASE                       (FixedPcdGet64(PcdSG2042SDIOBase))
+#define SDHCI_DMA_ADDRESS               0x00
+#define SDHCI_BLOCK_SIZE                0x04
+#define SDHCI_MAKE_BLKSZ(dma, blksz)    ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
+#define SDHCI_BLOCK_COUNT               0x06
+#define SDHCI_ARGUMENT                  0x08
+#define SDHCI_TRANSFER_MODE             0x0C
+#define SDHCI_TRNS_DMA                  BIT0
+#define SDHCI_TRNS_BLK_CNT_EN           BIT1
+#define SDHCI_TRNS_ACMD12               BIT2
+#define SDHCI_TRNS_READ                 BIT4
+#define SDHCI_TRNS_MULTI                BIT5
+#define SDHCI_TRNS_RESP_INT             BIT8
+#define SDHCI_COMMAND                   0x0E
+#define SDHCI_CMD_RESP_MASK             0x03
+#define SDHCI_CMD_CRC                   0x08
+#define SDHCI_CMD_INDEX                 0x10
+#define SDHCI_CMD_DATA                  0x20
+#define SDHCI_CMD_ABORTCMD              0xC0
+#define SDHCI_CMD_RESP_NONE             0x00
+#define SDHCI_CMD_RESP_LONG             0x01
+#define SDHCI_CMD_RESP_SHORT            0x02
+#define SDHCI_CMD_RESP_SHORT_BUSY       0x03
+#define SDHCI_MAKE_CMD(c, f)            ((((c) & 0xff) << 8) | ((f) & 0xff))
+#define SDHCI_RESPONSE_01               0x10
+#define SDHCI_RESPONSE_23               0x14
+#define SDHCI_RESPONSE_45               0x18
+#define SDHCI_RESPONSE_67               0x1C
+#define SDHCI_PSTATE                    0x24
+#define SDHCI_CMD_INHIBIT               BIT0
+#define SDHCI_CMD_INHIBIT_DAT           BIT1
+#define SDHCI_BUF_WR_ENABLE             BIT10
+#define SDHCI_BUF_RD_ENABLE             BIT11
+#define SDHCI_CARD_INSERTED             BIT16
+#define SDHCI_HOST_CONTROL              0x28
+#define SDHCI_DAT_XFER_WIDTH            BIT1
+#define SDHCI_EXT_DAT_XFER              BIT5
+#define SDHCI_CTRL_DMA_MASK             0x18
+#define SDHCI_CTRL_SDMA                 0x00
+#define SDHCI_PWR_CONTROL               0x29
+#define SDHCI_BUS_VOL_VDD1_1_8V         0xC
+#define SDHCI_BUS_VOL_VDD1_3_0V         0xE
+#define SDHCI_BUF_DATA_R                0x20
+#define SDHCI_BLOCK_GAP_CONTROL         0x2A
+#define SDHCI_CLK_CTRL                  0x2C
+#define SDHCI_TOUT_CTRL                 0x2E
+#define SDHCI_SOFTWARE_RESET            0x2F
+#define SDHCI_RESET_CMD                 0x02
+#define SDHCI_RESET_DATA                0x04
+#define SDHCI_INT_STATUS                0x30
+#define SDHCI_ERR_INT_STATUS            0x32
+#define SDHCI_INT_CMD_COMPLETE          BIT0
+#define SDHCI_INT_XFER_COMPLETE         BIT1
+#define SDHCI_INT_DMA_END               BIT3
+#define SDHCI_INT_BUF_WR_READY          BIT4
+#define SDHCI_INT_BUF_RD_READY          BIT5
+#define SDHCI_INT_ERROR                 BIT15
+#define SDHCI_INT_STATUS_EN             0x34
+#define SDHCI_ERR_INT_STATUS_EN         0x36
+#define SDHCI_INT_CMD_COMPLETE_EN       BIT0
+#define SDHCI_INT_XFER_COMPLETE_EN      BIT1
+#define SDHCI_INT_DMA_END_EN            BIT3
+#define SDHCI_INT_CARD_INSERTION_EN     BIT6
+#define SDHCI_INT_ERROR_EN              BIT15
+#define SDHCI_SIGNAL_ENABLE             0x38
+#define SDHCI_HOST_CONTROL2             0x3E
+#define SDHCI_HOST_VER4_ENABLE          BIT12
+#define SDHCI_CAPABILITIES1             0x40
+#define SDHCI_CAPABILITIES2             0x44
+#define SDHCI_ADMA_SA_LOW               0x58
+#define SDHCI_ADMA_SA_HIGH              0x5C
+#define SDHCI_HOST_CNTRL_VERS           0xFE
+#define SDHCI_UHS_2_TIMER_CNTRL         0xC2
+
+#define P_VENDOR_SPECIFIC_AREA          0xE8
+#define P_VENDOR2_SPECIFIC_AREA         0xEA
+#define VENDOR_SD_CTRL                  0x2C
+
+#define SDHCI_PHY_R_OFFSET              0x300
+
+#define SDHCI_P_PHY_CNFG        (SDHCI_PHY_R_OFFSET + 0x00)
+#define SDHCI_P_CMDPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x04)
+#define SDHCI_P_DATPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x06)
+#define SDHCI_P_CLKPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x08)
+#define SDHCI_P_STBPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x0A)
+#define SDHCI_P_RSTNPAD_CNFG    (SDHCI_PHY_R_OFFSET + 0x0C)
+#define SDHCI_P_PADTEST_CNFG    (SDHCI_PHY_R_OFFSET + 0x0E)
+#define SDHCI_P_PADTEST_OUT     (SDHCI_PHY_R_OFFSET + 0x10)
+#define SDHCI_P_PADTEST_IN      (SDHCI_PHY_R_OFFSET + 0x12)
+#define SDHCI_P_COMMDL_CNFG     (SDHCI_PHY_R_OFFSET + 0x1C)
+#define SDHCI_P_SDCLKDL_CNFG    (SDHCI_PHY_R_OFFSET + 0x1D)
+#define SDHCI_P_SDCLKDL_DC      (SDHCI_PHY_R_OFFSET + 0x1E)
+#define SDHCI_P_SMPLDL_CNFG     (SDHCI_PHY_R_OFFSET + 0x20)
+#define SDHCI_P_ATDL_CNFG       (SDHCI_PHY_R_OFFSET + 0x21)
+#define SDHCI_P_DLL_CTRL        (SDHCI_PHY_R_OFFSET + 0x24)
+#define SDHCI_P_DLL_CNFG1       (SDHCI_PHY_R_OFFSET + 0x25)
+#define SDHCI_P_DLL_CNFG2       (SDHCI_PHY_R_OFFSET + 0x26)
+#define SDHCI_P_DLLDL_CNFG      (SDHCI_PHY_R_OFFSET + 0x28)
+#define SDHCI_P_DLL_OFFST       (SDHCI_PHY_R_OFFSET + 0x29)
+#define SDHCI_P_DLLMST_TSTDC    (SDHCI_PHY_R_OFFSET + 0x2A)
+#define SDHCI_P_DLLLBT_CNFG     (SDHCI_PHY_R_OFFSET + 0x2C)
+#define SDHCI_P_DLL_STATUS      (SDHCI_PHY_R_OFFSET + 0x2E)
+#define SDHCI_P_DLLDBG_MLKDC    (SDHCI_PHY_R_OFFSET + 0x30)
+#define SDHCI_P_DLLDBG_SLKDC    (SDHCI_PHY_R_OFFSET + 0x32)
+
+#define PHY_CNFG_PHY_RSTN       0
+#define PHY_CNFG_PHY_PWRGOOD    1
+#define PHY_CNFG_PAD_SP         16
+#define PHY_CNFG_PAD_SP_MSK     0xf
+#define PHY_CNFG_PAD_SN         20
+#define PHY_CNFG_PAD_SN_MSK     0xf
+
+#define PAD_CNFG_RXSEL                0
+#define PAD_CNFG_RXSEL_MSK            0x7
+#define PAD_CNFG_WEAKPULL_EN          3
+#define PAD_CNFG_WEAKPULL_EN_MSK      0x3
+#define PAD_CNFG_TXSLEW_CTRL_P        5
+#define PAD_CNFG_TXSLEW_CTRL_P_MSK    0xf
+#define PAD_CNFG_TXSLEW_CTRL_N        9
+#define PAD_CNFG_TXSLEW_CTRL_N_MSK    0xf
+
+#define COMMDL_CNFG_DLSTEP_SEL        0
+#define COMMDL_CNFG_DLOUT_EN          1
+
+#define SDCLKDL_CNFG_EXTDLY_EN        0
+#define SDCLKDL_CNFG_BYPASS_EN        1
+#define SDCLKDL_CNFG_INPSEL_CNFG      2
+#define SDCLKDL_CNFG_INPSEL_CNFG_MSK  0x3
+#define SDCLKDL_CNFG_UPDATE_DC        4
+
+#define SMPLDL_CNFG_EXTDLY_EN         0
+#define SMPLDL_CNFG_BYPASS_EN         1
+#define SMPLDL_CNFG_INPSEL_CNFG       2
+#define SMPLDL_CNFG_INPSEL_CNFG_MSK   0x3
+#define SMPLDL_CNFG_INPSEL_OVERRIDE   4
+
+#define ATDL_CNFG_EXTDLY_EN           0
+#define ATDL_CNFG_BYPASS_EN           1
+#define ATDL_CNFG_INPSEL_CNFG         2
+#define ATDL_CNFG_INPSEL_CNFG_MSK     0x3
+
+#define SD_USE_PIO                    0x1
+
+/**
+  card detect status
+  -1: haven't check the card detect register
+  0 : no card detected
+  1 : card detected
+**/
+#define SDCARD_STATUS_UNKNOWN       (-1)
+#define SDCARD_STATUS_INSERTED      (1)
+#define SDCARD_STATUS_NOT_INSERTED  (0)
+
+typedef struct {
+  UINT32  CmdIdx;
+  UINT32  CmdArg;
+  UINT32  ResponseType;
+  UINT32  Response[4];
+} MMC_CMD;
+
+typedef struct {
+  UINTN   RegBase;
+  UINTN   VendorBase;
+  UINTN   DescBase;
+  UINTN   DescSize;
+  INT32   ClkRate;
+  INT32   BusWidth;
+  UINT32  Flags;
+  INT32   CardIn;
+} BM_SD_PARAMS;
+
+extern BM_SD_PARAMS BmParams;
+
+/**
+  SD card sends command.
+
+  @param[in]  Idx       Command ID.
+  @param[in]  Arg       Command argument.
+  @param[in]  RespType  Type of response data.
+  @param[out] Response  Response data.
+
+  @retval  EFI_SUCCESS             The command was sent successfully.
+  @retval  EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
+  @retval  EFI_TIMEOUT             The command transmission or response handling timed out.
+
+**/
+EFI_STATUS
+EFIAPI
+BmSdSendCmd (
+  IN  UINT32 Idx,
+  IN  UINT32 Arg,
+  IN  UINT32 RespType,
+  OUT UINT32 *Response
+  );
+
+/**
+  Detect the status of the SD card.
+
+  @return The status of the SD card:
+          - SDCARD_STATUS_INSERTED:      The SD card is inserted.
+          - SDCARD_STATUS_NOT_INSERTED:  The SD card is not inserted.
+          - SDCARD_STATUS_UNKNOWN:       The status of the SD card is unknown.
+
+**/
+INT32
+BmSdCardDetect (
+  VOID
+  );
+
+/**
+  Set the input/output settings for the SD card.
+
+  @param[in] Clk     The clock frequency for the SD card.
+  @param[in] Width   The bus width for data transfer.
+
+  @retval EFI_SUCCESS             The input/output settings were set successfully.
+  @retval EFI_UNSUPPORTED         The specified bus width is not supported.
+
+**/
+EFI_STATUS
+BmSdSetIos (
+  IN UINT32 Clk,
+  IN UINT32 Width
+  );
+
+/**
+  Prepare the SD card for data transfer.
+  Set the number and size of data blocks before sending IO commands to the SD card.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval EFI_SUCCESS             The SD card was prepared successfully.
+  @retval Other                   An error occurred during the preparation of the SD card.
+
+**/
+EFI_STATUS
+BmSdPrepare (
+  IN INT32 Lba,
+  IN UINTN Buf,
+  IN UINTN Size
+  );
+
+/**
+  SD card sends command to read data blocks.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval  EFI_SUCCESS             The command to read data blocks was sent successfully.
+  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
+
+**/
+EFI_STATUS
+BmSdRead (
+  IN INT32   Lba,
+  IN UINT32* Buf,
+  IN UINTN   Size
+  );
+
+/**
+  SD card sends commands to write data blocks.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval  EFI_SUCCESS             The command to write data blocks was sent successfully.
+  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
+
+**/
+EFI_STATUS
+BmSdWrite (
+  IN INT32   Lba,
+  IN UINT32* Buf,
+  IN UINTN   Size
+  );
+
+/**
+  Initialize the SD card.
+
+  This function performs the initialization of the SD card hardware and settings.
+
+  @param[in] Flags     Initialization flags.
+
+  @retval EFI_SUCCESS  The SD card was initialized successfully.
+
+**/
+EFI_STATUS
+SdInit (
+  IN UINT32  flags
+  );
+
+#endif
diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
new file mode 100755
index 000000000000..efa9f6397a1e
--- /dev/null
+++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
@@ -0,0 +1,929 @@
+/** @file
+  The implementation for handling SD card operations using the SD Host Controller Interface (SDHCI).
+
+  Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-3-Clause
+
+**/
+
+#include <Uefi.h>
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Include/MmcHost.h>
+
+#include "SdHci.h"
+
+#define SDCARD_INIT_FREQ  (200 * 1000)
+#define SDCARD_TRAN_FREQ  (6 * 1000 * 1000)
+
+/**
+  Return the clock rate of SD card.
+
+  @retval the clock rate of SD card.
+
+**/
+INT32
+BmGetSdClk (
+  VOID
+  )
+{
+  return 100*1000*1000;
+}
+
+/**
+  SD card sends command with response block data.
+
+  @param    Cmd   Command sent by SD card.
+
+  @retval EFI_SUCCESS             The command with response block data was sent successfully.
+  @retval EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
+  @retval EFI_TIMEOUT             The command transmission or response handling timed out.
+
+**/
+STATIC
+EFI_STATUS
+SdSendCmdWithData (
+  IN OUT MMC_CMD *Cmd
+  )
+{
+  UINTN   Base;
+  UINT32  Mode;
+  UINT32  State;
+  UINT32  DmaAddr;
+  UINT32  Flags;
+  UINT32  Timeout;
+
+  Base  = BmParams.RegBase;
+  Mode  = 0;
+  Flags = 0;
+
+  // Make sure Cmd line is clear
+  while (1) {
+    if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT))
+    break;
+  }
+
+  switch (Cmd->CmdIdx) {
+    case MMC_CMD17:
+    case MMC_CMD18:
+    case MMC_ACMD51:
+      Mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI | SDHCI_TRNS_READ;
+      if (!(BmParams.Flags & SD_USE_PIO))
+        Mode |= SDHCI_TRNS_DMA;
+      break;
+    case MMC_CMD24:
+    case MMC_CMD25:
+      Mode = (SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI) & ~SDHCI_TRNS_READ;
+      if (!(BmParams.Flags & SD_USE_PIO))
+        Mode |= SDHCI_TRNS_DMA;
+      break;
+    default:
+      ASSERT(0);
+  }
+
+  MmioWrite16 (Base + SDHCI_TRANSFER_MODE, Mode);
+  MmioWrite32 (Base + SDHCI_ARGUMENT, Cmd->CmdArg);
+
+  // set Cmd Flags
+  if (Cmd->CmdIdx == MMC_CMD0)
+    Flags |= SDHCI_CMD_RESP_NONE;
+  else {
+    if (Cmd->ResponseType & MMC_RSP_136)
+      Flags |= SDHCI_CMD_RESP_LONG;
+    else
+      Flags |= SDHCI_CMD_RESP_SHORT;
+    if (Cmd->ResponseType & MMC_RSP_CRC)
+      Flags |= SDHCI_CMD_CRC;
+    if (Cmd->ResponseType & MMC_RSP_CMD_IDX)
+      Flags |= SDHCI_CMD_INDEX;
+  }
+
+  Flags |= SDHCI_CMD_DATA;
+
+  // issue the Cmd
+  MmioWrite16 (Base + SDHCI_COMMAND, SDHCI_MAKE_CMD(Cmd->CmdIdx, Flags));
+
+  // check Cmd complete if necessary
+  if ((MmioRead16 (Base + SDHCI_TRANSFER_MODE) & SDHCI_TRNS_RESP_INT) == 0) {
+    Timeout = 100000;
+    while (1) {
+      State = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if (State & SDHCI_INT_ERROR) {
+        DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
+                                MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
+        return EFI_DEVICE_ERROR;
+      }
+      if (State & SDHCI_INT_CMD_COMPLETE) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS, State | SDHCI_INT_CMD_COMPLETE);
+        break;
+      }
+
+      gBS->Stall (1);
+      if (!Timeout--) {
+        DEBUG ((DEBUG_ERROR, "%a: Timeout!\n", __func__));
+        return EFI_TIMEOUT;
+      }
+    }
+
+    // get Cmd respond
+    if (Flags != SDHCI_CMD_RESP_NONE)
+      Cmd->Response[0] = MmioRead32 (Base + SDHCI_RESPONSE_01);
+    if (Flags & SDHCI_CMD_RESP_LONG) {
+      Cmd->Response[1] = MmioRead32 (Base + SDHCI_RESPONSE_23);
+      Cmd->Response[2] = MmioRead32 (Base + SDHCI_RESPONSE_45);
+      Cmd->Response[3] = MmioRead32 (Base + SDHCI_RESPONSE_67);
+    }
+  }
+
+  // check dma/transfer complete
+  if (!(BmParams.Flags & SD_USE_PIO)) {
+    while (1) {
+      State = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if (State & SDHCI_INT_ERROR) {
+        DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
+                                MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
+        return EFI_DEVICE_ERROR;
+      }
+
+      if (State & SDHCI_INT_XFER_COMPLETE) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS, State);
+        break;
+      }
+
+      if (State & SDHCI_INT_DMA_END) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS, State);
+        if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & SDHCI_HOST_VER4_ENABLE) {
+          DmaAddr = MmioRead32 (Base + SDHCI_ADMA_SA_LOW);
+          MmioWrite32 (Base + SDHCI_ADMA_SA_LOW, DmaAddr);
+          MmioWrite32 (Base + SDHCI_ADMA_SA_HIGH, 0);
+        } else {
+          DmaAddr = MmioRead32 (Base + SDHCI_DMA_ADDRESS);
+          MmioWrite32 (Base + SDHCI_DMA_ADDRESS, DmaAddr);
+        }
+      }
+
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  SD card sends command without response block data.
+
+  @param    Cmd   Command sent by SD card.
+
+  @retval EFI_SUCCESS             The command without response block data was sent successfully.
+  @retval EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
+  @retval EFI_TIMEOUT             The command transmission or response handling timed out.
+
+**/
+STATIC
+EFI_STATUS
+SdSendCmdWithoutData (
+  IN OUT MMC_CMD *Cmd
+  )
+{
+  UINTN   Base;
+  UINT32  State;
+  UINT32  Flags;
+  UINT32  Timeout;
+
+  Base    = BmParams.RegBase;
+  Flags   = 0x0;
+  Timeout = 10000;
+
+  // make sure Cmd line is clear
+  while (1) {
+    if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT))
+      break;
+  }
+
+  // set Cmd Flags
+  if (Cmd->CmdIdx == MMC_CMD0)
+    Flags |= SDHCI_CMD_RESP_NONE;
+  else if (Cmd->CmdIdx == MMC_CMD1)
+    Flags |= SDHCI_CMD_RESP_SHORT;
+  else if (Cmd->CmdIdx == MMC_ACMD41)
+    Flags |= SDHCI_CMD_RESP_SHORT;
+  else {
+    if (Cmd->ResponseType & MMC_RSP_136)
+      Flags |= SDHCI_CMD_RESP_LONG;
+    else
+      Flags |= SDHCI_CMD_RESP_SHORT;
+    if (Cmd->ResponseType & MMC_RSP_CRC)
+      Flags |= SDHCI_CMD_CRC;
+    if (Cmd->ResponseType & MMC_RSP_CMD_IDX)
+      Flags |= SDHCI_CMD_INDEX;
+  }
+
+  // make sure dat line is clear if necessary
+  if (Flags != SDHCI_CMD_RESP_NONE) {
+    while (1) {
+      if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT_DAT))
+        break;
+    }
+  }
+
+  // issue the Cmd
+  MmioWrite32 (Base + SDHCI_ARGUMENT, Cmd->CmdArg);
+  MmioWrite16 (Base + SDHCI_COMMAND, SDHCI_MAKE_CMD(Cmd->CmdIdx, Flags));
+
+  // check Cmd complete
+  Timeout = 100000;
+  while (1) {
+    State = MmioRead16 (Base + SDHCI_INT_STATUS);
+    if (State & SDHCI_INT_ERROR) {
+      DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
+                              MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
+      return EFI_DEVICE_ERROR;
+    }
+    if (State & SDHCI_INT_CMD_COMPLETE) {
+      MmioWrite16 (Base + SDHCI_INT_STATUS, State | SDHCI_INT_CMD_COMPLETE);
+      break;
+    }
+
+    gBS->Stall (1);
+    if (!Timeout--) {
+      DEBUG ((DEBUG_ERROR, "%a: Timeout!\n", __func__));
+      return EFI_TIMEOUT;
+    }
+  }
+
+  // get Cmd respond
+  if (!(Flags & SDHCI_CMD_RESP_NONE))
+    Cmd->Response[0] = MmioRead32 (Base + SDHCI_RESPONSE_01);
+  if (Flags & SDHCI_CMD_RESP_LONG) {
+    Cmd->Response[1] = MmioRead32 (Base + SDHCI_RESPONSE_23);
+    Cmd->Response[2] = MmioRead32 (Base + SDHCI_RESPONSE_45);
+    Cmd->Response[3] = MmioRead32 (Base + SDHCI_RESPONSE_67);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  SD card sends command.
+
+  @param[in]  Idx       Command ID.
+  @param[in]  Arg       Command argument.
+  @param[in]  RespType  Type of response data.
+  @param[out] Response  Response data.
+
+  @retval  EFI_SUCCESS             The command was sent successfully.
+  @retval  EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
+  @retval  EFI_TIMEOUT             The command transmission or response handling timed out.
+
+**/
+EFI_STATUS
+EFIAPI
+BmSdSendCmd (
+  IN  UINT32 Idx,
+  IN  UINT32 Arg,
+  IN  UINT32 RespType,
+  OUT UINT32 *Response
+  )
+{
+  EFI_STATUS  Status;
+  MMC_CMD     Cmd;
+
+  // DEBUG ((DEBUG_INFO, "%a: SDHCI Cmd, Idx=%d, Arg=0x%x, ResponseType=0x%x\n", __func__, Idx, Arg, RespType));
+
+  ZeroMem(&Cmd,sizeof(MMC_CMD));
+
+  Cmd.CmdIdx       = Idx;
+  Cmd.CmdArg       = Arg;
+  Cmd.ResponseType = RespType;
+
+  switch (Cmd.CmdIdx) {
+    case MMC_CMD17:
+    case MMC_CMD18:
+    case MMC_CMD24:
+    case MMC_CMD25:
+    case MMC_ACMD51:
+      Status = SdSendCmdWithData(&Cmd);
+      break;
+    default:
+      Status = SdSendCmdWithoutData(&Cmd);
+  }
+
+  if ((Status == EFI_SUCCESS) && (Response != NULL)) {
+    for (INT32 I = 0; I < 4; I++) {
+      *Response = Cmd.Response[I];
+      Response++;
+    }
+  }
+  return Status;
+}
+
+/**
+  Set clock frequency of SD card.
+
+  @param[in] Clk       The clock frequency of SD card.
+
+**/
+VOID
+SdSetClk (
+  IN INT32 Clk
+  )
+{
+  INT32  I;
+  INT32  Div;
+  UINTN  Base;
+
+  ASSERT (Clk > 0);
+
+  if (BmParams.ClkRate <= Clk) {
+    Div = 0;
+  } else {
+    for (Div = 0x1; Div < 0xFF; Div++) {
+      if (BmParams.ClkRate / (2 * Div) <= Clk)
+        break;
+    }
+  }
+  ASSERT (Div <= 0xFF);
+
+  Base = BmParams.RegBase;
+  if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & (1 << 15)) {
+    //verbose("Use SDCLK Preset Value\n");
+  } else {
+    //verbose("Set SDCLK by driver. Div=0x%x(%d)\n", Div, Div);
+    MmioWrite16 (Base + SDHCI_CLK_CTRL,
+            MmioRead16 (Base + SDHCI_CLK_CTRL) & ~0x9); // disable INTERNAL_CLK_EN and PLL_ENABLE
+    MmioWrite16 (Base + SDHCI_CLK_CTRL,
+            (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0xDF) | Div << 8); // set Clk Div
+    MmioWrite16 (Base + SDHCI_CLK_CTRL,
+            MmioRead16 (Base + SDHCI_CLK_CTRL) | 0x1); // set INTERNAL_CLK_EN
+
+    for (I = 0; I <= 150000; I += 100) {
+      if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
+        break;
+      gBS->Stall (100);
+    }
+
+    if (I > 150000) {
+      DEBUG ((DEBUG_ERROR, "%a: SD INTERNAL_CLK_EN setting FAILED!\n", __func__));
+      ASSERT(0);
+    }
+
+    MmioWrite16 (Base + SDHCI_CLK_CTRL, MmioRead16 (Base + SDHCI_CLK_CTRL) | 0x8); // set PLL_ENABLE
+
+    for (I = 0; I <= 150000; I += 100) {
+      if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
+        return;
+      gBS->Stall (100);
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: SD PLL setting FAILED!\n", __func__));
+}
+
+/**
+  Change clock frequency of SD card.
+
+  @param[in] Clk       The clock frequency of SD card.
+
+**/
+VOID
+SdChangeClk (
+  IN INT32 Clk
+  )
+{
+  INT32  I;
+  INT32  Div;
+  UINTN  Base;
+
+  ASSERT (Clk > 0);
+
+  if (BmParams.ClkRate <= Clk) {
+    Div = 0;
+  } else {
+    for (Div = 0x1; Div < 0xFF; Div++) {
+      if (BmParams.ClkRate / (2 * Div) <= Clk)
+        break;
+    }
+  }
+  ASSERT (Div <= 0xFF);
+
+  Base = BmParams.RegBase;
+
+  MmioWrite16 (Base + SDHCI_CLK_CTRL,
+          MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 2)); // stop SD clock
+
+  MmioWrite16 (Base + SDHCI_CLK_CTRL,
+          MmioRead16 (Base + SDHCI_CLK_CTRL) & ~0x8); // disable  PLL_ENABLE
+
+  if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & (1 << 15)) {
+    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+            MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
+  } else {
+    MmioWrite16 (Base + SDHCI_CLK_CTRL,
+            (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0xDF) | Div << 8); // set Clk Div
+    MmioWrite16 (Base + SDHCI_CLK_CTRL,
+            MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 5)); // CLK_GEN_SELECT
+  }
+
+  MmioWrite16 (Base + SDHCI_CLK_CTRL,
+          MmioRead16 (Base + SDHCI_CLK_CTRL) | 0xc); // enable  PLL_ENABLE
+
+  for (I = 0; I <= 150000; I += 100) {
+    if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
+      return;
+    gBS->Stall (100);
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: SD PLL setting FAILED!\n", __func__));
+}
+
+/**
+  Detect the status of the SD card.
+
+  @return The status of the SD card:
+          - SDCARD_STATUS_INSERTED:      The SD card is inserted.
+          - SDCARD_STATUS_NOT_INSERTED:  The SD card is not inserted.
+          - SDCARD_STATUS_UNKNOWN:       The status of the SD card is unknown.
+
+**/
+INT32
+BmSdCardDetect (
+  VOID
+  )
+{
+  UINTN  Base;
+  UINTN  Reg;
+
+  Base = BmParams.RegBase;
+
+  if (BmParams.CardIn != SDCARD_STATUS_UNKNOWN)
+    return BmParams.CardIn;
+
+  MmioWrite16 (Base + SDHCI_INT_STATUS_EN,
+          MmioRead16 (Base + SDHCI_INT_STATUS_EN) | SDHCI_INT_CARD_INSERTION_EN);
+
+  Reg = MmioRead32 (Base + SDHCI_PSTATE);
+
+  if (Reg & SDHCI_CARD_INSERTED)
+    BmParams.CardIn = SDCARD_STATUS_INSERTED;
+  else
+    BmParams.CardIn = SDCARD_STATUS_NOT_INSERTED;
+
+  return BmParams.CardIn;
+}
+
+/**
+  SD card hardware initialization.
+
+**/
+STATIC
+VOID
+SdHwInit (
+  VOID
+  )
+{
+  UINTN  Base;
+
+  Base                = BmParams.RegBase;
+  BmParams.VendorBase = Base + (MmioRead16 (Base + P_VENDOR_SPECIFIC_AREA) & ((1 << 12) - 1));
+
+  // deasset reset of phy
+  MmioWrite32 (Base + SDHCI_P_PHY_CNFG, MmioRead32 (Base + SDHCI_P_PHY_CNFG) | (1 << PHY_CNFG_PHY_RSTN));
+
+  // reset data & Cmd
+  MmioWrite8 (Base + SDHCI_SOFTWARE_RESET, 0x6);
+
+  // init common parameters
+  MmioWrite8 (Base + SDHCI_PWR_CONTROL, (0x7 << 1));
+  MmioWrite8 (Base + SDHCI_TOUT_CTRL, 0xe);  // for TMCLK 50Khz
+  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+          MmioRead16 (Base + SDHCI_HOST_CONTROL2) | 1 << 11);  // set cmd23 support
+  MmioWrite16 (Base + SDHCI_CLK_CTRL, MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 5));  // divided clock Mode
+
+  // set host version 4 parameters
+  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+          MmioRead16 (Base + SDHCI_HOST_CONTROL2) | (1 << 12)); // set HOST_VER4_ENABLE
+  if (MmioRead32 (Base + SDHCI_CAPABILITIES1) & (0x1 << 27)) {
+    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+            MmioRead16 (Base + SDHCI_HOST_CONTROL2) | 0x1 << 13); // set 64bit addressing
+  }
+
+  // if support asynchronous int
+  if (MmioRead32 (Base + SDHCI_CAPABILITIES1) & (0x1 << 29))
+    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+            MmioRead16 (Base + SDHCI_HOST_CONTROL2) | (0x1 << 14)); // enable async int
+  // give some time to power down card
+  gBS->Stall (20000);
+
+  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+          MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~(0x1 << 8)); // clr UHS2_IF_ENABLE
+  MmioWrite8 (Base + SDHCI_PWR_CONTROL,
+          MmioRead8 (Base + SDHCI_PWR_CONTROL) | 0x1); // set SD_BUS_PWR_VDD1
+  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
+          MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
+  SdSetClk (SDCARD_INIT_FREQ);
+  gBS->Stall (50000);
+
+  MmioWrite16 (Base + SDHCI_CLK_CTRL,
+          MmioRead16 (Base + SDHCI_CLK_CTRL) | (0x1 << 2)); // supply SD clock
+  gBS->Stall (400); // wait for voltage ramp up time at least 74 cycle, 400us is 80 cycles for 200Khz
+
+  MmioWrite16 (Base + SDHCI_INT_STATUS, MmioRead16 (Base + SDHCI_INT_STATUS) | (0x1 << 6));
+
+  // we enable all interrupt Status here for testing
+  MmioWrite16 (Base + SDHCI_INT_STATUS_EN, MmioRead16 (Base + SDHCI_INT_STATUS_EN) | 0xFFFF);
+  MmioWrite16 (Base + SDHCI_ERR_INT_STATUS_EN, MmioRead16 (Base + SDHCI_ERR_INT_STATUS_EN) | 0xFFFF);
+
+  //verbose("SD init done\n");
+}
+
+/**
+  Set the input/output settings for the SD card.
+
+  @param[in] Clk     The clock frequency for the SD card.
+  @param[in] Width   The bus width for data transfer.
+
+  @retval EFI_SUCCESS             The input/output settings were set successfully.
+  @retval EFI_UNSUPPORTED         The specified bus width is not supported.
+
+**/
+EFI_STATUS
+BmSdSetIos (
+  IN UINT32 Clk,
+  IN UINT32 Width
+  )
+{
+  switch (Width) {
+    case MMC_BUS_WIDTH_1:
+      MmioWrite8 (BmParams.RegBase + SDHCI_HOST_CONTROL,
+              MmioRead8 (BmParams.RegBase + SDHCI_HOST_CONTROL) &
+              ~SDHCI_DAT_XFER_WIDTH);
+      break;
+    case MMC_BUS_WIDTH_4:
+      MmioWrite8 (BmParams.RegBase + SDHCI_HOST_CONTROL,
+              MmioRead8 (BmParams.RegBase + SDHCI_HOST_CONTROL) |
+              SDHCI_DAT_XFER_WIDTH);
+      break;
+    default:
+      ASSERT (0);
+  }
+
+  SdChangeClk (Clk);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Prepare the SD card for data transfer.
+  Set the number and size of data blocks before sending IO commands to the SD card.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval EFI_SUCCESS             The SD card was prepared successfully.
+  @retval Other                   An error occurred during the preparation of the SD card.
+
+**/
+EFI_STATUS
+BmSdPrepare (
+  IN INT32 Lba,
+  IN UINTN Buf,
+  IN UINTN Size
+  )
+{
+  UINTN   LoadAddr;
+  UINTN   Base;
+  UINT32  BlockCnt;
+  UINT32  BlockSize;
+  UINT8   Tmp;
+
+  LoadAddr = Buf;
+
+  if (Size >= MMC_BLOCK_SIZE) {
+    // CMD17, 18, 24, 25
+    // ASSERT (((LoadAddr & MMC_BLOCK_MASK) == 0) && ((Size % MMC_BLOCK_SIZE) == 0));
+    BlockSize = MMC_BLOCK_SIZE;
+    BlockCnt  = Size / MMC_BLOCK_SIZE;
+  } else {
+    // ACMD51
+    ASSERT (((LoadAddr & 8) == 0) && ((Size % 8) == 0));
+    BlockSize = 8;
+    BlockCnt  = Size / 8;
+  }
+
+  Base = BmParams.RegBase;
+
+  if (!(BmParams.Flags & SD_USE_PIO)) {
+    if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & SDHCI_HOST_VER4_ENABLE) {
+      MmioWrite32 (Base + SDHCI_ADMA_SA_LOW, LoadAddr);
+      MmioWrite32 (Base + SDHCI_ADMA_SA_HIGH, (LoadAddr >> 32));
+      MmioWrite32 (Base + SDHCI_DMA_ADDRESS, BlockCnt);
+      MmioWrite16 (Base + SDHCI_BLOCK_COUNT, 0);
+    } else {
+      ASSERT((LoadAddr >> 32) == 0);
+      MmioWrite32 (Base + SDHCI_DMA_ADDRESS, LoadAddr);
+      MmioWrite16 (Base + SDHCI_BLOCK_COUNT, BlockCnt);
+    }
+
+    // 512K bytes SDMA buffer boundary
+    MmioWrite16 (Base + SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, BlockSize));
+
+    // select SDMA
+    Tmp = MmioRead8 (Base + SDHCI_HOST_CONTROL);
+    Tmp &= ~SDHCI_CTRL_DMA_MASK;
+    Tmp |= SDHCI_CTRL_SDMA;
+    MmioWrite8 (Base + SDHCI_HOST_CONTROL, Tmp);
+  } else {
+    MmioWrite16 (Base + SDHCI_BLOCK_SIZE, BlockSize);
+    MmioWrite16 (Base + SDHCI_BLOCK_COUNT, BlockCnt);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  SD card sends command to read data blocks.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval  EFI_SUCCESS             The command to read data blocks was sent successfully.
+  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
+
+**/
+EFI_STATUS
+BmSdRead (
+  IN INT32   Lba,
+  IN UINT32* Buf,
+  IN UINTN   Size
+  )
+{
+  UINT32  Timeout;
+  UINTN   Base;
+  UINT32  *Data;
+  UINT32  BlockSize;
+  UINT32  BlockCnt;
+  UINT32  Status;
+
+  Timeout   = 0;
+  Base      = BmParams.RegBase;
+  Data      = Buf;
+  BlockSize = 0;
+  BlockCnt  = 0;
+  Status    = 0;
+
+  if (BmParams.Flags & SD_USE_PIO) {
+    BlockSize = MmioRead16 (Base + SDHCI_BLOCK_SIZE);
+    BlockCnt  = Size / BlockSize;
+    BlockSize /= 4;
+
+    for (INT32 I = 0; I < BlockCnt; ) {
+      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if ((Status & SDHCI_INT_BUF_RD_READY) &&
+          (MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_BUF_RD_ENABLE)) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS, SDHCI_INT_BUF_RD_READY);
+        for (INT32 j = 0; j < BlockSize; j++) {
+          *(Data++) = MmioRead32 (Base + SDHCI_BUF_DATA_R);
+        }
+
+        Timeout = 0;
+        I++;
+      } else {
+        gBS->Stall (1);
+        Timeout++;
+      }
+
+      if (Timeout >= 10000) {
+        DEBUG ((DEBUG_INFO, "%a: sdhci read data Timeout\n", __func__));
+        goto Timeout;
+      }
+    }
+
+    Timeout = 0;
+    while (1) {
+      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if (Status & SDHCI_INT_XFER_COMPLETE) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS,
+                Status | SDHCI_INT_XFER_COMPLETE);
+
+        return EFI_SUCCESS;
+      } else {
+        gBS->Stall (1);
+        Timeout++;
+      }
+
+      if (Timeout >= 10000) {
+        DEBUG ((DEBUG_INFO, "%a:wait xfer complete Timeout\n", __func__));
+        goto Timeout;
+      }
+    }
+  } else {
+    return EFI_SUCCESS;
+  }
+
+Timeout:
+  return EFI_TIMEOUT;
+
+}
+
+/**
+  SD card sends commands to write data blocks.
+
+  @param[in]  Lba       Logical Block Address.
+  @param[in]  Buf       Buffer Address.
+  @param[in]  Size      Size of Data Blocks.
+
+  @retval  EFI_SUCCESS             The command to write data blocks was sent successfully.
+  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
+
+**/
+EFI_STATUS
+BmSdWrite (
+  IN INT32   Lba,
+  IN UINT32* Buf,
+  IN UINTN   Size
+  )
+{
+  UINT32  Timeout;
+  UINTN   Base;
+  UINT32  *Data;
+  UINT32  BlockSize;
+  UINT32  BlockCnt;
+  UINT32  Status;
+
+  Timeout   = 0;
+  Base      = BmParams.RegBase;
+  Data      = Buf;
+  BlockSize = 0;
+  BlockCnt  = 0;
+  Status    = 0;
+
+  if (BmParams.Flags & SD_USE_PIO) {
+    BlockSize = MmioRead16 (Base + SDHCI_BLOCK_SIZE);
+    BlockCnt = Size / BlockSize;
+    BlockSize /= 4;
+
+    for (INT32 j = 0; j < BlockSize; j++) {
+      MmioWrite32 (Base + SDHCI_BUF_DATA_R, *(Data++));
+    }
+
+    for (INT32 I = 0; I < BlockCnt-1; ) {
+      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if ((Status & SDHCI_INT_BUF_WR_READY) &&
+          (MmioRead32 (Base + SDHCI_PSTATE) &
+          SDHCI_BUF_WR_ENABLE)) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS, SDHCI_INT_BUF_WR_READY);
+        for (INT32 j = 0; j < BlockSize; j++) {
+          MmioWrite32 (Base + SDHCI_BUF_DATA_R, *(Data++));
+        }
+
+        Timeout = 0;
+        I++;
+      } else {
+        gBS->Stall (1);
+        Timeout++;
+      }
+
+      if (Timeout >= 10000000) {
+        DEBUG ((DEBUG_INFO, "%a:sdhci write data Timeout\n", __func__));
+        goto Timeout;
+      }
+    }
+
+    Timeout = 0;
+    while (1) {
+      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
+      if (Status & SDHCI_INT_XFER_COMPLETE) {
+        MmioWrite16 (Base + SDHCI_INT_STATUS,
+                Status | SDHCI_INT_XFER_COMPLETE);
+
+        return EFI_SUCCESS;
+      } else {
+        gBS->Stall (1);
+        Timeout++;
+      }
+
+      if (Timeout >= 10000) {
+        DEBUG ((DEBUG_INFO, "%a:wait xfer complete Timeout\n", __func__));
+        goto Timeout;
+      }
+    }
+  } else
+    return EFI_SUCCESS;
+
+Timeout:
+  return EFI_TIMEOUT;
+}
+
+/**
+  Initialize the SD PHY.
+
+  This function performs the initialization of the SD PHY hardware.
+
+**/
+VOID
+SdPhyInit (
+  VOID
+  )
+{
+  UINTN Base;
+  INT32 RetryCount;
+
+  Base       = BmParams.RegBase;
+  RetryCount = 100;
+
+  // reset hardware
+  MmioWrite8 (Base + SDHCI_SOFTWARE_RESET, 0x7);
+  while (MmioRead8 (Base + SDHCI_SOFTWARE_RESET)) {
+    if (RetryCount-- > 0)
+      gBS->Stall (10000);
+    else
+      break;
+  }
+
+  // Wait for the PHY power on ready
+  RetryCount = 100;
+  while (!(MmioRead32 (Base + SDHCI_P_PHY_CNFG) & (1 << PHY_CNFG_PHY_PWRGOOD))) {
+    if (RetryCount-- > 0)
+      gBS->Stall (10000);
+    else
+      break;
+  }
+
+  // Asset reset of phy
+  MmioAnd32 (Base + SDHCI_P_PHY_CNFG, ~(1 << PHY_CNFG_PHY_RSTN));
+
+  // Set PAD_SN PAD_SP
+  MmioWrite32 (Base + SDHCI_P_PHY_CNFG,
+          (1 << PHY_CNFG_PHY_PWRGOOD) | (0x9 << PHY_CNFG_PAD_SP) | (0x8 << PHY_CNFG_PAD_SN));
+
+  // Set CMDPAD
+  MmioWrite16 (Base + SDHCI_P_CMDPAD_CNFG,
+          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
+          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
+
+  // Set DATAPAD
+  MmioWrite16 (Base + SDHCI_P_DATPAD_CNFG,
+          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
+          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
+
+  // Set CLKPAD
+  MmioWrite16 (Base + SDHCI_P_CLKPAD_CNFG,
+          (0x2 << PAD_CNFG_RXSEL) | (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
+
+  // Set STB_PAD
+  MmioWrite16 (Base + SDHCI_P_STBPAD_CNFG,
+          (0x2 << PAD_CNFG_RXSEL) | (0x2 << PAD_CNFG_WEAKPULL_EN) |
+          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
+
+  // Set RSTPAD
+  MmioWrite16 (Base + SDHCI_P_RSTNPAD_CNFG,
+          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
+          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
+
+  // Set SDCLKDL_CNFG, EXTDLY_EN = 1, fix delay
+  MmioWrite8 (Base + SDHCI_P_SDCLKDL_CNFG, (1 << SDCLKDL_CNFG_EXTDLY_EN));
+
+  // Set SMPLDL_CNFG, Bypass
+  MmioWrite8 (Base + SDHCI_P_SMPLDL_CNFG, (1 << SMPLDL_CNFG_BYPASS_EN));
+
+  // Set ATDL_CNFG, tuning Clk not use for init
+  MmioWrite8 (Base + SDHCI_P_ATDL_CNFG, (2 << ATDL_CNFG_INPSEL_CNFG));
+
+  return;
+}
+
+/**
+  Initialize the SD card.
+
+  This function performs the initialization of the SD card hardware and settings.
+
+  @param[in] Flags     Initialization flags.
+
+  @retval EFI_SUCCESS  The SD card was initialized successfully.
+
+**/
+EFI_STATUS
+SdInit (
+  IN UINT32 Flags
+)
+{
+  BmParams.ClkRate = BmGetSdClk ();
+
+  DEBUG ((DEBUG_INFO, "SD initializing %dHz\n", BmParams.ClkRate));
+
+  BmParams.Flags = Flags;
+
+  SdPhyInit ();
+
+  SdHwInit ();
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
new file mode 100644
index 000000000000..3bb04344320a
--- /dev/null
+++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
@@ -0,0 +1,450 @@
+/** @file
+  This file implements the SD host controller driver for UEFI systems.
+  The file contains the implementation of the EFI_MMC_HOST_PROTOCOL, which provides
+  the necessary interfaces for handling communication and data transfer with SD cards.
+
+  Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+  Copyright (c) Microsoft Corporation. All rights reserved.
+  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DmaLib.h>
+#include <Library/TimerLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Include/MmcHost.h>
+
+#include "SdHci.h"
+
+#define SDHOST_BLOCK_BYTE_LENGTH  512
+
+#define DEBUG_MMCHOST_SD          DEBUG_VERBOSE
+#define DEBUG_MMCHOST_SD_INFO     DEBUG_INFO
+#define DEBUG_MMCHOST_SD_ERROR    DEBUG_ERROR
+
+STATIC BOOLEAN            mCardIsPresent   = FALSE;
+STATIC CARD_DETECT_STATE  mCardDetectState = CardDetectRequired;
+BM_SD_PARAMS              BmParams;
+
+/**
+  Check if the SD card is read-only.
+
+  @param[in] This      Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+
+  @retval FALSE        The SD card is not read-only.
+
+**/
+STATIC
+BOOLEAN
+SdIsReadOnly (
+  IN EFI_MMC_HOST_PROTOCOL *This
+  )
+{
+  return FALSE;
+}
+
+/**
+  Build the device path for the SD card.
+
+  @param[in]  This           Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[out] DevicePath     Pointer to the location to store the newly created device path.
+
+  @retval EFI_SUCCESS        The device path is built successfully.
+
+**/
+STATIC
+EFI_STATUS
+SdBuildDevicePath (
+  IN  EFI_MMC_HOST_PROTOCOL       *This,
+  OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+  EFI_GUID DevicePathGuid = EFI_CALLER_ID_GUID;
+
+  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: SdBuildDevicePath ()\n"));
+
+  NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
+  CopyGuid (&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &DevicePathGuid);
+  *DevicePath = NewDevicePathNode;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Send a command to the SD card.
+
+  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in] MmcCmd     The MMC command to send.
+  @param[in] Argument   The argument for the command.
+  @param[in] Type       The type of response expected.
+  @param[in] Buffer     Pointer to the buffer to store the response.
+
+  @retval EFI_SUCCESS   The command was sent successfully and the response was retrieved.
+  @retval Other         An error occurred while sending a command.
+**/
+STATIC
+EFI_STATUS
+SdSendCommand (
+  IN EFI_MMC_HOST_PROTOCOL    *This,
+  IN MMC_IDX                  MmcCmd,
+  IN UINT32                   Argument,
+  IN MMC_RESPONSE_TYPE        Type,
+  IN UINT32*                  Buffer
+  )
+{
+  EFI_STATUS Status;
+
+  Status = BmSdSendCmd (MmcCmd, Argument, Type, Buffer);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdSendCommand Error, Status=%r.\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read block data from an SD card.
+
+  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in] Lba        Logical Block Address of the starting block to read.
+  @param[in] Length     Number of blocks to read.
+  @param[in] Buffer     Pointer to the buffer to store the read data.
+
+  @retval EFI_SUCCESS   The operation completed successfully.
+  @retval Other         The operation failed.
+
+**/
+STATIC
+EFI_STATUS
+SdReadBlockData (
+  IN  EFI_MMC_HOST_PROTOCOL    *This,
+  IN  EFI_LBA                  Lba,
+  IN  UINTN                    Length,
+  OUT UINT32*                  Buffer
+  )
+{
+  EFI_STATUS Status;
+
+  ASSERT (Buffer != NULL);
+  ASSERT (Length % 4 == 0);
+
+  Status = BmSdRead (Lba, Buffer, Length);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdReadBlockData Error, Status=%r.\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write block data to an SD card.
+
+  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in] Lba        Logical Block Address of the starting block to write.
+  @param[in] Length     Number of blocks to write.
+  @param[in] Buffer     Pointer to the buffer containing the data to be written.
+
+  @retval EFI_SUCCESS   The operation completed successfully.
+  @retval Other         The operation failed.
+
+**/
+STATIC
+EFI_STATUS
+SdWriteBlockData (
+  IN EFI_MMC_HOST_PROTOCOL    *This,
+  IN EFI_LBA                  Lba,
+  IN UINTN                    Length,
+  IN UINT32*                  Buffer
+  )
+{
+  EFI_STATUS Status;
+
+  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: SdWriteBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n",(UINT32)Lba, Length, Buffer));
+
+  ASSERT (Buffer != NULL);
+  ASSERT (Length % SDHOST_BLOCK_BYTE_LENGTH == 0);
+
+  Status = BmSdWrite (Lba, Buffer, Length);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdWriteBlockData Error, Status=%r.\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the I/O settings for an SD card.
+
+  @param[in]  This           Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in]  BusClockFreq   Bus clock frequency in Hz.
+  @param[in]  BusWidth       Bus width setting.
+
+  @retval EFI_SUCCESS        The operation completed successfully.
+  @retval Other              The operation failed.
+
+**/
+STATIC
+EFI_STATUS
+SdSetIos (
+  IN EFI_MMC_HOST_PROTOCOL      *This,
+  IN  UINT32                    BusClockFreq,
+  IN  UINT32                    BusWidth
+  )
+{
+  EFI_STATUS Status;
+
+  DEBUG ((DEBUG_MMCHOST_SD_INFO, "%a: Setting Freq %u Hz\n", __func__, BusClockFreq));
+  DEBUG ((DEBUG_MMCHOST_SD_INFO, "%a: Setting BusWidth %u\n", __func__, BusWidth));
+
+  Status = BmSdSetIos (BusClockFreq,BusWidth);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdSetIos Error, Status=%r.\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Prepare the SD card for data transfer.
+
+  @param[in]  This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in]  Lba        Logical Block Address of the starting block to prepare.
+  @param[in]  Length     Number of blocks to prepare.
+  @param[in]  Buffer     Buffer containing the data to be prepared.
+
+  @retval EFI_SUCCESS    The operation completed successfully.
+  @retval Other          The operation failed.
+
+**/
+STATIC
+EFI_STATUS
+SdPrepare (
+  IN EFI_MMC_HOST_PROTOCOL    *This,
+  IN EFI_LBA                  Lba,
+  IN UINTN                    Length,
+  IN UINTN                    Buffer
+  )
+{
+  EFI_STATUS Status;
+
+  Status = BmSdPrepare (Lba, Buffer, Length);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdPrepare Error, Status=%r.\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notify the state of the SD card.
+
+  @param[in]  This    Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+  @param[in]  State   State of the SD card.
+
+  @retval EFI_SUCCESS       The operation completed successfully.
+  @retval EFI_NOT_READY     The card detection has not completed yet.
+  @retval Other             The operation failed.
+
+**/
+STATIC
+EFI_STATUS
+SdNotifyState (
+  IN EFI_MMC_HOST_PROTOCOL    *This,
+  IN MMC_STATE                State
+  )
+{
+  // Stall all operations except init until card detection has occurred.
+  if (State != MmcHwInitializationState && mCardDetectState != CardDetectCompleted) {
+    return EFI_NOT_READY;
+  }
+
+  switch (State) {
+    case MmcHwInitializationState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcHwInitializationState\n", State));
+
+      EFI_STATUS Status = SdInit (SD_USE_PIO);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_MMCHOST_SD_ERROR,"SdHost: SdNotifyState(): Fail to initialize!\n"));
+        return Status;
+      }
+      break;
+    case MmcIdleState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcIdleState\n", State));
+      break;
+    case MmcReadyState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcReadyState\n", State));
+      break;
+    case MmcIdentificationState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcIdentificationState\n", State));
+      break;
+    case MmcStandByState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcStandByState\n", State));
+      break;
+    case MmcTransferState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcTransferState\n", State));
+      break;
+    case MmcSendingDataState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcSendingDataState\n", State));
+      break;
+    case MmcReceiveDataState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcReceiveDataState\n", State));
+      break;
+    case MmcProgrammingState:
+      DEBUG ((DEBUG_MMCHOST_SD, "MmcProgrammingState\n", State));
+      break;
+    case MmcDisconnectState:
+    case MmcInvalidState:
+    default:
+      DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdHost: SdNotifyState(): Invalid State: %d\n", State));
+      ASSERT (0);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check if an SD card is present.
+
+  @param[in]  This    Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+
+  @retval TRUE        An SD card is present.
+  @retval FALSE       No SD card is present.
+
+**/
+STATIC
+BOOLEAN
+SdIsCardPresent (
+  IN EFI_MMC_HOST_PROTOCOL *This
+  )
+{
+  //
+  // If we are already in progress (we may get concurrent calls)
+  // or completed the detection, just return the current value.
+  //
+  if (mCardDetectState != CardDetectRequired) {
+    return mCardIsPresent;
+  }
+
+  mCardDetectState = CardDetectInProgress;
+  mCardIsPresent = FALSE;
+
+  if (BmSdCardDetect () == 1) {
+    mCardIsPresent = TRUE;
+    goto out;
+  }
+  else {
+    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdIsCardPresent: Error SdCardDetect.\n"));
+    mCardDetectState = CardDetectRequired;
+    return FALSE;
+  }
+
+  DEBUG ((DEBUG_MMCHOST_SD_INFO, "SdIsCardPresent: Not detected.\n"));
+
+out:
+  mCardDetectState = CardDetectCompleted;
+  return mCardIsPresent;
+}
+
+/**
+  Check if the SD card supports multi-block transfers.
+
+  @param[in]  This     Pointer to the EFI_MMC_HOST_PROTOCOL instance.
+
+  @retval TRUE         The SD card supports multi-block transfers.
+
+**/
+BOOLEAN
+SdIsMultiBlock (
+  IN EFI_MMC_HOST_PROTOCOL *This
+  )
+{
+  return TRUE;
+}
+
+EFI_MMC_HOST_PROTOCOL gMmcHost = {
+  MMC_HOST_PROTOCOL_REVISION,
+  SdIsCardPresent,
+  SdIsReadOnly,
+  SdBuildDevicePath,
+  SdNotifyState,
+  SdSendCommand,
+  SdReadBlockData,
+  SdWriteBlockData,
+  SdSetIos,
+  SdPrepare,
+  SdIsMultiBlock
+};
+
+/**
+  Initialize the SD host.
+
+  @param[in]  ImageHandle    The image handle.
+  @param[in]  SystemTable    The system table.
+
+  @retval EFI_SUCCESS        The operation completed successfully.
+  @retval Other              The operation failed.
+**/
+EFI_STATUS
+SdHostInitialize (
+  IN EFI_HANDLE          ImageHandle,
+  IN EFI_SYSTEM_TABLE    *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+  UINTN       Base;
+
+  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: Initialize\n"));
+
+  Handle            = NULL;
+  Base              = SDIO_BASE;
+
+  if(!PcdGetBool (PcdForceNoMMU)){
+    for (INT32 I = 39; I < 64; I++) {
+      if (Base & (1ULL << 38)) {
+        Base |= (1ULL << I);
+      } else {
+        Base &= ~(1ULL << I);
+      }
+    }
+  }
+
+  BmParams.RegBase  = Base;
+  BmParams.ClkRate  = 50 * 1000 * 1000;
+  BmParams.BusWidth = MMC_BUS_WIDTH_4;
+  BmParams.Flags    = 0;
+  BmParams.CardIn   = SDCARD_STATUS_UNKNOWN;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+    &Handle,
+    &gSophgoMmcHostProtocolGuid,
+    &gMmcHost,
+    NULL
+  );
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
-- 
2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108378): https://edk2.groups.io/g/devel/message/108378
Mute This Topic: https://groups.io/mt/101213491/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 3/8] Sophgo/SG2042Pkg: Add Sophgo SDHCI driver.
Posted by Leif Lindholm 11 months, 4 weeks ago
On Thu, Sep 07, 2023 at 18:25:46 +0800, caiyuqing_hz@163.com wrote:
> From: caiyuqing379 <202235273@mail.sdu.edu.cn>
> 
> This driver implements Sophgo SDHCI controller, which provides
> the necessary interfaces for handling communication and data
> transfer with SD cards.
> 
> Signed-off-by: caiyuqing379 <202235273@mail.sdu.edu.cn>
> Co-authored-by: USER0FISH <libing1202@outlook.com>
> Cc: dahogn <dahogn@hotmail.com>
> Cc: meng-cz <mengcz1126@gmail.com>
> Cc: yli147 <yong.li@intel.com>
> Cc: ChaiEvan <evan.chai@intel.com>
> Cc: Sunil V L <sunilvl@ventanamicro.com>
> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> ---
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf |  47 +
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHci.h       | 309 ++++++
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHci.c       | 929 ++++++++++++++++++
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c   | 450 +++++++++
>  4 files changed, 1735 insertions(+)
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
>  create mode 100755 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
> 

> diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
> new file mode 100644
> index 000000000000..d9a9c88674e6
> --- /dev/null
> +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
> @@ -0,0 +1,309 @@
> +/** @file
> +  The header file that provides definitions and function declarations
> +  related to the SD Host Controller Interface (SDHCI) for SD card host controllers.
> +
> +  Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
> +  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-3-Clause

The license for this whole repository is BSD-2-Clause-Patent.
What is the origin code that this is based on?

> +
> +**/
> +
> +#ifndef _SD_HCI_H_
> +#define _SD_HCI_H_
> +
> +#define SDIO_BASE                       (FixedPcdGet64(PcdSG2042SDIOBase))
> +#define SDHCI_DMA_ADDRESS               0x00
> +#define SDHCI_BLOCK_SIZE                0x04
> +#define SDHCI_MAKE_BLKSZ(dma, blksz)    ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
> +#define SDHCI_BLOCK_COUNT               0x06
> +#define SDHCI_ARGUMENT                  0x08
> +#define SDHCI_TRANSFER_MODE             0x0C
> +#define SDHCI_TRNS_DMA                  BIT0
> +#define SDHCI_TRNS_BLK_CNT_EN           BIT1
> +#define SDHCI_TRNS_ACMD12               BIT2
> +#define SDHCI_TRNS_READ                 BIT4
> +#define SDHCI_TRNS_MULTI                BIT5
> +#define SDHCI_TRNS_RESP_INT             BIT8
> +#define SDHCI_COMMAND                   0x0E
> +#define SDHCI_CMD_RESP_MASK             0x03
> +#define SDHCI_CMD_CRC                   0x08
> +#define SDHCI_CMD_INDEX                 0x10
> +#define SDHCI_CMD_DATA                  0x20
> +#define SDHCI_CMD_ABORTCMD              0xC0
> +#define SDHCI_CMD_RESP_NONE             0x00
> +#define SDHCI_CMD_RESP_LONG             0x01
> +#define SDHCI_CMD_RESP_SHORT            0x02
> +#define SDHCI_CMD_RESP_SHORT_BUSY       0x03
> +#define SDHCI_MAKE_CMD(c, f)            ((((c) & 0xff) << 8) | ((f) & 0xff))
> +#define SDHCI_RESPONSE_01               0x10
> +#define SDHCI_RESPONSE_23               0x14
> +#define SDHCI_RESPONSE_45               0x18
> +#define SDHCI_RESPONSE_67               0x1C
> +#define SDHCI_PSTATE                    0x24
> +#define SDHCI_CMD_INHIBIT               BIT0
> +#define SDHCI_CMD_INHIBIT_DAT           BIT1
> +#define SDHCI_BUF_WR_ENABLE             BIT10
> +#define SDHCI_BUF_RD_ENABLE             BIT11
> +#define SDHCI_CARD_INSERTED             BIT16
> +#define SDHCI_HOST_CONTROL              0x28
> +#define SDHCI_DAT_XFER_WIDTH            BIT1
> +#define SDHCI_EXT_DAT_XFER              BIT5
> +#define SDHCI_CTRL_DMA_MASK             0x18
> +#define SDHCI_CTRL_SDMA                 0x00
> +#define SDHCI_PWR_CONTROL               0x29
> +#define SDHCI_BUS_VOL_VDD1_1_8V         0xC
> +#define SDHCI_BUS_VOL_VDD1_3_0V         0xE
> +#define SDHCI_BUF_DATA_R                0x20
> +#define SDHCI_BLOCK_GAP_CONTROL         0x2A
> +#define SDHCI_CLK_CTRL                  0x2C
> +#define SDHCI_TOUT_CTRL                 0x2E
> +#define SDHCI_SOFTWARE_RESET            0x2F
> +#define SDHCI_RESET_CMD                 0x02
> +#define SDHCI_RESET_DATA                0x04
> +#define SDHCI_INT_STATUS                0x30
> +#define SDHCI_ERR_INT_STATUS            0x32
> +#define SDHCI_INT_CMD_COMPLETE          BIT0
> +#define SDHCI_INT_XFER_COMPLETE         BIT1
> +#define SDHCI_INT_DMA_END               BIT3
> +#define SDHCI_INT_BUF_WR_READY          BIT4
> +#define SDHCI_INT_BUF_RD_READY          BIT5
> +#define SDHCI_INT_ERROR                 BIT15
> +#define SDHCI_INT_STATUS_EN             0x34
> +#define SDHCI_ERR_INT_STATUS_EN         0x36
> +#define SDHCI_INT_CMD_COMPLETE_EN       BIT0
> +#define SDHCI_INT_XFER_COMPLETE_EN      BIT1
> +#define SDHCI_INT_DMA_END_EN            BIT3
> +#define SDHCI_INT_CARD_INSERTION_EN     BIT6
> +#define SDHCI_INT_ERROR_EN              BIT15
> +#define SDHCI_SIGNAL_ENABLE             0x38
> +#define SDHCI_HOST_CONTROL2             0x3E
> +#define SDHCI_HOST_VER4_ENABLE          BIT12
> +#define SDHCI_CAPABILITIES1             0x40
> +#define SDHCI_CAPABILITIES2             0x44
> +#define SDHCI_ADMA_SA_LOW               0x58
> +#define SDHCI_ADMA_SA_HIGH              0x5C
> +#define SDHCI_HOST_CNTRL_VERS           0xFE
> +#define SDHCI_UHS_2_TIMER_CNTRL         0xC2
> +
> +#define P_VENDOR_SPECIFIC_AREA          0xE8
> +#define P_VENDOR2_SPECIFIC_AREA         0xEA
> +#define VENDOR_SD_CTRL                  0x2C
> +
> +#define SDHCI_PHY_R_OFFSET              0x300
> +
> +#define SDHCI_P_PHY_CNFG        (SDHCI_PHY_R_OFFSET + 0x00)
> +#define SDHCI_P_CMDPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x04)
> +#define SDHCI_P_DATPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x06)
> +#define SDHCI_P_CLKPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x08)
> +#define SDHCI_P_STBPAD_CNFG     (SDHCI_PHY_R_OFFSET + 0x0A)
> +#define SDHCI_P_RSTNPAD_CNFG    (SDHCI_PHY_R_OFFSET + 0x0C)
> +#define SDHCI_P_PADTEST_CNFG    (SDHCI_PHY_R_OFFSET + 0x0E)
> +#define SDHCI_P_PADTEST_OUT     (SDHCI_PHY_R_OFFSET + 0x10)
> +#define SDHCI_P_PADTEST_IN      (SDHCI_PHY_R_OFFSET + 0x12)
> +#define SDHCI_P_COMMDL_CNFG     (SDHCI_PHY_R_OFFSET + 0x1C)
> +#define SDHCI_P_SDCLKDL_CNFG    (SDHCI_PHY_R_OFFSET + 0x1D)
> +#define SDHCI_P_SDCLKDL_DC      (SDHCI_PHY_R_OFFSET + 0x1E)
> +#define SDHCI_P_SMPLDL_CNFG     (SDHCI_PHY_R_OFFSET + 0x20)
> +#define SDHCI_P_ATDL_CNFG       (SDHCI_PHY_R_OFFSET + 0x21)
> +#define SDHCI_P_DLL_CTRL        (SDHCI_PHY_R_OFFSET + 0x24)
> +#define SDHCI_P_DLL_CNFG1       (SDHCI_PHY_R_OFFSET + 0x25)
> +#define SDHCI_P_DLL_CNFG2       (SDHCI_PHY_R_OFFSET + 0x26)
> +#define SDHCI_P_DLLDL_CNFG      (SDHCI_PHY_R_OFFSET + 0x28)
> +#define SDHCI_P_DLL_OFFST       (SDHCI_PHY_R_OFFSET + 0x29)
> +#define SDHCI_P_DLLMST_TSTDC    (SDHCI_PHY_R_OFFSET + 0x2A)
> +#define SDHCI_P_DLLLBT_CNFG     (SDHCI_PHY_R_OFFSET + 0x2C)
> +#define SDHCI_P_DLL_STATUS      (SDHCI_PHY_R_OFFSET + 0x2E)
> +#define SDHCI_P_DLLDBG_MLKDC    (SDHCI_PHY_R_OFFSET + 0x30)
> +#define SDHCI_P_DLLDBG_SLKDC    (SDHCI_PHY_R_OFFSET + 0x32)
> +
> +#define PHY_CNFG_PHY_RSTN       0
> +#define PHY_CNFG_PHY_PWRGOOD    1
> +#define PHY_CNFG_PAD_SP         16
> +#define PHY_CNFG_PAD_SP_MSK     0xf
> +#define PHY_CNFG_PAD_SN         20
> +#define PHY_CNFG_PAD_SN_MSK     0xf
> +
> +#define PAD_CNFG_RXSEL                0
> +#define PAD_CNFG_RXSEL_MSK            0x7
> +#define PAD_CNFG_WEAKPULL_EN          3
> +#define PAD_CNFG_WEAKPULL_EN_MSK      0x3
> +#define PAD_CNFG_TXSLEW_CTRL_P        5
> +#define PAD_CNFG_TXSLEW_CTRL_P_MSK    0xf
> +#define PAD_CNFG_TXSLEW_CTRL_N        9
> +#define PAD_CNFG_TXSLEW_CTRL_N_MSK    0xf
> +
> +#define COMMDL_CNFG_DLSTEP_SEL        0
> +#define COMMDL_CNFG_DLOUT_EN          1
> +
> +#define SDCLKDL_CNFG_EXTDLY_EN        0
> +#define SDCLKDL_CNFG_BYPASS_EN        1
> +#define SDCLKDL_CNFG_INPSEL_CNFG      2
> +#define SDCLKDL_CNFG_INPSEL_CNFG_MSK  0x3
> +#define SDCLKDL_CNFG_UPDATE_DC        4
> +
> +#define SMPLDL_CNFG_EXTDLY_EN         0
> +#define SMPLDL_CNFG_BYPASS_EN         1
> +#define SMPLDL_CNFG_INPSEL_CNFG       2
> +#define SMPLDL_CNFG_INPSEL_CNFG_MSK   0x3
> +#define SMPLDL_CNFG_INPSEL_OVERRIDE   4
> +
> +#define ATDL_CNFG_EXTDLY_EN           0
> +#define ATDL_CNFG_BYPASS_EN           1
> +#define ATDL_CNFG_INPSEL_CNFG         2
> +#define ATDL_CNFG_INPSEL_CNFG_MSK     0x3
> +
> +#define SD_USE_PIO                    0x1
> +
> +/**
> +  card detect status
> +  -1: haven't check the card detect register
> +  0 : no card detected
> +  1 : card detected
> +**/
> +#define SDCARD_STATUS_UNKNOWN       (-1)
> +#define SDCARD_STATUS_INSERTED      (1)
> +#define SDCARD_STATUS_NOT_INSERTED  (0)
> +
> +typedef struct {
> +  UINT32  CmdIdx;
> +  UINT32  CmdArg;
> +  UINT32  ResponseType;
> +  UINT32  Response[4];
> +} MMC_CMD;
> +
> +typedef struct {
> +  UINTN   RegBase;
> +  UINTN   VendorBase;
> +  UINTN   DescBase;
> +  UINTN   DescSize;
> +  INT32   ClkRate;
> +  INT32   BusWidth;
> +  UINT32  Flags;
> +  INT32   CardIn;
> +} BM_SD_PARAMS;
> +
> +extern BM_SD_PARAMS BmParams;
> +
> +/**
> +  SD card sends command.
> +
> +  @param[in]  Idx       Command ID.
> +  @param[in]  Arg       Command argument.
> +  @param[in]  RespType  Type of response data.
> +  @param[out] Response  Response data.
> +
> +  @retval  EFI_SUCCESS             The command was sent successfully.
> +  @retval  EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
> +  @retval  EFI_TIMEOUT             The command transmission or response handling timed out.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +BmSdSendCmd (
> +  IN  UINT32 Idx,
> +  IN  UINT32 Arg,
> +  IN  UINT32 RespType,
> +  OUT UINT32 *Response
> +  );
> +
> +/**
> +  Detect the status of the SD card.
> +
> +  @return The status of the SD card:
> +          - SDCARD_STATUS_INSERTED:      The SD card is inserted.
> +          - SDCARD_STATUS_NOT_INSERTED:  The SD card is not inserted.
> +          - SDCARD_STATUS_UNKNOWN:       The status of the SD card is unknown.
> +
> +**/
> +INT32
> +BmSdCardDetect (
> +  VOID
> +  );
> +
> +/**
> +  Set the input/output settings for the SD card.
> +
> +  @param[in] Clk     The clock frequency for the SD card.
> +  @param[in] Width   The bus width for data transfer.
> +
> +  @retval EFI_SUCCESS             The input/output settings were set successfully.
> +  @retval EFI_UNSUPPORTED         The specified bus width is not supported.
> +
> +**/
> +EFI_STATUS
> +BmSdSetIos (
> +  IN UINT32 Clk,
> +  IN UINT32 Width
> +  );
> +
> +/**
> +  Prepare the SD card for data transfer.
> +  Set the number and size of data blocks before sending IO commands to the SD card.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval EFI_SUCCESS             The SD card was prepared successfully.
> +  @retval Other                   An error occurred during the preparation of the SD card.
> +
> +**/
> +EFI_STATUS
> +BmSdPrepare (
> +  IN INT32 Lba,
> +  IN UINTN Buf,
> +  IN UINTN Size
> +  );
> +
> +/**
> +  SD card sends command to read data blocks.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval  EFI_SUCCESS             The command to read data blocks was sent successfully.
> +  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
> +
> +**/
> +EFI_STATUS
> +BmSdRead (
> +  IN INT32   Lba,
> +  IN UINT32* Buf,
> +  IN UINTN   Size
> +  );
> +
> +/**
> +  SD card sends commands to write data blocks.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval  EFI_SUCCESS             The command to write data blocks was sent successfully.
> +  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
> +
> +**/
> +EFI_STATUS
> +BmSdWrite (
> +  IN INT32   Lba,
> +  IN UINT32* Buf,
> +  IN UINTN   Size
> +  );
> +
> +/**
> +  Initialize the SD card.
> +
> +  This function performs the initialization of the SD card hardware and settings.
> +
> +  @param[in] Flags     Initialization flags.
> +
> +  @retval EFI_SUCCESS  The SD card was initialized successfully.
> +
> +**/
> +EFI_STATUS
> +SdInit (
> +  IN UINT32  flags
> +  );
> +
> +#endif
> diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
> new file mode 100755
> index 000000000000..efa9f6397a1e
> --- /dev/null
> +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
> @@ -0,0 +1,929 @@
> +/** @file
> +  The implementation for handling SD card operations using the SD Host Controller Interface (SDHCI).
> +
> +  Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
> +  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-3-Clause

Same as above.

/
    Leif

> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Base.h>
> +#include <Library/BaseLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Include/MmcHost.h>
> +
> +#include "SdHci.h"
> +
> +#define SDCARD_INIT_FREQ  (200 * 1000)
> +#define SDCARD_TRAN_FREQ  (6 * 1000 * 1000)
> +
> +/**
> +  Return the clock rate of SD card.
> +
> +  @retval the clock rate of SD card.
> +
> +**/
> +INT32
> +BmGetSdClk (
> +  VOID
> +  )
> +{
> +  return 100*1000*1000;
> +}
> +
> +/**
> +  SD card sends command with response block data.
> +
> +  @param    Cmd   Command sent by SD card.
> +
> +  @retval EFI_SUCCESS             The command with response block data was sent successfully.
> +  @retval EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
> +  @retval EFI_TIMEOUT             The command transmission or response handling timed out.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdSendCmdWithData (
> +  IN OUT MMC_CMD *Cmd
> +  )
> +{
> +  UINTN   Base;
> +  UINT32  Mode;
> +  UINT32  State;
> +  UINT32  DmaAddr;
> +  UINT32  Flags;
> +  UINT32  Timeout;
> +
> +  Base  = BmParams.RegBase;
> +  Mode  = 0;
> +  Flags = 0;
> +
> +  // Make sure Cmd line is clear
> +  while (1) {
> +    if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT))
> +    break;
> +  }
> +
> +  switch (Cmd->CmdIdx) {
> +    case MMC_CMD17:
> +    case MMC_CMD18:
> +    case MMC_ACMD51:
> +      Mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI | SDHCI_TRNS_READ;
> +      if (!(BmParams.Flags & SD_USE_PIO))
> +        Mode |= SDHCI_TRNS_DMA;
> +      break;
> +    case MMC_CMD24:
> +    case MMC_CMD25:
> +      Mode = (SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI) & ~SDHCI_TRNS_READ;
> +      if (!(BmParams.Flags & SD_USE_PIO))
> +        Mode |= SDHCI_TRNS_DMA;
> +      break;
> +    default:
> +      ASSERT(0);
> +  }
> +
> +  MmioWrite16 (Base + SDHCI_TRANSFER_MODE, Mode);
> +  MmioWrite32 (Base + SDHCI_ARGUMENT, Cmd->CmdArg);
> +
> +  // set Cmd Flags
> +  if (Cmd->CmdIdx == MMC_CMD0)
> +    Flags |= SDHCI_CMD_RESP_NONE;
> +  else {
> +    if (Cmd->ResponseType & MMC_RSP_136)
> +      Flags |= SDHCI_CMD_RESP_LONG;
> +    else
> +      Flags |= SDHCI_CMD_RESP_SHORT;
> +    if (Cmd->ResponseType & MMC_RSP_CRC)
> +      Flags |= SDHCI_CMD_CRC;
> +    if (Cmd->ResponseType & MMC_RSP_CMD_IDX)
> +      Flags |= SDHCI_CMD_INDEX;
> +  }
> +
> +  Flags |= SDHCI_CMD_DATA;
> +
> +  // issue the Cmd
> +  MmioWrite16 (Base + SDHCI_COMMAND, SDHCI_MAKE_CMD(Cmd->CmdIdx, Flags));
> +
> +  // check Cmd complete if necessary
> +  if ((MmioRead16 (Base + SDHCI_TRANSFER_MODE) & SDHCI_TRNS_RESP_INT) == 0) {
> +    Timeout = 100000;
> +    while (1) {
> +      State = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if (State & SDHCI_INT_ERROR) {
> +        DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
> +                                MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
> +        return EFI_DEVICE_ERROR;
> +      }
> +      if (State & SDHCI_INT_CMD_COMPLETE) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS, State | SDHCI_INT_CMD_COMPLETE);
> +        break;
> +      }
> +
> +      gBS->Stall (1);
> +      if (!Timeout--) {
> +        DEBUG ((DEBUG_ERROR, "%a: Timeout!\n", __func__));
> +        return EFI_TIMEOUT;
> +      }
> +    }
> +
> +    // get Cmd respond
> +    if (Flags != SDHCI_CMD_RESP_NONE)
> +      Cmd->Response[0] = MmioRead32 (Base + SDHCI_RESPONSE_01);
> +    if (Flags & SDHCI_CMD_RESP_LONG) {
> +      Cmd->Response[1] = MmioRead32 (Base + SDHCI_RESPONSE_23);
> +      Cmd->Response[2] = MmioRead32 (Base + SDHCI_RESPONSE_45);
> +      Cmd->Response[3] = MmioRead32 (Base + SDHCI_RESPONSE_67);
> +    }
> +  }
> +
> +  // check dma/transfer complete
> +  if (!(BmParams.Flags & SD_USE_PIO)) {
> +    while (1) {
> +      State = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if (State & SDHCI_INT_ERROR) {
> +        DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
> +                                MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
> +        return EFI_DEVICE_ERROR;
> +      }
> +
> +      if (State & SDHCI_INT_XFER_COMPLETE) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS, State);
> +        break;
> +      }
> +
> +      if (State & SDHCI_INT_DMA_END) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS, State);
> +        if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & SDHCI_HOST_VER4_ENABLE) {
> +          DmaAddr = MmioRead32 (Base + SDHCI_ADMA_SA_LOW);
> +          MmioWrite32 (Base + SDHCI_ADMA_SA_LOW, DmaAddr);
> +          MmioWrite32 (Base + SDHCI_ADMA_SA_HIGH, 0);
> +        } else {
> +          DmaAddr = MmioRead32 (Base + SDHCI_DMA_ADDRESS);
> +          MmioWrite32 (Base + SDHCI_DMA_ADDRESS, DmaAddr);
> +        }
> +      }
> +
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  SD card sends command without response block data.
> +
> +  @param    Cmd   Command sent by SD card.
> +
> +  @retval EFI_SUCCESS             The command without response block data was sent successfully.
> +  @retval EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
> +  @retval EFI_TIMEOUT             The command transmission or response handling timed out.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdSendCmdWithoutData (
> +  IN OUT MMC_CMD *Cmd
> +  )
> +{
> +  UINTN   Base;
> +  UINT32  State;
> +  UINT32  Flags;
> +  UINT32  Timeout;
> +
> +  Base    = BmParams.RegBase;
> +  Flags   = 0x0;
> +  Timeout = 10000;
> +
> +  // make sure Cmd line is clear
> +  while (1) {
> +    if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT))
> +      break;
> +  }
> +
> +  // set Cmd Flags
> +  if (Cmd->CmdIdx == MMC_CMD0)
> +    Flags |= SDHCI_CMD_RESP_NONE;
> +  else if (Cmd->CmdIdx == MMC_CMD1)
> +    Flags |= SDHCI_CMD_RESP_SHORT;
> +  else if (Cmd->CmdIdx == MMC_ACMD41)
> +    Flags |= SDHCI_CMD_RESP_SHORT;
> +  else {
> +    if (Cmd->ResponseType & MMC_RSP_136)
> +      Flags |= SDHCI_CMD_RESP_LONG;
> +    else
> +      Flags |= SDHCI_CMD_RESP_SHORT;
> +    if (Cmd->ResponseType & MMC_RSP_CRC)
> +      Flags |= SDHCI_CMD_CRC;
> +    if (Cmd->ResponseType & MMC_RSP_CMD_IDX)
> +      Flags |= SDHCI_CMD_INDEX;
> +  }
> +
> +  // make sure dat line is clear if necessary
> +  if (Flags != SDHCI_CMD_RESP_NONE) {
> +    while (1) {
> +      if (!(MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_CMD_INHIBIT_DAT))
> +        break;
> +    }
> +  }
> +
> +  // issue the Cmd
> +  MmioWrite32 (Base + SDHCI_ARGUMENT, Cmd->CmdArg);
> +  MmioWrite16 (Base + SDHCI_COMMAND, SDHCI_MAKE_CMD(Cmd->CmdIdx, Flags));
> +
> +  // check Cmd complete
> +  Timeout = 100000;
> +  while (1) {
> +    State = MmioRead16 (Base + SDHCI_INT_STATUS);
> +    if (State & SDHCI_INT_ERROR) {
> +      DEBUG ((DEBUG_ERROR, "%a: interrupt error: 0x%x 0x%x\n", __func__,  MmioRead16 (Base + SDHCI_INT_STATUS),
> +                              MmioRead16 (Base + SDHCI_ERR_INT_STATUS)));
> +      return EFI_DEVICE_ERROR;
> +    }
> +    if (State & SDHCI_INT_CMD_COMPLETE) {
> +      MmioWrite16 (Base + SDHCI_INT_STATUS, State | SDHCI_INT_CMD_COMPLETE);
> +      break;
> +    }
> +
> +    gBS->Stall (1);
> +    if (!Timeout--) {
> +      DEBUG ((DEBUG_ERROR, "%a: Timeout!\n", __func__));
> +      return EFI_TIMEOUT;
> +    }
> +  }
> +
> +  // get Cmd respond
> +  if (!(Flags & SDHCI_CMD_RESP_NONE))
> +    Cmd->Response[0] = MmioRead32 (Base + SDHCI_RESPONSE_01);
> +  if (Flags & SDHCI_CMD_RESP_LONG) {
> +    Cmd->Response[1] = MmioRead32 (Base + SDHCI_RESPONSE_23);
> +    Cmd->Response[2] = MmioRead32 (Base + SDHCI_RESPONSE_45);
> +    Cmd->Response[3] = MmioRead32 (Base + SDHCI_RESPONSE_67);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  SD card sends command.
> +
> +  @param[in]  Idx       Command ID.
> +  @param[in]  Arg       Command argument.
> +  @param[in]  RespType  Type of response data.
> +  @param[out] Response  Response data.
> +
> +  @retval  EFI_SUCCESS             The command was sent successfully.
> +  @retval  EFI_DEVICE_ERROR        There was an error during the command transmission or response handling.
> +  @retval  EFI_TIMEOUT             The command transmission or response handling timed out.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +BmSdSendCmd (
> +  IN  UINT32 Idx,
> +  IN  UINT32 Arg,
> +  IN  UINT32 RespType,
> +  OUT UINT32 *Response
> +  )
> +{
> +  EFI_STATUS  Status;
> +  MMC_CMD     Cmd;
> +
> +  // DEBUG ((DEBUG_INFO, "%a: SDHCI Cmd, Idx=%d, Arg=0x%x, ResponseType=0x%x\n", __func__, Idx, Arg, RespType));
> +
> +  ZeroMem(&Cmd,sizeof(MMC_CMD));
> +
> +  Cmd.CmdIdx       = Idx;
> +  Cmd.CmdArg       = Arg;
> +  Cmd.ResponseType = RespType;
> +
> +  switch (Cmd.CmdIdx) {
> +    case MMC_CMD17:
> +    case MMC_CMD18:
> +    case MMC_CMD24:
> +    case MMC_CMD25:
> +    case MMC_ACMD51:
> +      Status = SdSendCmdWithData(&Cmd);
> +      break;
> +    default:
> +      Status = SdSendCmdWithoutData(&Cmd);
> +  }
> +
> +  if ((Status == EFI_SUCCESS) && (Response != NULL)) {
> +    for (INT32 I = 0; I < 4; I++) {
> +      *Response = Cmd.Response[I];
> +      Response++;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Set clock frequency of SD card.
> +
> +  @param[in] Clk       The clock frequency of SD card.
> +
> +**/
> +VOID
> +SdSetClk (
> +  IN INT32 Clk
> +  )
> +{
> +  INT32  I;
> +  INT32  Div;
> +  UINTN  Base;
> +
> +  ASSERT (Clk > 0);
> +
> +  if (BmParams.ClkRate <= Clk) {
> +    Div = 0;
> +  } else {
> +    for (Div = 0x1; Div < 0xFF; Div++) {
> +      if (BmParams.ClkRate / (2 * Div) <= Clk)
> +        break;
> +    }
> +  }
> +  ASSERT (Div <= 0xFF);
> +
> +  Base = BmParams.RegBase;
> +  if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & (1 << 15)) {
> +    //verbose("Use SDCLK Preset Value\n");
> +  } else {
> +    //verbose("Set SDCLK by driver. Div=0x%x(%d)\n", Div, Div);
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +            MmioRead16 (Base + SDHCI_CLK_CTRL) & ~0x9); // disable INTERNAL_CLK_EN and PLL_ENABLE
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +            (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0xDF) | Div << 8); // set Clk Div
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +            MmioRead16 (Base + SDHCI_CLK_CTRL) | 0x1); // set INTERNAL_CLK_EN
> +
> +    for (I = 0; I <= 150000; I += 100) {
> +      if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
> +        break;
> +      gBS->Stall (100);
> +    }
> +
> +    if (I > 150000) {
> +      DEBUG ((DEBUG_ERROR, "%a: SD INTERNAL_CLK_EN setting FAILED!\n", __func__));
> +      ASSERT(0);
> +    }
> +
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL, MmioRead16 (Base + SDHCI_CLK_CTRL) | 0x8); // set PLL_ENABLE
> +
> +    for (I = 0; I <= 150000; I += 100) {
> +      if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
> +        return;
> +      gBS->Stall (100);
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: SD PLL setting FAILED!\n", __func__));
> +}
> +
> +/**
> +  Change clock frequency of SD card.
> +
> +  @param[in] Clk       The clock frequency of SD card.
> +
> +**/
> +VOID
> +SdChangeClk (
> +  IN INT32 Clk
> +  )
> +{
> +  INT32  I;
> +  INT32  Div;
> +  UINTN  Base;
> +
> +  ASSERT (Clk > 0);
> +
> +  if (BmParams.ClkRate <= Clk) {
> +    Div = 0;
> +  } else {
> +    for (Div = 0x1; Div < 0xFF; Div++) {
> +      if (BmParams.ClkRate / (2 * Div) <= Clk)
> +        break;
> +    }
> +  }
> +  ASSERT (Div <= 0xFF);
> +
> +  Base = BmParams.RegBase;
> +
> +  MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +          MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 2)); // stop SD clock
> +
> +  MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +          MmioRead16 (Base + SDHCI_CLK_CTRL) & ~0x8); // disable  PLL_ENABLE
> +
> +  if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & (1 << 15)) {
> +    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +            MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
> +  } else {
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +            (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0xDF) | Div << 8); // set Clk Div
> +    MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +            MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 5)); // CLK_GEN_SELECT
> +  }
> +
> +  MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +          MmioRead16 (Base + SDHCI_CLK_CTRL) | 0xc); // enable  PLL_ENABLE
> +
> +  for (I = 0; I <= 150000; I += 100) {
> +    if (MmioRead16 (Base + SDHCI_CLK_CTRL) & 0x2)
> +      return;
> +    gBS->Stall (100);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: SD PLL setting FAILED!\n", __func__));
> +}
> +
> +/**
> +  Detect the status of the SD card.
> +
> +  @return The status of the SD card:
> +          - SDCARD_STATUS_INSERTED:      The SD card is inserted.
> +          - SDCARD_STATUS_NOT_INSERTED:  The SD card is not inserted.
> +          - SDCARD_STATUS_UNKNOWN:       The status of the SD card is unknown.
> +
> +**/
> +INT32
> +BmSdCardDetect (
> +  VOID
> +  )
> +{
> +  UINTN  Base;
> +  UINTN  Reg;
> +
> +  Base = BmParams.RegBase;
> +
> +  if (BmParams.CardIn != SDCARD_STATUS_UNKNOWN)
> +    return BmParams.CardIn;
> +
> +  MmioWrite16 (Base + SDHCI_INT_STATUS_EN,
> +          MmioRead16 (Base + SDHCI_INT_STATUS_EN) | SDHCI_INT_CARD_INSERTION_EN);
> +
> +  Reg = MmioRead32 (Base + SDHCI_PSTATE);
> +
> +  if (Reg & SDHCI_CARD_INSERTED)
> +    BmParams.CardIn = SDCARD_STATUS_INSERTED;
> +  else
> +    BmParams.CardIn = SDCARD_STATUS_NOT_INSERTED;
> +
> +  return BmParams.CardIn;
> +}
> +
> +/**
> +  SD card hardware initialization.
> +
> +**/
> +STATIC
> +VOID
> +SdHwInit (
> +  VOID
> +  )
> +{
> +  UINTN  Base;
> +
> +  Base                = BmParams.RegBase;
> +  BmParams.VendorBase = Base + (MmioRead16 (Base + P_VENDOR_SPECIFIC_AREA) & ((1 << 12) - 1));
> +
> +  // deasset reset of phy
> +  MmioWrite32 (Base + SDHCI_P_PHY_CNFG, MmioRead32 (Base + SDHCI_P_PHY_CNFG) | (1 << PHY_CNFG_PHY_RSTN));
> +
> +  // reset data & Cmd
> +  MmioWrite8 (Base + SDHCI_SOFTWARE_RESET, 0x6);
> +
> +  // init common parameters
> +  MmioWrite8 (Base + SDHCI_PWR_CONTROL, (0x7 << 1));
> +  MmioWrite8 (Base + SDHCI_TOUT_CTRL, 0xe);  // for TMCLK 50Khz
> +  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +          MmioRead16 (Base + SDHCI_HOST_CONTROL2) | 1 << 11);  // set cmd23 support
> +  MmioWrite16 (Base + SDHCI_CLK_CTRL, MmioRead16 (Base + SDHCI_CLK_CTRL) & ~(0x1 << 5));  // divided clock Mode
> +
> +  // set host version 4 parameters
> +  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +          MmioRead16 (Base + SDHCI_HOST_CONTROL2) | (1 << 12)); // set HOST_VER4_ENABLE
> +  if (MmioRead32 (Base + SDHCI_CAPABILITIES1) & (0x1 << 27)) {
> +    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +            MmioRead16 (Base + SDHCI_HOST_CONTROL2) | 0x1 << 13); // set 64bit addressing
> +  }
> +
> +  // if support asynchronous int
> +  if (MmioRead32 (Base + SDHCI_CAPABILITIES1) & (0x1 << 29))
> +    MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +            MmioRead16 (Base + SDHCI_HOST_CONTROL2) | (0x1 << 14)); // enable async int
> +  // give some time to power down card
> +  gBS->Stall (20000);
> +
> +  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +          MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~(0x1 << 8)); // clr UHS2_IF_ENABLE
> +  MmioWrite8 (Base + SDHCI_PWR_CONTROL,
> +          MmioRead8 (Base + SDHCI_PWR_CONTROL) | 0x1); // set SD_BUS_PWR_VDD1
> +  MmioWrite16 (Base + SDHCI_HOST_CONTROL2,
> +          MmioRead16 (Base + SDHCI_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
> +  SdSetClk (SDCARD_INIT_FREQ);
> +  gBS->Stall (50000);
> +
> +  MmioWrite16 (Base + SDHCI_CLK_CTRL,
> +          MmioRead16 (Base + SDHCI_CLK_CTRL) | (0x1 << 2)); // supply SD clock
> +  gBS->Stall (400); // wait for voltage ramp up time at least 74 cycle, 400us is 80 cycles for 200Khz
> +
> +  MmioWrite16 (Base + SDHCI_INT_STATUS, MmioRead16 (Base + SDHCI_INT_STATUS) | (0x1 << 6));
> +
> +  // we enable all interrupt Status here for testing
> +  MmioWrite16 (Base + SDHCI_INT_STATUS_EN, MmioRead16 (Base + SDHCI_INT_STATUS_EN) | 0xFFFF);
> +  MmioWrite16 (Base + SDHCI_ERR_INT_STATUS_EN, MmioRead16 (Base + SDHCI_ERR_INT_STATUS_EN) | 0xFFFF);
> +
> +  //verbose("SD init done\n");
> +}
> +
> +/**
> +  Set the input/output settings for the SD card.
> +
> +  @param[in] Clk     The clock frequency for the SD card.
> +  @param[in] Width   The bus width for data transfer.
> +
> +  @retval EFI_SUCCESS             The input/output settings were set successfully.
> +  @retval EFI_UNSUPPORTED         The specified bus width is not supported.
> +
> +**/
> +EFI_STATUS
> +BmSdSetIos (
> +  IN UINT32 Clk,
> +  IN UINT32 Width
> +  )
> +{
> +  switch (Width) {
> +    case MMC_BUS_WIDTH_1:
> +      MmioWrite8 (BmParams.RegBase + SDHCI_HOST_CONTROL,
> +              MmioRead8 (BmParams.RegBase + SDHCI_HOST_CONTROL) &
> +              ~SDHCI_DAT_XFER_WIDTH);
> +      break;
> +    case MMC_BUS_WIDTH_4:
> +      MmioWrite8 (BmParams.RegBase + SDHCI_HOST_CONTROL,
> +              MmioRead8 (BmParams.RegBase + SDHCI_HOST_CONTROL) |
> +              SDHCI_DAT_XFER_WIDTH);
> +      break;
> +    default:
> +      ASSERT (0);
> +  }
> +
> +  SdChangeClk (Clk);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Prepare the SD card for data transfer.
> +  Set the number and size of data blocks before sending IO commands to the SD card.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval EFI_SUCCESS             The SD card was prepared successfully.
> +  @retval Other                   An error occurred during the preparation of the SD card.
> +
> +**/
> +EFI_STATUS
> +BmSdPrepare (
> +  IN INT32 Lba,
> +  IN UINTN Buf,
> +  IN UINTN Size
> +  )
> +{
> +  UINTN   LoadAddr;
> +  UINTN   Base;
> +  UINT32  BlockCnt;
> +  UINT32  BlockSize;
> +  UINT8   Tmp;
> +
> +  LoadAddr = Buf;
> +
> +  if (Size >= MMC_BLOCK_SIZE) {
> +    // CMD17, 18, 24, 25
> +    // ASSERT (((LoadAddr & MMC_BLOCK_MASK) == 0) && ((Size % MMC_BLOCK_SIZE) == 0));
> +    BlockSize = MMC_BLOCK_SIZE;
> +    BlockCnt  = Size / MMC_BLOCK_SIZE;
> +  } else {
> +    // ACMD51
> +    ASSERT (((LoadAddr & 8) == 0) && ((Size % 8) == 0));
> +    BlockSize = 8;
> +    BlockCnt  = Size / 8;
> +  }
> +
> +  Base = BmParams.RegBase;
> +
> +  if (!(BmParams.Flags & SD_USE_PIO)) {
> +    if (MmioRead16 (Base + SDHCI_HOST_CONTROL2) & SDHCI_HOST_VER4_ENABLE) {
> +      MmioWrite32 (Base + SDHCI_ADMA_SA_LOW, LoadAddr);
> +      MmioWrite32 (Base + SDHCI_ADMA_SA_HIGH, (LoadAddr >> 32));
> +      MmioWrite32 (Base + SDHCI_DMA_ADDRESS, BlockCnt);
> +      MmioWrite16 (Base + SDHCI_BLOCK_COUNT, 0);
> +    } else {
> +      ASSERT((LoadAddr >> 32) == 0);
> +      MmioWrite32 (Base + SDHCI_DMA_ADDRESS, LoadAddr);
> +      MmioWrite16 (Base + SDHCI_BLOCK_COUNT, BlockCnt);
> +    }
> +
> +    // 512K bytes SDMA buffer boundary
> +    MmioWrite16 (Base + SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, BlockSize));
> +
> +    // select SDMA
> +    Tmp = MmioRead8 (Base + SDHCI_HOST_CONTROL);
> +    Tmp &= ~SDHCI_CTRL_DMA_MASK;
> +    Tmp |= SDHCI_CTRL_SDMA;
> +    MmioWrite8 (Base + SDHCI_HOST_CONTROL, Tmp);
> +  } else {
> +    MmioWrite16 (Base + SDHCI_BLOCK_SIZE, BlockSize);
> +    MmioWrite16 (Base + SDHCI_BLOCK_COUNT, BlockCnt);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  SD card sends command to read data blocks.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval  EFI_SUCCESS             The command to read data blocks was sent successfully.
> +  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
> +
> +**/
> +EFI_STATUS
> +BmSdRead (
> +  IN INT32   Lba,
> +  IN UINT32* Buf,
> +  IN UINTN   Size
> +  )
> +{
> +  UINT32  Timeout;
> +  UINTN   Base;
> +  UINT32  *Data;
> +  UINT32  BlockSize;
> +  UINT32  BlockCnt;
> +  UINT32  Status;
> +
> +  Timeout   = 0;
> +  Base      = BmParams.RegBase;
> +  Data      = Buf;
> +  BlockSize = 0;
> +  BlockCnt  = 0;
> +  Status    = 0;
> +
> +  if (BmParams.Flags & SD_USE_PIO) {
> +    BlockSize = MmioRead16 (Base + SDHCI_BLOCK_SIZE);
> +    BlockCnt  = Size / BlockSize;
> +    BlockSize /= 4;
> +
> +    for (INT32 I = 0; I < BlockCnt; ) {
> +      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if ((Status & SDHCI_INT_BUF_RD_READY) &&
> +          (MmioRead32 (Base + SDHCI_PSTATE) & SDHCI_BUF_RD_ENABLE)) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS, SDHCI_INT_BUF_RD_READY);
> +        for (INT32 j = 0; j < BlockSize; j++) {
> +          *(Data++) = MmioRead32 (Base + SDHCI_BUF_DATA_R);
> +        }
> +
> +        Timeout = 0;
> +        I++;
> +      } else {
> +        gBS->Stall (1);
> +        Timeout++;
> +      }
> +
> +      if (Timeout >= 10000) {
> +        DEBUG ((DEBUG_INFO, "%a: sdhci read data Timeout\n", __func__));
> +        goto Timeout;
> +      }
> +    }
> +
> +    Timeout = 0;
> +    while (1) {
> +      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if (Status & SDHCI_INT_XFER_COMPLETE) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS,
> +                Status | SDHCI_INT_XFER_COMPLETE);
> +
> +        return EFI_SUCCESS;
> +      } else {
> +        gBS->Stall (1);
> +        Timeout++;
> +      }
> +
> +      if (Timeout >= 10000) {
> +        DEBUG ((DEBUG_INFO, "%a:wait xfer complete Timeout\n", __func__));
> +        goto Timeout;
> +      }
> +    }
> +  } else {
> +    return EFI_SUCCESS;
> +  }
> +
> +Timeout:
> +  return EFI_TIMEOUT;
> +
> +}
> +
> +/**
> +  SD card sends commands to write data blocks.
> +
> +  @param[in]  Lba       Logical Block Address.
> +  @param[in]  Buf       Buffer Address.
> +  @param[in]  Size      Size of Data Blocks.
> +
> +  @retval  EFI_SUCCESS             The command to write data blocks was sent successfully.
> +  @retval  EFI_TIMEOUT             The command transmission or data transfer timed out.
> +
> +**/
> +EFI_STATUS
> +BmSdWrite (
> +  IN INT32   Lba,
> +  IN UINT32* Buf,
> +  IN UINTN   Size
> +  )
> +{
> +  UINT32  Timeout;
> +  UINTN   Base;
> +  UINT32  *Data;
> +  UINT32  BlockSize;
> +  UINT32  BlockCnt;
> +  UINT32  Status;
> +
> +  Timeout   = 0;
> +  Base      = BmParams.RegBase;
> +  Data      = Buf;
> +  BlockSize = 0;
> +  BlockCnt  = 0;
> +  Status    = 0;
> +
> +  if (BmParams.Flags & SD_USE_PIO) {
> +    BlockSize = MmioRead16 (Base + SDHCI_BLOCK_SIZE);
> +    BlockCnt = Size / BlockSize;
> +    BlockSize /= 4;
> +
> +    for (INT32 j = 0; j < BlockSize; j++) {
> +      MmioWrite32 (Base + SDHCI_BUF_DATA_R, *(Data++));
> +    }
> +
> +    for (INT32 I = 0; I < BlockCnt-1; ) {
> +      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if ((Status & SDHCI_INT_BUF_WR_READY) &&
> +          (MmioRead32 (Base + SDHCI_PSTATE) &
> +          SDHCI_BUF_WR_ENABLE)) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS, SDHCI_INT_BUF_WR_READY);
> +        for (INT32 j = 0; j < BlockSize; j++) {
> +          MmioWrite32 (Base + SDHCI_BUF_DATA_R, *(Data++));
> +        }
> +
> +        Timeout = 0;
> +        I++;
> +      } else {
> +        gBS->Stall (1);
> +        Timeout++;
> +      }
> +
> +      if (Timeout >= 10000000) {
> +        DEBUG ((DEBUG_INFO, "%a:sdhci write data Timeout\n", __func__));
> +        goto Timeout;
> +      }
> +    }
> +
> +    Timeout = 0;
> +    while (1) {
> +      Status = MmioRead16 (Base + SDHCI_INT_STATUS);
> +      if (Status & SDHCI_INT_XFER_COMPLETE) {
> +        MmioWrite16 (Base + SDHCI_INT_STATUS,
> +                Status | SDHCI_INT_XFER_COMPLETE);
> +
> +        return EFI_SUCCESS;
> +      } else {
> +        gBS->Stall (1);
> +        Timeout++;
> +      }
> +
> +      if (Timeout >= 10000) {
> +        DEBUG ((DEBUG_INFO, "%a:wait xfer complete Timeout\n", __func__));
> +        goto Timeout;
> +      }
> +    }
> +  } else
> +    return EFI_SUCCESS;
> +
> +Timeout:
> +  return EFI_TIMEOUT;
> +}
> +
> +/**
> +  Initialize the SD PHY.
> +
> +  This function performs the initialization of the SD PHY hardware.
> +
> +**/
> +VOID
> +SdPhyInit (
> +  VOID
> +  )
> +{
> +  UINTN Base;
> +  INT32 RetryCount;
> +
> +  Base       = BmParams.RegBase;
> +  RetryCount = 100;
> +
> +  // reset hardware
> +  MmioWrite8 (Base + SDHCI_SOFTWARE_RESET, 0x7);
> +  while (MmioRead8 (Base + SDHCI_SOFTWARE_RESET)) {
> +    if (RetryCount-- > 0)
> +      gBS->Stall (10000);
> +    else
> +      break;
> +  }
> +
> +  // Wait for the PHY power on ready
> +  RetryCount = 100;
> +  while (!(MmioRead32 (Base + SDHCI_P_PHY_CNFG) & (1 << PHY_CNFG_PHY_PWRGOOD))) {
> +    if (RetryCount-- > 0)
> +      gBS->Stall (10000);
> +    else
> +      break;
> +  }
> +
> +  // Asset reset of phy
> +  MmioAnd32 (Base + SDHCI_P_PHY_CNFG, ~(1 << PHY_CNFG_PHY_RSTN));
> +
> +  // Set PAD_SN PAD_SP
> +  MmioWrite32 (Base + SDHCI_P_PHY_CNFG,
> +          (1 << PHY_CNFG_PHY_PWRGOOD) | (0x9 << PHY_CNFG_PAD_SP) | (0x8 << PHY_CNFG_PAD_SN));
> +
> +  // Set CMDPAD
> +  MmioWrite16 (Base + SDHCI_P_CMDPAD_CNFG,
> +          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
> +          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
> +
> +  // Set DATAPAD
> +  MmioWrite16 (Base + SDHCI_P_DATPAD_CNFG,
> +          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
> +          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
> +
> +  // Set CLKPAD
> +  MmioWrite16 (Base + SDHCI_P_CLKPAD_CNFG,
> +          (0x2 << PAD_CNFG_RXSEL) | (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
> +
> +  // Set STB_PAD
> +  MmioWrite16 (Base + SDHCI_P_STBPAD_CNFG,
> +          (0x2 << PAD_CNFG_RXSEL) | (0x2 << PAD_CNFG_WEAKPULL_EN) |
> +          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
> +
> +  // Set RSTPAD
> +  MmioWrite16 (Base + SDHCI_P_RSTNPAD_CNFG,
> +          (0x2 << PAD_CNFG_RXSEL) | (1 << PAD_CNFG_WEAKPULL_EN) |
> +          (0x3 << PAD_CNFG_TXSLEW_CTRL_P) | (0x2 << PAD_CNFG_TXSLEW_CTRL_N));
> +
> +  // Set SDCLKDL_CNFG, EXTDLY_EN = 1, fix delay
> +  MmioWrite8 (Base + SDHCI_P_SDCLKDL_CNFG, (1 << SDCLKDL_CNFG_EXTDLY_EN));
> +
> +  // Set SMPLDL_CNFG, Bypass
> +  MmioWrite8 (Base + SDHCI_P_SMPLDL_CNFG, (1 << SMPLDL_CNFG_BYPASS_EN));
> +
> +  // Set ATDL_CNFG, tuning Clk not use for init
> +  MmioWrite8 (Base + SDHCI_P_ATDL_CNFG, (2 << ATDL_CNFG_INPSEL_CNFG));
> +
> +  return;
> +}
> +
> +/**
> +  Initialize the SD card.
> +
> +  This function performs the initialization of the SD card hardware and settings.
> +
> +  @param[in] Flags     Initialization flags.
> +
> +  @retval EFI_SUCCESS  The SD card was initialized successfully.
> +
> +**/
> +EFI_STATUS
> +SdInit (
> +  IN UINT32 Flags
> +)
> +{
> +  BmParams.ClkRate = BmGetSdClk ();
> +
> +  DEBUG ((DEBUG_INFO, "SD initializing %dHz\n", BmParams.ClkRate));
> +
> +  BmParams.Flags = Flags;
> +
> +  SdPhyInit ();
> +
> +  SdHwInit ();
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
> new file mode 100644
> index 000000000000..3bb04344320a
> --- /dev/null
> +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
> @@ -0,0 +1,450 @@
> +/** @file
> +  This file implements the SD host controller driver for UEFI systems.
> +  The file contains the implementation of the EFI_MMC_HOST_PROTOCOL, which provides
> +  the necessary interfaces for handling communication and data transfer with SD cards.
> +
> +  Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
> +  Copyright (c) Microsoft Corporation. All rights reserved.
> +  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DmaLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <Protocol/EmbeddedExternalDevice.h>
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/DevicePath.h>
> +#include <Include/MmcHost.h>
> +
> +#include "SdHci.h"
> +
> +#define SDHOST_BLOCK_BYTE_LENGTH  512
> +
> +#define DEBUG_MMCHOST_SD          DEBUG_VERBOSE
> +#define DEBUG_MMCHOST_SD_INFO     DEBUG_INFO
> +#define DEBUG_MMCHOST_SD_ERROR    DEBUG_ERROR
> +
> +STATIC BOOLEAN            mCardIsPresent   = FALSE;
> +STATIC CARD_DETECT_STATE  mCardDetectState = CardDetectRequired;
> +BM_SD_PARAMS              BmParams;
> +
> +/**
> +  Check if the SD card is read-only.
> +
> +  @param[in] This      Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +
> +  @retval FALSE        The SD card is not read-only.
> +
> +**/
> +STATIC
> +BOOLEAN
> +SdIsReadOnly (
> +  IN EFI_MMC_HOST_PROTOCOL *This
> +  )
> +{
> +  return FALSE;
> +}
> +
> +/**
> +  Build the device path for the SD card.
> +
> +  @param[in]  This           Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[out] DevicePath     Pointer to the location to store the newly created device path.
> +
> +  @retval EFI_SUCCESS        The device path is built successfully.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdBuildDevicePath (
> +  IN  EFI_MMC_HOST_PROTOCOL       *This,
> +  OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
> +  EFI_GUID DevicePathGuid = EFI_CALLER_ID_GUID;
> +
> +  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: SdBuildDevicePath ()\n"));
> +
> +  NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
> +  CopyGuid (&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &DevicePathGuid);
> +  *DevicePath = NewDevicePathNode;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Send a command to the SD card.
> +
> +  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in] MmcCmd     The MMC command to send.
> +  @param[in] Argument   The argument for the command.
> +  @param[in] Type       The type of response expected.
> +  @param[in] Buffer     Pointer to the buffer to store the response.
> +
> +  @retval EFI_SUCCESS   The command was sent successfully and the response was retrieved.
> +  @retval Other         An error occurred while sending a command.
> +**/
> +STATIC
> +EFI_STATUS
> +SdSendCommand (
> +  IN EFI_MMC_HOST_PROTOCOL    *This,
> +  IN MMC_IDX                  MmcCmd,
> +  IN UINT32                   Argument,
> +  IN MMC_RESPONSE_TYPE        Type,
> +  IN UINT32*                  Buffer
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  Status = BmSdSendCmd (MmcCmd, Argument, Type, Buffer);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdSendCommand Error, Status=%r.\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read block data from an SD card.
> +
> +  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in] Lba        Logical Block Address of the starting block to read.
> +  @param[in] Length     Number of blocks to read.
> +  @param[in] Buffer     Pointer to the buffer to store the read data.
> +
> +  @retval EFI_SUCCESS   The operation completed successfully.
> +  @retval Other         The operation failed.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdReadBlockData (
> +  IN  EFI_MMC_HOST_PROTOCOL    *This,
> +  IN  EFI_LBA                  Lba,
> +  IN  UINTN                    Length,
> +  OUT UINT32*                  Buffer
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  ASSERT (Buffer != NULL);
> +  ASSERT (Length % 4 == 0);
> +
> +  Status = BmSdRead (Lba, Buffer, Length);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdReadBlockData Error, Status=%r.\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Write block data to an SD card.
> +
> +  @param[in] This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in] Lba        Logical Block Address of the starting block to write.
> +  @param[in] Length     Number of blocks to write.
> +  @param[in] Buffer     Pointer to the buffer containing the data to be written.
> +
> +  @retval EFI_SUCCESS   The operation completed successfully.
> +  @retval Other         The operation failed.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdWriteBlockData (
> +  IN EFI_MMC_HOST_PROTOCOL    *This,
> +  IN EFI_LBA                  Lba,
> +  IN UINTN                    Length,
> +  IN UINT32*                  Buffer
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: SdWriteBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n",(UINT32)Lba, Length, Buffer));
> +
> +  ASSERT (Buffer != NULL);
> +  ASSERT (Length % SDHOST_BLOCK_BYTE_LENGTH == 0);
> +
> +  Status = BmSdWrite (Lba, Buffer, Length);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdWriteBlockData Error, Status=%r.\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set the I/O settings for an SD card.
> +
> +  @param[in]  This           Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in]  BusClockFreq   Bus clock frequency in Hz.
> +  @param[in]  BusWidth       Bus width setting.
> +
> +  @retval EFI_SUCCESS        The operation completed successfully.
> +  @retval Other              The operation failed.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdSetIos (
> +  IN EFI_MMC_HOST_PROTOCOL      *This,
> +  IN  UINT32                    BusClockFreq,
> +  IN  UINT32                    BusWidth
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  DEBUG ((DEBUG_MMCHOST_SD_INFO, "%a: Setting Freq %u Hz\n", __func__, BusClockFreq));
> +  DEBUG ((DEBUG_MMCHOST_SD_INFO, "%a: Setting BusWidth %u\n", __func__, BusWidth));
> +
> +  Status = BmSdSetIos (BusClockFreq,BusWidth);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdSetIos Error, Status=%r.\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Prepare the SD card for data transfer.
> +
> +  @param[in]  This       Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in]  Lba        Logical Block Address of the starting block to prepare.
> +  @param[in]  Length     Number of blocks to prepare.
> +  @param[in]  Buffer     Buffer containing the data to be prepared.
> +
> +  @retval EFI_SUCCESS    The operation completed successfully.
> +  @retval Other          The operation failed.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdPrepare (
> +  IN EFI_MMC_HOST_PROTOCOL    *This,
> +  IN EFI_LBA                  Lba,
> +  IN UINTN                    Length,
> +  IN UINTN                    Buffer
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  Status = BmSdPrepare (Lba, Buffer, Length);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdPrepare Error, Status=%r.\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Notify the state of the SD card.
> +
> +  @param[in]  This    Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +  @param[in]  State   State of the SD card.
> +
> +  @retval EFI_SUCCESS       The operation completed successfully.
> +  @retval EFI_NOT_READY     The card detection has not completed yet.
> +  @retval Other             The operation failed.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdNotifyState (
> +  IN EFI_MMC_HOST_PROTOCOL    *This,
> +  IN MMC_STATE                State
> +  )
> +{
> +  // Stall all operations except init until card detection has occurred.
> +  if (State != MmcHwInitializationState && mCardDetectState != CardDetectCompleted) {
> +    return EFI_NOT_READY;
> +  }
> +
> +  switch (State) {
> +    case MmcHwInitializationState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcHwInitializationState\n", State));
> +
> +      EFI_STATUS Status = SdInit (SD_USE_PIO);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_MMCHOST_SD_ERROR,"SdHost: SdNotifyState(): Fail to initialize!\n"));
> +        return Status;
> +      }
> +      break;
> +    case MmcIdleState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcIdleState\n", State));
> +      break;
> +    case MmcReadyState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcReadyState\n", State));
> +      break;
> +    case MmcIdentificationState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcIdentificationState\n", State));
> +      break;
> +    case MmcStandByState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcStandByState\n", State));
> +      break;
> +    case MmcTransferState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcTransferState\n", State));
> +      break;
> +    case MmcSendingDataState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcSendingDataState\n", State));
> +      break;
> +    case MmcReceiveDataState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcReceiveDataState\n", State));
> +      break;
> +    case MmcProgrammingState:
> +      DEBUG ((DEBUG_MMCHOST_SD, "MmcProgrammingState\n", State));
> +      break;
> +    case MmcDisconnectState:
> +    case MmcInvalidState:
> +    default:
> +      DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdHost: SdNotifyState(): Invalid State: %d\n", State));
> +      ASSERT (0);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Check if an SD card is present.
> +
> +  @param[in]  This    Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +
> +  @retval TRUE        An SD card is present.
> +  @retval FALSE       No SD card is present.
> +
> +**/
> +STATIC
> +BOOLEAN
> +SdIsCardPresent (
> +  IN EFI_MMC_HOST_PROTOCOL *This
> +  )
> +{
> +  //
> +  // If we are already in progress (we may get concurrent calls)
> +  // or completed the detection, just return the current value.
> +  //
> +  if (mCardDetectState != CardDetectRequired) {
> +    return mCardIsPresent;
> +  }
> +
> +  mCardDetectState = CardDetectInProgress;
> +  mCardIsPresent = FALSE;
> +
> +  if (BmSdCardDetect () == 1) {
> +    mCardIsPresent = TRUE;
> +    goto out;
> +  }
> +  else {
> +    DEBUG ((DEBUG_MMCHOST_SD_ERROR, "SdIsCardPresent: Error SdCardDetect.\n"));
> +    mCardDetectState = CardDetectRequired;
> +    return FALSE;
> +  }
> +
> +  DEBUG ((DEBUG_MMCHOST_SD_INFO, "SdIsCardPresent: Not detected.\n"));
> +
> +out:
> +  mCardDetectState = CardDetectCompleted;
> +  return mCardIsPresent;
> +}
> +
> +/**
> +  Check if the SD card supports multi-block transfers.
> +
> +  @param[in]  This     Pointer to the EFI_MMC_HOST_PROTOCOL instance.
> +
> +  @retval TRUE         The SD card supports multi-block transfers.
> +
> +**/
> +BOOLEAN
> +SdIsMultiBlock (
> +  IN EFI_MMC_HOST_PROTOCOL *This
> +  )
> +{
> +  return TRUE;
> +}
> +
> +EFI_MMC_HOST_PROTOCOL gMmcHost = {
> +  MMC_HOST_PROTOCOL_REVISION,
> +  SdIsCardPresent,
> +  SdIsReadOnly,
> +  SdBuildDevicePath,
> +  SdNotifyState,
> +  SdSendCommand,
> +  SdReadBlockData,
> +  SdWriteBlockData,
> +  SdSetIos,
> +  SdPrepare,
> +  SdIsMultiBlock
> +};
> +
> +/**
> +  Initialize the SD host.
> +
> +  @param[in]  ImageHandle    The image handle.
> +  @param[in]  SystemTable    The system table.
> +
> +  @retval EFI_SUCCESS        The operation completed successfully.
> +  @retval Other              The operation failed.
> +**/
> +EFI_STATUS
> +SdHostInitialize (
> +  IN EFI_HANDLE          ImageHandle,
> +  IN EFI_SYSTEM_TABLE    *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_HANDLE  Handle;
> +  UINTN       Base;
> +
> +  DEBUG ((DEBUG_MMCHOST_SD, "SdHost: Initialize\n"));
> +
> +  Handle            = NULL;
> +  Base              = SDIO_BASE;
> +
> +  if(!PcdGetBool (PcdForceNoMMU)){
> +    for (INT32 I = 39; I < 64; I++) {
> +      if (Base & (1ULL << 38)) {
> +        Base |= (1ULL << I);
> +      } else {
> +        Base &= ~(1ULL << I);
> +      }
> +    }
> +  }
> +
> +  BmParams.RegBase  = Base;
> +  BmParams.ClkRate  = 50 * 1000 * 1000;
> +  BmParams.BusWidth = MMC_BUS_WIDTH_4;
> +  BmParams.Flags    = 0;
> +  BmParams.CardIn   = SDCARD_STATUS_UNKNOWN;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +    &Handle,
> +    &gSophgoMmcHostProtocolGuid,
> +    &gMmcHost,
> +    NULL
> +  );
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> -- 
> 2.34.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108729): https://edk2.groups.io/g/devel/message/108729
Mute This Topic: https://groups.io/mt/101213491/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 3/8] Sophgo/SG2042Pkg: Add Sophgo SDHCI driver.
Posted by Sunil V L 11 months, 4 weeks ago
On Thu, Sep 07, 2023 at 06:25:46PM +0800, caiyuqing_hz@163.com wrote:
> From: caiyuqing379 <202235273@mail.sdu.edu.cn>
> 
> This driver implements Sophgo SDHCI controller, which provides
> the necessary interfaces for handling communication and data
> transfer with SD cards.
> 
> Signed-off-by: caiyuqing379 <202235273@mail.sdu.edu.cn>
> Co-authored-by: USER0FISH <libing1202@outlook.com>
> Cc: dahogn <dahogn@hotmail.com>
> Cc: meng-cz <mengcz1126@gmail.com>
> Cc: yli147 <yong.li@intel.com>
> Cc: ChaiEvan <evan.chai@intel.com>
> Cc: Sunil V L <sunilvl@ventanamicro.com>
> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> ---
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf |  47 +
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHci.h       | 309 ++++++
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHci.c       | 929 ++++++++++++++++++
>  .../SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c   | 450 +++++++++
>  4 files changed, 1735 insertions(+)
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.h
>  create mode 100755 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHci.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.c
> 
> diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
> new file mode 100644
> index 000000000000..f4f51d8fde74
> --- /dev/null
> +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/SdHostDxe/SdHostDxe.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#  Component description file for the SD Host Controller DXE driver module.
> +#
> +#  Copyright (c) 2019, ARM Limited. All rights reserved.
> +#  Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
> +#  Copyright (c) Microsoft Corporation. All rights reserved.
> +#  Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
Just Curious. Why is INF_VERSION 0x0001001A? As per [1], I think new INF
file should have version 1.27.

[1] - https://tianocore-docs.github.io/edk2-InfSpecification/draft/2_inf_overview/24_[defines]_section.html#24-defines-section

Otherwise,
Acked-by: Sunil V L <sunilvl@ventanamicro.com>



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108709): https://edk2.groups.io/g/devel/message/108709
Mute This Topic: https://groups.io/mt/101213491/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-