On 23 November 2016 at 07:08, Haojian Zhuang <[email protected]> wrote:
> Add more SD commands to support 4-bit bus width & iospeed.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <[email protected]>
> Tested-by: Ryan Harkin <[email protected]>
> ---
> 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
>
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel