From: Haojian Zhuang <haojian.zhuang@linaro.org>
To: ryan.harkin@linaro.org, edk2-devel@lists.01.org,
leif.lindholm@linaro.org, ard.biesheuvel@linaro.org
Cc: Haojian Zhuang <haojian.zhuang@linaro.org>
Subject: [PATCH v8 2/4] MmcDxe: set iospeed and bus width in SD stack
Date: Wed, 23 Nov 2016 21:36:22 +0800 [thread overview]
Message-ID: <1479908184-9406-3-git-send-email-haojian.zhuang@linaro.org> (raw)
In-Reply-To: <1479908184-9406-1-git-send-email-haojian.zhuang@linaro.org>
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 4f0a7b4..6297d0a 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..4c0fd8e 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, 26 * 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;
}
--
2.7.4
next prev parent reply other threads:[~2016-11-23 13:36 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-23 13:36 [PATCH v8 0/4] enhance MMC Haojian Zhuang
2016-11-23 13:36 ` [PATCH v8 1/4] MmcDxe: add interface in mmc host protocol Haojian Zhuang
2016-11-23 13:36 ` Haojian Zhuang [this message]
2016-11-23 13:36 ` [PATCH v8 3/4] PL180: update for indentifying SD Haojian Zhuang
2016-11-23 13:36 ` [PATCH v8 4/4] MmcDxe: expand to support multiple blocks Haojian Zhuang
2016-11-24 16:31 ` [PATCH v8 0/4] enhance MMC Ard Biesheuvel
2016-11-24 18:47 ` Ryan Harkin
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=1479908184-9406-3-git-send-email-haojian.zhuang@linaro.org \
--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