public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Haojian Zhuang <haojian.zhuang@linaro.org>
Cc: Ryan Harkin <ryan.harkin@linaro.org>,
	edk2-devel-01 <edk2-devel@lists.01.org>,
	 Leif Lindholm <leif.lindholm@linaro.org>
Subject: Re: [PATCH v7 2/4] MmcDxe: set iospeed and bus width in SD stack
Date: Wed, 23 Nov 2016 08:58:45 +0000	[thread overview]
Message-ID: <CAKv+Gu80_Zo9+jq096n0sAA1cxTyBPViFR1EtMf4f2CkPSMr3w@mail.gmail.com> (raw)
In-Reply-To: <1479884921-25398-3-git-send-email-haojian.zhuang@linaro.org>

On 23 November 2016 at 07:08, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> Add more SD commands to support 4-bit bus width & iospeed.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
> ---
>  EmbeddedPkg/Include/Protocol/MmcHost.h           |   3 +
>  EmbeddedPkg/Universal/MmcDxe/Mmc.h               |  16 ++++
>  EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 106 +++++++++++++++++++++++
>  3 files changed, 125 insertions(+)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 9d7a604..445e53f 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -64,11 +64,14 @@ typedef UINT32 MMC_CMD;
>  #define MMC_CMD24             (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD55             (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_ACMD41            (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
> +#define MMC_ACMD51            (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
>
>  // Valid responses for CMD1 in eMMC
>  #define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used
>  #define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used
>
> +#define MMC_STATUS_APP_CMD    (1 << 5)
> +
>  typedef enum _MMC_STATE {
>      MmcInvalidState = 0,
>      MmcHwInitializationState,
> diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> index fb3f6c9..6bc85e0 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> +++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> @@ -80,6 +80,22 @@ typedef struct {
>    UINT32  PowerUp:     1; // This bit is set to LOW if the card has not finished the power up routine
>  } OCR;
>
> +typedef struct {
> +  UINT8   SD_SPEC:               4; // SD Memory Card - Spec. Version [59:56]
> +  UINT8   SCR_STRUCTURE:         4; // SCR Structure [63:60]
> +  UINT8   SD_BUS_WIDTHS:         4; // DAT Bus widths supported [51:48]
> +  UINT8   DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]
> +  UINT8   SD_SECURITY:           3; // CPRM Security Support [54:52]
> +  UINT8   EX_SECURITY_1:         1; // Extended Security Support [43]
> +  UINT8   SD_SPEC4:              1; // Spec. Version 4.00 or higher [42]
> +  UINT8   RESERVED_1:            2; // Reserved [41:40]
> +  UINT8   SD_SPEC3:              1; // Spec. Version 3.00 or higher [47]
> +  UINT8   EX_SECURITY_2:         3; // Extended Security Support [46:44]
> +  UINT8   CMD_SUPPORT:           4; // Command Support bits [35:32]
> +  UINT8   RESERVED_2:            4; // Reserved [39:36]
> +  UINT32  RESERVED_3;               // Manufacturer Usage [31:0]
> +} SCR;
> +
>  typedef struct {
>    UINT32  NOT_USED;   // 1 [0:0]
>    UINT32  CRC;        // CRC7 checksum [7:1]
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> index 7441459..c47a92b 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> @@ -12,6 +12,9 @@
>  *
>  **/
>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/TimerLib.h>
> +
>  #include "Mmc.h"
>
>  typedef union {
> @@ -41,6 +44,11 @@ typedef union {
>
>  #define EMMC_SWITCH_ERROR       (1 << 7)
>
> +#define SD_BUS_WIDTH_1BIT       (1 << 0)
> +#define SD_BUS_WIDTH_4BIT       (1 << 2)
> +
> +#define SD_CCC_SWITCH           (1 << 10)
> +
>  #define DEVICE_STATE(x)         (((x) >> 9) & 0xf)
>  typedef enum _EMMC_DEVICE_STATE {
>    EMMC_IDLE_STATE = 0,
> @@ -296,9 +304,12 @@ InitializeSdMmcDevice (
>  {
>    UINT32        CmdArg;
>    UINT32        Response[4];
> +  UINT32        Buffer[128];
>    UINTN         BlockSize;
>    UINTN         CardSize;
>    UINTN         NumBlocks;
> +  BOOLEAN       CccSwitch;
> +  SCR           Scr;
>    EFI_STATUS    Status;
>    EFI_MMC_HOST_PROTOCOL     *MmcHost;
>
> @@ -319,6 +330,11 @@ InitializeSdMmcDevice (
>      return Status;
>    }
>    PrintCSD (Response);
> +  if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) {
> +    CccSwitch = TRUE;
> +  } else {
> +    CccSwitch = FALSE;
> +  }
>
>    if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
>      CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
> @@ -349,6 +365,96 @@ InitializeSdMmcDevice (
>      return Status;
>    }
>
> +  Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> +    return Status;
> +  }
> +  Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> +    return Status;
> +  }
> +  if ((Response[0] & MMC_STATUS_APP_CMD) == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  /* SCR */
> +  Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
> +    return Status;
> +  } else {
> +    Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
> +      return Status;
> +    }
> +    CopyMem (&Scr, Buffer, 8);
> +    if (Scr.SD_SPEC == 2) {
> +      if (Scr.SD_SPEC3 == 1) {
> +       if (Scr.SD_SPEC4 == 1) {
> +          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
> +       } else {
> +          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
> +       }
> +      } else {
> +       if (Scr.SD_SPEC4 == 0) {
> +          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
> +       } else {
> +         DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
> +       }
> +      }
> +    } else {
> +      if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
> +        if (Scr.SD_SPEC == 1) {
> +         DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
> +       } else {
> +         DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
> +       }
> +      } else {
> +        DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
> +      }
> +    }
> +  }
> +  if (CccSwitch) {
> +    /* SD Switch, Mode:1, Group:0, Value:1 */
> +    CmdArg = 1 << 31 | 0x00FFFFFF;
> +    CmdArg &= ~(0xF << (0 * 4));
> +    CmdArg |= 1 << (0 * 4);
> +    Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
> +       return Status;
> +    } else {
> +      Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));
> +        return Status;
> +      }
> +    }
> +  }
> +  if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
> +    CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> +    Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> +      return Status;
> +    }
> +    /* Width: 4 */
> +    Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
> +      return Status;
> +    }
> +  }
> +  if (MMC_HOST_HAS_SETIOS(MmcHost)) {
> +    Status = MmcHost->SetIos (MmcHost, 24 * 1000 * 1000, 4, EMMCBACKWARD);

Could you explain where the constant comes from?

> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
> +      return Status;
> +    }
> +  }
>    return EFI_SUCCESS;
>  }
>
> --
> 2.7.4
>


  reply	other threads:[~2016-11-23  8:58 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-23  7:08 [PATCH v7 0/4] enhance MMC Haojian Zhuang
2016-11-23  7:08 ` [PATCH v7 1/4] MmcDxe: add interface to change io width and speed Haojian Zhuang
2016-11-23  8:56   ` Ard Biesheuvel
2016-11-23  7:08 ` [PATCH v7 2/4] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
2016-11-23  8:58   ` Ard Biesheuvel [this message]
2016-11-23  7:08 ` [PATCH v7 3/4] PL180: update for indentifying SD Haojian Zhuang
2016-11-23  8:59   ` Ard Biesheuvel
2016-11-23  7:08 ` [PATCH v7 4/4] MmcDxe: expand to support multiple blocks Haojian Zhuang
2016-11-23  9:01   ` Ard Biesheuvel
2016-11-23  8:54 ` [PATCH v7 0/4] enhance MMC Ard Biesheuvel

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=CAKv+Gu80_Zo9+jq096n0sAA1cxTyBPViFR1EtMf4f2CkPSMr3w@mail.gmail.com \
    --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