public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Leif Lindholm" <quic_llindhol@quicinc.com>
To: <caiyuqing_hz@163.com>
Cc: <devel@edk2.groups.io>, <sunilvl@ventanamicro.com>,
	<libing1202@outlook.com>, <inochiama@outlook.com>
Subject: Re: [edk2-devel] [PATCH v3 4/8] Sophgo/SG2042Pkg: Add base MMC driver.
Date: Fri, 15 Sep 2023 15:25:26 +0100	[thread overview]
Message-ID: <ZQRpVhXyrvb5MDqo@qc-i7.hemma.eciton.net> (raw)
In-Reply-To: <adec58a0baf30299c07765cba9c9eebbc4a378ce.1694010673.git.202235273@mail.sdu.edu.cn>

On Thu, Sep 07, 2023 at 18:25:47 +0800, caiyuqing_hz@163.com wrote:
> From: caiyuqing379 <202235273@mail.sdu.edu.cn>
> 
> This driver implements the MMC Host protocol, which is used by SD
> interface driver that the Sophgo SG2042 EVB supports. Add this driver
> in Sophgo/SG2042Pkg leveraging the one form Embedded Package.
> 
> 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/MmcDxe/MmcDxe.inf       |  46 ++
>  Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.h | 513 +++++++++++++
>  Silicon/Sophgo/SG2042Pkg/Include/MmcHost.h    | 225 ++++++
>  .../SG2042Pkg/Drivers/MmcDxe/ComponentName.c  | 156 ++++
>  .../SG2042Pkg/Drivers/MmcDxe/Diagnostics.c    | 323 ++++++++
>  Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.c | 527 +++++++++++++
>  .../SG2042Pkg/Drivers/MmcDxe/MmcBlockIo.c     | 643 ++++++++++++++++
>  .../SG2042Pkg/Drivers/MmcDxe/MmcDebug.c       | 194 +++++
>  .../Drivers/MmcDxe/MmcIdentification.c        | 719 ++++++++++++++++++
>  9 files changed, 3346 insertions(+)
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcDxe.inf
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.h
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Include/MmcHost.h
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/ComponentName.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Diagnostics.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcBlockIo.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcDebug.c
>  create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c
> 

> diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c b/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c
> new file mode 100644
> index 000000000000..855b45b794a7
> --- /dev/null
> +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c
> @@ -0,0 +1,719 @@
> +/** @file
> +  Define a simple and generic interface to access SD-card devices.
> +
> +  Copyright (c) 2018-2021, 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

Again, this is not the license this project is under.

/
    Leif

> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Include/MmcHost.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +#include "Mmc.h"
> +
> +#define MMC_DEFAULT_MAX_RETRIES   5
> +#define SEND_OP_COND_MAX_RETRIES  100
> +
> +#define MULT_BY_512K_SHIFT        19
> +
> +STATIC UINT32  MmcOCR;
> +STATIC CSD     MmcCsd;
> +STATIC UINT8   MmcExtCsd[512] __attribute__ ((aligned(16)));
> +STATIC UINT32  MmcRCA;
> +STATIC UINT32  MmcSCR[2] __attribute__ ((aligned(16))) = { 0 };
> +
> +typedef enum _MMC_DEVICE_TYPE {
> +  MMC_IS_EMMC,
> +  MMC_IS_SD,
> +  MMC_IS_SD_HC,
> +} MMC_DEVICE_TYPE;
> +
> +typedef struct {
> +  UINT64           DeviceSize;  /* Size of device in bytes */
> +  UINT32           BlockSize;   /* Block size in bytes */
> +  UINT32           MaxBusFreq;  /* Max bus freq in Hz */
> +  UINT32           OCRVoltage;  /* OCR voltage */
> +  MMC_DEVICE_TYPE  MmcDevType;  /* Type of MMC */
> +} MMC_DEVICE_INFO;
> +
> +STATIC MMC_DEVICE_INFO MmcDevInfo = {
> +  .MmcDevType = MMC_IS_SD_HC,
> +  .OCRVoltage = 0x00300000, // OCR 3.2~3.3 3.3~3.4
> +};
> +
> +STATIC CONST UINT8 TranSpeedBase[16] = {
> +  0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
> +};
> +
> +STATIC CONST UINT8 SdTranSpeedBase[16] = {
> +  0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
> +};
> +
> +/**
> +  Get the current state of the MMC device.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +  @param[out]    State                 Pointer to the variable to store the device state.
> +
> +  @retval EFI_SUCCESS                  The device state was retrieved successfully.
> +  @retval EFI_DEVICE_ERROR             Failed to retrieve the device state.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcDeviceState (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance,
> +  IN UINT32             *State
> +  )
> +{
> +  EFI_STATUS Status;
> +  INT32      RetryCount;
> +  UINT32     Response[4];
> +
> +  RetryCount = MMC_DEFAULT_MAX_RETRIES;
> +
> +  do {
> +    if (RetryCount == 0) {
> +      DEBUG ((DEBUG_ERROR, "%a: CMD13 failed after %d retries\n", __func__, MMC_DEFAULT_MAX_RETRIES));
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD13, MmcRCA << RCA_SHIFT_OFFSET,
> +               MMC_RESPONSE_R1, Response);
> +    if (EFI_ERROR (Status)) {
> +      RetryCount--;
> +      continue;
> +    }
> +
> +    if ((Response[0] & MMC_R0_SWITCH_ERROR) != 0U) {
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    RetryCount--;
> +  } while ((Response[0] & MMC_R0_READY_FOR_DATA) == 0U);
> +
> +  // DEBUG ((DEBUG_INFO, "%a: sd state %x\n", __func__, MMC_R0_CURRENTSTATE(Response)));
> +  *State = MMC_R0_CURRENTSTATE (Response);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set the value of the specified MMC extended CSD register.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +  @param[in]     ExtCmd                The extended CSD command.
> +  @param[in]     Value                 The value to set.
> +
> +  @retval EFI_SUCCESS                  The value was successfully set.
> +  @retval Other                        An error occurred while setting the value.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcSetExtCsd (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance,
> +  IN UINT32             ExtCmd,
> +  IN UINT32             Value
> +  )
> +{
> +  EFI_STATUS Status;
> +  UINT32     State;
> +
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD6,
> +             EXTCSD_WRITE_BYTES | EXTCSD_CMD(ExtCmd) |
> +             EXTCSD_VALUE(Value) | EXTCSD_CMD_SET_NORMAL,
> +             MMC_RESPONSE_R1B, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  do {
> +    Status = MmcDeviceState (MmcHostInstance, &State);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } while (State == MMC_R0_STATE_PROG);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Perform an SD switch to set the bus width for the MMC/SD device.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +  @param[in]     BusWidth              The desired bus width.
> +
> +  @retval EFI_SUCCESS                   The bus width was successfully set.
> +  @retval Other                         An error occurred while setting the bus width.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcSdSwitch (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance,
> +  IN UINT32             BusWidth
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      State;
> +  INT32       RetryCount;
> +  UINT32      BusWidthArg;
> +
> +  RetryCount  = MMC_DEFAULT_MAX_RETRIES;
> +  BusWidthArg = 0;
> +
> +  Status = MmcHostInstance->MmcHost->Prepare (MmcHostInstance->MmcHost, 0, sizeof(MmcSCR), (UINTN)&MmcSCR);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // CMD55: Application Specific Command
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, MmcRCA << RCA_SHIFT_OFFSET,
> +             MMC_RESPONSE_R5, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // ACMD51: SEND_SCR
> +  do {
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_ACMD51, 0, MMC_RESPONSE_R1, NULL);
> +    if ((EFI_ERROR (Status)) && (RetryCount == 0)) {
> +      DEBUG ((DEBUG_ERROR, "%a: ACMD51 failed after %d retries (Status=%r)\n", __func__, MMC_DEFAULT_MAX_RETRIES, Status));
> +      return Status;
> +    }
> +
> +    RetryCount--;
> +  } while (EFI_ERROR (Status));
> +
> +  Status = MmcHostInstance->MmcHost->ReadBlockData (MmcHostInstance->MmcHost, 0, sizeof(MmcSCR), MmcSCR);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (((MmcSCR[0] & SD_SCR_BUS_WIDTH_4) != 0U) && (BusWidth == MMC_BUS_WIDTH_4)) {
> +    BusWidthArg = 2;
> +  }
> +
> +  // CMD55: Application Specific Command
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, MmcRCA << RCA_SHIFT_OFFSET,
> +             MMC_RESPONSE_R5, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // ACMD6: SET_BUS_WIDTH
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD6, BusWidthArg, MMC_RESPONSE_R1, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  do {
> +    Status = MmcDeviceState (MmcHostInstance, &State);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } while (State == MMC_R0_STATE_PROG);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set the I/O settings for the MMC/SD device.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +  @param[in]     Clk                   The desired clock frequency.
> +  @param[in]     BusWidth              The desired bus width.
> +
> +  @retval EFI_SUCCESS                   The I/O settings were successfully set.
> +  @retval Other                         An error occurred while setting the I/O settings.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcSetIos (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance,
> +  IN UINT32             Clk,
> +  IN UINT32             BusWidth
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      Width;
> +
> +  Width = BusWidth;
> +
> +  if (MmcDevInfo.MmcDevType != MMC_IS_EMMC) {
> +    if (Width == MMC_BUS_WIDTH_8) {
> +      DEBUG ((DEBUG_INFO, "%a: Wrong bus config for SD-card, force to 4\n", __func__));
> +      Width = MMC_BUS_WIDTH_4;
> +    }
> +
> +    Status = MmcSdSwitch (MmcHostInstance, Width);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } else if (MmcCsd.SPEC_VERS == 4U) {
> +    Status = MmcSetExtCsd (MmcHostInstance, CMD_EXTCSD_BUS_WIDTH, (UINT32)Width);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } else {
> +    DEBUG ((DEBUG_INFO, "%a: Wrong MMC type or spec version\n", __func__));
> +  }
> +
> +  return MmcHostInstance->MmcHost->SetIos (MmcHostInstance->MmcHost, Clk, Width);
> +}
> +
> +/**
> +  Fill the MMC device information.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +
> +  @retval EFI_SUCCESS                   The MMC device information was successfully filled.
> +  @retval EFI_DEVICE_ERROR              Failed to fill the MMC device information.
> +  @retval Other                         An error occurred while filling the MMC device information.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcFillDeviceInfo (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINTN       CardSize;
> +  UINT32      SpeedIdx;
> +  UINT32      NumBlocks;
> +  UINT32      FreqUnit;
> +  UINT32      State;
> +  ECSD        *CsdSdV2;
> +
> +  Status = EFI_SUCCESS;
> +
> +  switch (MmcDevInfo.MmcDevType) {
> +    case MMC_IS_EMMC:
> +      MmcDevInfo.BlockSize = MMC_BLOCK_SIZE;
> +
> +      Status = MmcHostInstance->MmcHost->Prepare (MmcHostInstance->MmcHost, 0, sizeof(MmcExtCsd), (UINTN)&MmcExtCsd);
> +
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +
> +      /* MMC CMD8: SEND_EXT_CSD */
> +      Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD8, 0, MMC_RESPONSE_R1, NULL);
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +
> +      Status = MmcHostInstance->MmcHost->ReadBlockData (MmcHostInstance->MmcHost, 0, sizeof(MmcExtCsd), (UINT32*)MmcExtCsd);
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +
> +      do {
> +        Status = MmcDeviceState (MmcHostInstance, &State);
> +        if (EFI_ERROR (Status)) {
> +          return Status;
> +        }
> +      } while (State != MMC_R0_STATE_TRAN);
> +
> +      NumBlocks = (MmcExtCsd[CMD_EXTCSD_SEC_CNT] << 0) |
> +            (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
> +            (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
> +            (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 3] << 24);
> +
> +      MmcDevInfo.DeviceSize = (UINT64)NumBlocks * MmcDevInfo.BlockSize;
> +
> +      break;
> +
> +    case MMC_IS_SD:
> +      /*
> +      * Use the same MmcCsd struct, as required fields here
> +      * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC.
> +      */
> +      MmcDevInfo.BlockSize = BIT_32(MmcCsd.READ_BL_LEN);
> +
> +      CardSize = ((UINT64)MmcCsd.C_SIZEHigh10 << 2U) |
> +        (UINT64)MmcCsd.C_SIZELow2;
> +      ASSERT(CardSize != 0xFFFU);
> +
> +      MmcDevInfo.DeviceSize = (CardSize + 1U) *
> +                BIT_64(MmcCsd.C_SIZE_MULT + 2U) *
> +                MmcDevInfo.BlockSize;
> +
> +      break;
> +
> +    case MMC_IS_SD_HC:
> +        MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
> +
> +      ASSERT (MmcCsd.CSD_STRUCTURE == 1U);
> +
> +      MmcDevInfo.BlockSize = MMC_BLOCK_SIZE;
> +
> +      /* Need to use ECSD struct */
> +      CsdSdV2 = (ECSD *)&MmcCsd;
> +      CardSize = ((UINT64)CsdSdV2->C_SIZEHigh6 << 16) |
> +        (UINT64)CsdSdV2->C_SIZELow16;
> +
> +      MmcDevInfo.DeviceSize = (CardSize + 1U) << MULT_BY_512K_SHIFT;
> +      break;
> +
> +    default:
> +      Status = EFI_DEVICE_ERROR;
> +      break;
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  SpeedIdx = (MmcCsd.TRAN_SPEED & CSD_TRAN_SPEED_MULT_MASK) >>
> +        CSD_TRAN_SPEED_MULT_SHIFT;
> +
> +  ASSERT (SpeedIdx > 0U);
> +
> +  if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) {
> +    MmcDevInfo.MaxBusFreq = TranSpeedBase[SpeedIdx];
> +  } else {
> +    MmcDevInfo.MaxBusFreq = SdTranSpeedBase[SpeedIdx];
> +  }
> +
> +  FreqUnit = MmcCsd.TRAN_SPEED & CSD_TRAN_SPEED_UNIT_MASK;
> +  while (FreqUnit != 0U) {
> +    MmcDevInfo.MaxBusFreq *= 10U;
> +    --FreqUnit;
> +  }
> +
> +  MmcDevInfo.MaxBusFreq *= 10000U;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Send the SD_SEND_OP_COND command to initialize the SD card.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +
> +  @retval EFI_SUCCESS                   The SD_SEND_OP_COND command was successfully sent.
> +  @retval EFI_DEVICE_ERROR              Failed to send the SD_SEND_OP_COND command.
> +  @retval Other                         An error occurred while sending the SD_SEND_OP_COND command.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +SdSendOpCond (
> +  IN MMC_HOST_INSTANCE  *MmcHostInstance
> +  )
> +{
> +  EFI_STATUS Status;
> +  INT32      I;
> +  UINT32     Response[4];
> +
> +  for (I = 0; I < SEND_OP_COND_MAX_RETRIES; I++) {
> +    // CMD55: Application Specific Command
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, 0, MMC_RESPONSE_R1, NULL);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    // ACMD41: SD_SEND_OP_COND
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_ACMD41, OCR_HCS |
> +      MmcDevInfo.OCRVoltage, MMC_RESPONSE_R3, Response);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    if ((Response[0] & MMC_OCR_POWERUP) != 0U) {
> +      MmcOCR = Response[0];
> +
> +      if ((MmcOCR & OCR_HCS) != 0U) {
> +        MmcDevInfo.MmcDevType = MMC_IS_SD_HC;
> +        MmcHostInstance->CardInfo.OCRData.AccessMode = 0x2;
> +      } else {
> +        MmcDevInfo.MmcDevType = MMC_IS_SD;
> +        MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0;
> +      }
> +
> +      return EFI_SUCCESS;
> +    }
> +
> +    gBS->Stall (10000);
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "%a: ACMD41 failed after %d retries\n", __func__, SEND_OP_COND_MAX_RETRIES));
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Reset the MMC/SD card to the idle state.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +
> +  @retval EFI_SUCCESS                   The MMC/SD card was successfully reset to the idle state.
> +  @retval Other                         An error occurred while resetting the MMC/SD card to the idle state.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcResetToIdle(
> +  IN MMC_HOST_INSTANCE     *MmcHostInstance
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  /* CMD0: reset to IDLE */
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD0, 0, 0, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  gBS->Stall (2000);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Send the Operation Condition (CMD1) to the MMC/SD card.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +
> +  @retval EFI_SUCCESS                   The Operation Condition was successfully sent to the MMC/SD card.
> +  @retval EFI_DEVICE_ERROR              Failed to send the Operation Condition to the MMC/SD card.
> +  @retval Other                         An error occurred while sending the Operation Condition to the MMC/SD card.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcSendOpCond (
> +  IN MMC_HOST_INSTANCE     *MmcHostInstance
> +  )
> +{
> +  INT32       I;
> +  EFI_STATUS  Status;
> +  UINT32      Response[4];
> +
> +  Status = MmcResetToIdle (MmcHostInstance);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  for (I = 0; I < SEND_OP_COND_MAX_RETRIES; I++) {
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD1, OCR_SECTOR_MODE |
> +            OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
> +            MMC_RESPONSE_R3, Response);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    if ((Response[0] & MMC_OCR_POWERUP) != 0U) {
> +      MmcOCR = Response[0];
> +      return EFI_SUCCESS;
> +    }
> +
> +    gBS->Stall (10000);
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "%a: CMD1 failed after %d retries\n", __func__, SEND_OP_COND_MAX_RETRIES));
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Enumerate and initialize the MMC/SD card.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +  @param[in]     Clk                   Clock frequency for the MMC/SD card.
> +  @param[in]     BusWidth              Bus width for the MMC/SD card.
> +
> +  @retval EFI_SUCCESS                   The MMC/SD card was successfully enumerated and initialized.
> +  @retval Other                         An error occurred while enumerating and initializing the MMC/SD card.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MmcEnumerte (
> +  IN MMC_HOST_INSTANCE     *MmcHostInstance,
> +  IN UINT32                Clk,
> +  IN UINT32                BusWidth
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      State;
> +  UINT32      Response[4];
> +
> +  Status = MmcResetToIdle (MmcHostInstance);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) {
> +    Status = MmcSendOpCond (MmcHostInstance);
> +  } else {
> +    // CMD8: Send Interface Condition Command
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD8, VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,
> +            MMC_RESPONSE_R5, Response);
> +
> +    if ((Status == EFI_SUCCESS) && ((Response[0] & 0xffU) == CMD8_CHECK_PATTERN)) {
> +      Status = SdSendOpCond (MmcHostInstance);
> +    }
> +  }
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // CMD2: Card Identification
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD2, 0, MMC_RESPONSE_R2, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // CMD3: Set Relative Address
> +  if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) {
> +    MmcRCA = MMC_FIX_RCA;
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD3, MmcRCA << RCA_SHIFT_OFFSET,
> +            MMC_RESPONSE_R1, NULL);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } else {
> +    Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD3, 0,
> +            MMC_RESPONSE_R6, Response);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    MmcRCA = (Response[0] & 0xFFFF0000U) >> 16;
> +  }
> +
> +  // CMD9: CSD Register
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD9, MmcRCA << RCA_SHIFT_OFFSET,
> +          MMC_RESPONSE_R2, Response);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CopyMem(&MmcCsd, &Response, sizeof(Response));
> +
> +  // CMD7: Select Card
> +  Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD7, MmcRCA << RCA_SHIFT_OFFSET,
> +          MMC_RESPONSE_R1, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  do {
> +    Status = MmcDeviceState (MmcHostInstance, &State);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } while (State != MMC_R0_STATE_TRAN);
> +
> +  Status = MmcSetIos (MmcHostInstance, Clk, BusWidth);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return MmcFillDeviceInfo (MmcHostInstance);
> +}
> +
> +/**
> +  Perform the MMC Identification Mode.
> +
> +  @param[in]     MmcHostInstance       Pointer to the MMC_HOST_INSTANCE structure.
> +
> +  @retval EFI_SUCCESS                   The MMC Identification Mode was performed successfully.
> +  @retval EFI_INVALID_PARAMETER         MmcHost is NULL.
> +  @retval Other                         An error occurred while performing the MMC Identification Mode.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MmcIdentificationMode (
> +  IN MMC_HOST_INSTANCE     *MmcHostInstance
> +  )
> +{
> +  EFI_STATUS              Status;
> +  UINTN                   CmdArg;
> +  BOOLEAN                 IsHCS;
> +  EFI_MMC_HOST_PROTOCOL   *MmcHost;
> +
> +  MmcHost = MmcHostInstance->MmcHost;
> +  CmdArg  = 0;
> +  IsHCS   = FALSE;
> +
> +  if (MmcHost == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // We can get into this function if we restart the identification mode
> +  if (MmcHostInstance->State == MmcHwInitializationState) {
> +    // Initialize the MMC Host HW
> +    Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status));
> +      return Status;
> +    }
> +  }
> +
> +  Status = MmcEnumerte (MmcHostInstance, 50 * 1000 * 1000, MMC_BUS_WIDTH_4);
> +
> +  if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcEnumerte, Status=%r.\n", Status));
> +      return Status;
> +  }
> +
> +  MmcHostInstance->CardInfo.RCA                = MmcRCA;
> +  MmcHostInstance->BlockIo.Media->LastBlock    = ((MmcDevInfo.DeviceSize >> 9) - 1);
> +  MmcHostInstance->BlockIo.Media->BlockSize    = MmcDevInfo.BlockSize;
> +  MmcHostInstance->BlockIo.Media->ReadOnly     = MmcHost->IsReadOnly (MmcHost);
> +  MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
> +  MmcHostInstance->BlockIo.Media->MediaId++;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Initialize the MMC device.
> +
> +  @param[in] MmcHostInstance   MMC host instance
> +
> +  @retval EFI_SUCCESS          MMC device initialized successfully
> +  @retval Other                MMC device initialization failed
> +
> +**/
> +EFI_STATUS
> +InitializeMmcDevice (
> +  IN  MMC_HOST_INSTANCE   *MmcHostInstance
> +  )
> +{
> +  EFI_STATUS              Status;
> +  EFI_MMC_HOST_PROTOCOL   *MmcHost;
> +  UINTN                   BlockCount;
> +
> +  BlockCount = 1;
> +  MmcHost    = MmcHostInstance->MmcHost;
> +
> +  Status = MmcIdentificationMode (MmcHostInstance);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status));
> +    return Status;
> +  }
> +
> +  Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.34.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108730): https://edk2.groups.io/g/devel/message/108730
Mute This Topic: https://groups.io/mt/101213495/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2023-09-15 14:25 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-07 10:25 [edk2-devel] [PATCH v3 0/8] EDK2 on RISC-V Sophgo SG2042 platform caiyuqing_hz
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 1/8] Sophgo/SG2042Pkg: Add SmbiosPlatformDxe module caiyuqing_hz
2023-09-15 10:36   ` Sunil V L
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 2/8] Sophgo/SG2042Pkg: Add PlatformUpdateMmuDxe module caiyuqing_hz
2023-09-15 10:41   ` Sunil V L
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 3/8] Sophgo/SG2042Pkg: Add Sophgo SDHCI driver caiyuqing_hz
2023-09-15 10:47   ` Sunil V L
2023-09-15 14:23   ` Leif Lindholm
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 4/8] Sophgo/SG2042Pkg: Add base MMC driver caiyuqing_hz
2023-09-15 10:53   ` Sunil V L
2023-09-15 14:25   ` Leif Lindholm [this message]
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 5/8] Sophgo/SG2042Pkg: Add SEC module caiyuqing_hz
2023-09-15 10:57   ` Sunil V L
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 6/8] Sophgo/SG2042_EVB_Board: Add Sophgo SG2042 platform caiyuqing_hz
2023-09-15 11:03   ` Sunil V L
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 7/8] Sophgo/SG2042Pkg: Add SG2042Pkg caiyuqing_hz
2023-09-07 10:25 ` [edk2-devel] [PATCH v3 8/8] Sophgo/SG2042Pkg: Add platform readme and document caiyuqing_hz
2023-09-15 10:35 ` [edk2-devel] [PATCH v3 0/8] EDK2 on RISC-V Sophgo SG2042 platform Sunil V L

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZQRpVhXyrvb5MDqo@qc-i7.hemma.eciton.net \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox