diff mbox

[edk2,v7,2/4] MmcDxe: set iospeed and bus width in SD stack

Message ID 1479884921-25398-3-git-send-email-haojian.zhuang@linaro.org
State Superseded
Headers show

Commit Message

Haojian Zhuang Nov. 23, 2016, 7:08 a.m. UTC
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(+)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Ard Biesheuvel Nov. 23, 2016, 8:58 a.m. UTC | #1
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

>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox

Patch

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);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
+      return Status;
+    }
+  }
   return EFI_SUCCESS;
 }