public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v7 0/4] enhance MMC
@ 2016-11-23  7:08 Haojian Zhuang
  2016-11-23  7:08 ` [PATCH v7 1/4] MmcDxe: add interface to change io width and speed Haojian Zhuang
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Haojian Zhuang @ 2016-11-23  7:08 UTC (permalink / raw)
  To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang

v7:
  * Add revision checking.

v6:
  * Reformat the last 5 patches after 4 MMC patches of this series merged.
  * Squash original #5 and #6 patches together.
  * Fix according comments.

v5:
  * Remove patch on MediaId.
  * Squash two PL180 patches together.

v4:
  * Fix PL180 hang in some cases. Since the proper variable length
    isn't set for CMD6 & ACMD51.

v3:
  * Fix PL180 hang because of CMD6 & ACMD51 not supported.

v2:
  * Fix print error with missing parameter.
  * Change CMD51 to ACMD51.
  * Add the protection after CMD55 for SD. If there's no
    response of CMD55, skip to send ACMD51.

v1:
  * Wait OCR busy bit free according to eMMC spec.
  * Define ECSD structure.
  * Add interface to set IO bus width and speed.
  * Support to access multiple blocks.

Haojian Zhuang (4):
  MmcDxe: add interface to change io width and speed
  MmcDxe: set iospeed and bus width in SD stack
  PL180: update for indentifying SD
  MmcDxe: expand to support multiple blocks

 ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c    |  29 ++-
 EmbeddedPkg/Include/Protocol/MmcHost.h           |  36 ++-
 EmbeddedPkg/Universal/MmcDxe/Mmc.h               |  25 ++
 EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c        | 176 +++++++++-----
 EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 291 ++++++++++++++++++++++-
 5 files changed, 487 insertions(+), 70 deletions(-)

-- 
2.7.4



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v7 1/4] MmcDxe: add interface to change io width and speed
  2016-11-23  7:08 [PATCH v7 0/4] enhance MMC Haojian Zhuang
@ 2016-11-23  7:08 ` 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
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Haojian Zhuang @ 2016-11-23  7:08 UTC (permalink / raw)
  To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang

By default, MMC is initialized with 1-bit mode and less than 400KHz bus
clock. It causes MMC working inefficiently.

Add the interface to change the bus width and speed.

Set io bus width on both MMC controller and EXTCSD. Otherwise, it may
cause unmatched failure case. And support more timing mode, high speed,
HS200 & HS400 mode.

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           |  25 ++-
 EmbeddedPkg/Universal/MmcDxe/Mmc.h               |   5 +
 EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 185 ++++++++++++++++++++++-
 3 files changed, 211 insertions(+), 4 deletions(-)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 89f2e80..9d7a604 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -49,6 +49,7 @@ typedef UINT32 MMC_CMD;
 #define MMC_CMD2              (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
 #define MMC_CMD3              (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD5              (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
+#define MMC_CMD6              (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD7              (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD8              (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD9              (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
@@ -82,6 +83,16 @@ typedef enum _MMC_STATE {
     MmcDisconnectState,
 } MMC_STATE;
 
+#define EMMCBACKWARD         (0)
+#define EMMCHS26             (1 << 0)      // High-Speed @26MHz at rated device voltages
+#define EMMCHS52             (1 << 1)      // High-Speed @52MHz at rated device voltages
+#define EMMCHS52DDR1V8       (1 << 2)      // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O
+#define EMMCHS52DDR1V2       (1 << 3)      // High-Speed Dual Data Rate @52MHz 1.2V I/O
+#define EMMCHS200SDR1V8      (1 << 4)      // HS200 Single Data Rate @200MHz 1.8V I/O
+#define EMMCHS200SDR1V2      (1 << 5)      // HS200 Single Data Rate @200MHz 1.2V I/O
+#define EMMCHS400DDR1V8      (1 << 6)      // HS400 Dual Data Rate @400MHz 1.8V I/O
+#define EMMCHS400DDR1V2      (1 << 7)      // HS400 Dual Data Rate @400MHz 1.2V I/O
+
 ///
 /// Forward declaration for EFI_MMC_HOST_PROTOCOL
 ///
@@ -131,6 +142,13 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
   IN  UINT32                    *Buffer
   );
 
+typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
+  IN  EFI_MMC_HOST_PROTOCOL     *This,
+  IN  UINT32                    BusClockFreq,
+  IN  UINT32                    BusWidth,
+  IN  UINT32                    TimingMode
+  );
+
 
 struct _EFI_MMC_HOST_PROTOCOL {
 
@@ -147,9 +165,14 @@ struct _EFI_MMC_HOST_PROTOCOL {
   MMC_READBLOCKDATA       ReadBlockData;
   MMC_WRITEBLOCKDATA      WriteBlockData;
 
+  MMC_SETIOS              SetIos;
+
 };
 
-#define MMC_HOST_PROTOCOL_REVISION    0x00010001    // 1.1
+#define MMC_HOST_PROTOCOL_REVISION    0x00010002    // 1.2
+
+#define MMC_HOST_HAS_SETIOS(Host)     (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
+                                       Host->SetIos != NULL)
 
 extern EFI_GUID gEfiMmcHostProtocolGuid;
 
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 112bc47..fb3f6c9 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -55,6 +55,11 @@
 #define MMC_R0_STATE_TRAN       4
 #define MMC_R0_STATE_DATA       5
 
+#define EMMC_CMD6_ARG_ACCESS(x)             (((x) & 0x3) << 24)
+#define EMMC_CMD6_ARG_INDEX(x)              (((x) & 0xFF) << 16)
+#define EMMC_CMD6_ARG_VALUE(x)              (((x) & 0xFF) << 8)
+#define EMMC_CMD6_ARG_CMD_SET(x)            (((x) & 0x7) << 0)
+
 typedef enum {
   UNKNOWN_CARD,
   MMC_CARD,              //MMC card
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 9aefb26..7441459 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -25,11 +25,111 @@ typedef union {
 #define EMMC_CARD_SIZE          512
 #define EMMC_ECSD_SIZE_OFFSET   53
 
+#define EXTCSD_BUS_WIDTH        183
+#define EXTCSD_HS_TIMING        185
+
+#define EMMC_TIMING_BACKWARD    0
+#define EMMC_TIMING_HS          1
+#define EMMC_TIMING_HS200       2
+#define EMMC_TIMING_HS400       3
+
+#define EMMC_BUS_WIDTH_1BIT     0
+#define EMMC_BUS_WIDTH_4BIT     1
+#define EMMC_BUS_WIDTH_8BIT     2
+#define EMMC_BUS_WIDTH_DDR_4BIT 5
+#define EMMC_BUS_WIDTH_DDR_8BIT 6
+
+#define EMMC_SWITCH_ERROR       (1 << 7)
+
+#define DEVICE_STATE(x)         (((x) >> 9) & 0xf)
+typedef enum _EMMC_DEVICE_STATE {
+  EMMC_IDLE_STATE = 0,
+  EMMC_READY_STATE,
+  EMMC_IDENT_STATE,
+  EMMC_STBY_STATE,
+  EMMC_TRAN_STATE,
+  EMMC_DATA_STATE,
+  EMMC_RCV_STATE,
+  EMMC_PRG_STATE,
+  EMMC_DIS_STATE,
+  EMMC_BTST_STATE,
+  EMMC_SLP_STATE
+} EMMC_DEVICE_STATE;
+
 UINT32 mEmmcRcaCount = 0;
 
 STATIC
 EFI_STATUS
 EFIAPI
+EmmcGetDeviceState (
+  IN  MMC_HOST_INSTANCE    *MmcHostInstance,
+  OUT EMMC_DEVICE_STATE    *State
+  )
+{
+  EFI_MMC_HOST_PROTOCOL *Host;
+  EFI_STATUS Status;
+  UINT32     Data, RCA;
+
+  if (State == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Host = MmcHostInstance->MmcHost;
+  RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
+  Status = Host->SendCommand (Host, MMC_CMD13, RCA);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
+    return Status;
+  }
+  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
+    return Status;
+  }
+  if (Data & EMMC_SWITCH_ERROR) {
+    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
+    return EFI_DEVICE_ERROR;
+  }
+  *State = DEVICE_STATE(Data);
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+EmmcSetEXTCSD (
+  IN MMC_HOST_INSTANCE     *MmcHostInstance,
+  UINT32                   ExtCmdIndex,
+  UINT32                   Value
+  )
+{
+  EFI_MMC_HOST_PROTOCOL *Host;
+  EMMC_DEVICE_STATE     State;
+  EFI_STATUS Status;
+  UINT32     Argument;
+
+  Host  = MmcHostInstance->MmcHost;
+  Argument = EMMC_CMD6_ARG_ACCESS(3) | EMMC_CMD6_ARG_INDEX(ExtCmdIndex) |
+             EMMC_CMD6_ARG_VALUE(Value) | EMMC_CMD6_ARG_CMD_SET(1);
+  Status = Host->SendCommand (Host, MMC_CMD6, Argument);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
+    return Status;
+  }
+  // Make sure device exiting prog mode
+  do {
+    Status = EmmcGetDeviceState (MmcHostInstance, &State);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
+      return Status;
+    }
+  } while (State == EMMC_PRG_STATE);
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
 EmmcIdentificationMode (
   IN MMC_HOST_INSTANCE     *MmcHostInstance,
   IN OCR_RESPONSE           Response
@@ -38,6 +138,7 @@ EmmcIdentificationMode (
   EFI_MMC_HOST_PROTOCOL *Host;
   EFI_BLOCK_IO_MEDIA    *Media;
   EFI_STATUS Status;
+  EMMC_DEVICE_STATE     State;
   UINT32     RCA;
 
   Host  = MmcHostInstance->MmcHost;
@@ -84,6 +185,22 @@ EmmcIdentificationMode (
     DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
   }
 
+  if (MMC_HOST_HAS_SETIOS(Host)) {
+    // Set 1-bit bus width
+    Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
+      return Status;
+    }
+
+    // Set 1-bit bus width for EXTCSD
+    Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
+      return Status;
+    }
+  }
+
   // Fetch ECSD
   Status = Host->SendCommand (Host, MMC_CMD8, RCA);
   if (EFI_ERROR (Status)) {
@@ -96,6 +213,15 @@ EmmcIdentificationMode (
     return Status;
   }
 
+  // Make sure device exiting data mode
+  do {
+    Status = EmmcGetDeviceState (MmcHostInstance, &State);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
+      return Status;
+    }
+  } while (State == EMMC_DATA_STATE);
+
   // Set up media
   Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
   Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
@@ -113,6 +239,57 @@ EmmcIdentificationMode (
 
 STATIC
 EFI_STATUS
+InitializeEmmcDevice (
+  IN  MMC_HOST_INSTANCE   *MmcHostInstance
+  )
+{
+  EFI_MMC_HOST_PROTOCOL *Host;
+  EFI_STATUS Status = EFI_SUCCESS;
+  ECSD       *ECSDData;
+  UINT32     BusClockFreq, Idx;
+  UINT32     TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
+
+  Host  = MmcHostInstance->MmcHost;
+  ECSDData = &MmcHostInstance->CardInfo.ECSDData;
+  if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
+    return EFI_SUCCESS;
+
+  if (!MMC_HOST_HAS_SETIOS(Host)) {
+    return EFI_SUCCESS;
+  }
+  Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
+    return Status;
+  }
+
+  for (Idx = 0; Idx < 4; Idx++) {
+    switch (TimingMode[Idx]) {
+    case EMMCHS52DDR1V2:
+    case EMMCHS52DDR1V8:
+    case EMMCHS52:
+      BusClockFreq = 52000000;
+      break;
+    case EMMCHS26:
+      BusClockFreq = 26000000;
+      break;
+    default:
+      return EFI_UNSUPPORTED;
+    }
+    Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
+    if (!EFI_ERROR (Status)) {
+      Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_DDR_8BIT);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
+      }
+      return Status;
+    }
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
 InitializeSdMmcDevice (
   IN  MMC_HOST_INSTANCE   *MmcHostInstance
   )
@@ -431,9 +608,11 @@ InitializeMmcDevice (
 
   if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
     Status = InitializeSdMmcDevice (MmcHostInstance);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
+  } else {
+    Status = InitializeEmmcDevice (MmcHostInstance);
+  }
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
   // Set Block Length
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v7 2/4] MmcDxe: set iospeed and bus width in SD stack
  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  7:08 ` Haojian Zhuang
  2016-11-23  8:58   ` Ard Biesheuvel
  2016-11-23  7:08 ` [PATCH v7 3/4] PL180: update for indentifying SD Haojian Zhuang
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Haojian Zhuang @ 2016-11-23  7:08 UTC (permalink / raw)
  To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang

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



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v7 3/4] PL180: update for indentifying SD
  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  7:08 ` [PATCH v7 2/4] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
@ 2016-11-23  7:08 ` 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  8:54 ` [PATCH v7 0/4] enhance MMC Ard Biesheuvel
  4 siblings, 1 reply; 10+ messages in thread
From: Haojian Zhuang @ 2016-11-23  7:08 UTC (permalink / raw)
  To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang

When CMD6 & ACMD51 are added into indentifying SD process, PL180
should also support CMD6 & ACMD51. Otherwise, it'll hang when
system tries to read expected data.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
 ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 ++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
index 5526aac..b2ba4c0 100644
--- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -63,11 +63,6 @@ MciIsReadOnly (
   return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
 }
 
-#if 0
-//Note: This function has been commented out because it is not used yet.
-//      This function could be used to remove the hardcoded BlockLen used
-//      in MciPrepareDataPath
-
 // Convert block size to 2^n
 STATIC
 UINT32
@@ -87,7 +82,6 @@ GetPow2BlockLen (
 
   return Pow2BlockLen;
 }
-#endif
 
 VOID
 MciPrepareDataPath (
@@ -126,6 +120,23 @@ MciSendCommand (
     MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
   } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
     MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
+  } else if (MmcCmd == MMC_CMD6) {
+    MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+    MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
+#ifndef USE_STREAM
+    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
+#else
+    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
+  } else if (MmcCmd == MMC_ACMD51) {
+    MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+    /* SCR register is 8 bytes long. */
+    MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
+#ifndef USE_STREAM
+    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
+#else
+    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
   }
 
   // Create Command for PL180
@@ -223,7 +234,11 @@ MciReadBlockData (
 
   // Read data from the RX FIFO
   Loop   = 0;
-  Finish = MMCI0_BLOCKLEN / 4;
+  if (Length < MMCI0_BLOCKLEN) {
+    Finish = Length / 4;
+  } else {
+    Finish = MMCI0_BLOCKLEN / 4;
+  }
 
   // Raise the TPL at the highest level to disable Interrupts.
   Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v7 4/4] MmcDxe: expand to support multiple blocks
  2016-11-23  7:08 [PATCH v7 0/4] enhance MMC Haojian Zhuang
                   ` (2 preceding siblings ...)
  2016-11-23  7:08 ` [PATCH v7 3/4] PL180: update for indentifying SD Haojian Zhuang
@ 2016-11-23  7:08 ` Haojian Zhuang
  2016-11-23  9:01   ` Ard Biesheuvel
  2016-11-23  8:54 ` [PATCH v7 0/4] enhance MMC Ard Biesheuvel
  4 siblings, 1 reply; 10+ messages in thread
From: Haojian Zhuang @ 2016-11-23  7:08 UTC (permalink / raw)
  To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang

Make use of DMA to transfer multiple blocks at one time. It could
improve the performance on MMC/SD driver.

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    |  10 +-
 EmbeddedPkg/Universal/MmcDxe/Mmc.h        |   4 +
 EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 176 ++++++++++++++++++++----------
 3 files changed, 130 insertions(+), 60 deletions(-)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 445e53f..8c8c8a7 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -62,6 +62,7 @@ typedef UINT32 MMC_CMD;
 #define MMC_CMD20             (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD23             (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
 #define MMC_CMD24             (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD25             (MMC_INDX(25) | 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)
@@ -152,6 +153,10 @@ typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
   IN  UINT32                    TimingMode
   );
 
+typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) (
+  IN  EFI_MMC_HOST_PROTOCOL     *This
+  );
+
 
 struct _EFI_MMC_HOST_PROTOCOL {
 
@@ -169,13 +174,16 @@ struct _EFI_MMC_HOST_PROTOCOL {
   MMC_WRITEBLOCKDATA      WriteBlockData;
 
   MMC_SETIOS              SetIos;
+  MMC_ISMULTIBLOCK        IsMultiBlock;
 
 };
 
-#define MMC_HOST_PROTOCOL_REVISION    0x00010002    // 1.2
+#define MMC_HOST_PROTOCOL_REVISION    0x00010003    // 1.3
 
 #define MMC_HOST_HAS_SETIOS(Host)     (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
                                        Host->SetIos != NULL)
+#define MMC_HOST_HAS_ISMULTIBLOCK(Host) (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
+                                         Host->IsMultiBlock != NULL)
 
 extern EFI_GUID gEfiMmcHostProtocolGuid;
 
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 6bc85e0..8e7a80a 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -34,6 +34,10 @@
 
 #define MMC_OCR_POWERUP             0x80000000
 
+#define MMC_OCR_ACCESS_MASK         0x3     /* bit[30-29] */
+#define MMC_OCR_ACCESS_BYTE         0x1     /* bit[29] */
+#define MMC_OCR_ACCESS_SECTOR       0x2     /* bit[30] */
+
 #define MMC_CSD_GET_CCC(Response)    (Response[2] >> 20)
 #define MMC_CSD_GET_TRANSPEED(Response)    (Response[3] & 0xFF)
 #define MMC_CSD_GET_READBLLEN(Response)    ((Response[2] >> 16) & 0xF)
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
index 0e1ef57..35570fd 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
@@ -126,6 +126,96 @@ MmcStopTransmission (
 #define MMCI0_BLOCKLEN 512
 #define MMCI0_TIMEOUT  10000
 
+STATIC
+EFI_STATUS
+MmcTransferBlock (
+  IN EFI_BLOCK_IO_PROTOCOL    *This,
+  IN UINTN                    Cmd,
+  IN UINTN                    Transfer,
+  IN UINT32                   MediaId,
+  IN EFI_LBA                  Lba,
+  IN UINTN                    BufferSize,
+  OUT VOID                    *Buffer
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   CmdArg;
+  INTN                    Timeout;
+  UINT32                  Response[4];
+  MMC_HOST_INSTANCE       *MmcHostInstance;
+  EFI_MMC_HOST_PROTOCOL   *MmcHost;
+
+  MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
+  MmcHost = MmcHostInstance->MmcHost;
+
+  //Set command argument based on the card access mode (Byte mode or Block mode)
+  if ((MmcHostInstance->CardInfo.OCRData.AccessMode & MMC_OCR_ACCESS_MASK) ==
+      MMC_OCR_ACCESS_SECTOR) {
+    CmdArg = Lba;
+  } else {
+    CmdArg = Lba * This->Media->BlockSize;
+  }
+
+  Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
+    return Status;
+  }
+
+  if (Transfer == MMC_IOBLOCKS_READ) {
+    // Read Data
+    Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
+      MmcStopTransmission (MmcHost);
+      return Status;
+    }
+    Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
+      return Status;
+    }
+  } else {
+    // Write Data
+    Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
+      MmcStopTransmission (MmcHost);
+      return Status;
+    }
+  }
+
+  // Command 13 - Read status and wait for programming to complete (return to tran)
+  Timeout = MMCI0_TIMEOUT;
+  CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+  Response[0] = 0;
+  while(!(Response[0] & MMC_R0_READY_FOR_DATA)
+        && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
+        && Timeout--) {
+    Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
+    if (!EFI_ERROR (Status)) {
+      MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
+      if (Response[0] & MMC_R0_READY_FOR_DATA) {
+        break;  // Prevents delay once finished
+      }
+    }
+  }
+
+  if (BufferSize > This->Media->BlockSize) {
+    Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
+    }
+  }
+
+  Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
+    return Status;
+  }
+  return Status;
+}
+
 EFI_STATUS
 MmcIoBlocks (
   IN EFI_BLOCK_IO_PROTOCOL    *This,
@@ -145,6 +235,7 @@ MmcIoBlocks (
   EFI_MMC_HOST_PROTOCOL   *MmcHost;
   UINTN                   BytesRemainingToBeTransfered;
   UINTN                   BlockCount;
+  UINTN                   ConsumeSize;
 
   BlockCount = 1;
   MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
@@ -165,6 +256,10 @@ MmcIoBlocks (
     return EFI_NO_MEDIA;
   }
 
+  if (MmcHost->IsMultiBlock && MmcHost->IsMultiBlock(MmcHost)) {
+    BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
+  }
+
   // All blocks must be within the device
   if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
     return EFI_INVALID_PARAMETER;
@@ -210,75 +305,38 @@ MmcIoBlocks (
       return EFI_NOT_READY;
     }
 
-    //Set command argument based on the card access mode (Byte mode or Block mode)
-    if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
-      CmdArg = Lba;
-    } else {
-      CmdArg = Lba * This->Media->BlockSize;
-    }
-
     if (Transfer == MMC_IOBLOCKS_READ) {
-      // Read a single block
-      Cmd = MMC_CMD17;
-    } else {
-      // Write a single block
-      Cmd = MMC_CMD24;
-    }
-    Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
-      return Status;
-    }
-
-    if (Transfer == MMC_IOBLOCKS_READ) {
-      // Read one block of Data
-      Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
-      if (EFI_ERROR (Status)) {
-        DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
-        MmcStopTransmission (MmcHost);
-        return Status;
-      }
-      Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
-      if (EFI_ERROR (Status)) {
-        DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
-        return Status;
+      if (BlockCount == 1) {
+        // Read a single block
+        Cmd = MMC_CMD17;
+      } else {
+	// Read multiple blocks
+	Cmd = MMC_CMD18;
       }
     } else {
-      // Write one block of Data
-      Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
-      if (EFI_ERROR (Status)) {
-        DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
-        MmcStopTransmission (MmcHost);
-        return Status;
+      if (BlockCount == 1) {
+        // Write a single block
+        Cmd = MMC_CMD24;
+      } else {
+	// Write multiple blocks
+	Cmd = MMC_CMD25;
       }
     }
 
-    // Command 13 - Read status and wait for programming to complete (return to tran)
-    Timeout = MMCI0_TIMEOUT;
-    CmdArg = MmcHostInstance->CardInfo.RCA << 16;
-    Response[0] = 0;
-    while(   (!(Response[0] & MMC_R0_READY_FOR_DATA))
-          && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
-          && Timeout--) {
-      Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
-      if (!EFI_ERROR (Status)) {
-        MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
-        if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
-          break;  // Prevents delay once finished
-        }
-      }
-      gBS->Stall (1);
+    ConsumeSize = BlockCount * This->Media->BlockSize;
+    if (BytesRemainingToBeTransfered < ConsumeSize) {
+      ConsumeSize = BytesRemainingToBeTransfered;
     }
-
-    Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+    Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
     if (EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
-      return Status;
+      DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
     }
 
-    BytesRemainingToBeTransfered -= This->Media->BlockSize;
-    Lba    += BlockCount;
-    Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+    BytesRemainingToBeTransfered -= ConsumeSize;
+    if (BytesRemainingToBeTransfered > 0) {
+      Lba    += BlockCount;
+      Buffer = (UINT8 *)Buffer + ConsumeSize;
+    }
   }
 
   return EFI_SUCCESS;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v7 0/4] enhance MMC
  2016-11-23  7:08 [PATCH v7 0/4] enhance MMC Haojian Zhuang
                   ` (3 preceding siblings ...)
  2016-11-23  7:08 ` [PATCH v7 4/4] MmcDxe: expand to support multiple blocks Haojian Zhuang
@ 2016-11-23  8:54 ` Ard Biesheuvel
  4 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2016-11-23  8:54 UTC (permalink / raw)
  To: Haojian Zhuang; +Cc: Ryan Harkin, edk2-devel-01, Leif Lindholm

On 23 November 2016 at 07:08, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> v7:
>   * Add revision checking.
>

Thanks for the hard work and the quick turnaround, but I'm afraid
we're not quite there yet.

Please find my comments in response to the individual patches

> v6:
>   * Reformat the last 5 patches after 4 MMC patches of this series merged.
>   * Squash original #5 and #6 patches together.
>   * Fix according comments.
>
> v5:
>   * Remove patch on MediaId.
>   * Squash two PL180 patches together.
>
> v4:
>   * Fix PL180 hang in some cases. Since the proper variable length
>     isn't set for CMD6 & ACMD51.
>
> v3:
>   * Fix PL180 hang because of CMD6 & ACMD51 not supported.
>
> v2:
>   * Fix print error with missing parameter.
>   * Change CMD51 to ACMD51.
>   * Add the protection after CMD55 for SD. If there's no
>     response of CMD55, skip to send ACMD51.
>
> v1:
>   * Wait OCR busy bit free according to eMMC spec.
>   * Define ECSD structure.
>   * Add interface to set IO bus width and speed.
>   * Support to access multiple blocks.
>
> Haojian Zhuang (4):
>   MmcDxe: add interface to change io width and speed
>   MmcDxe: set iospeed and bus width in SD stack
>   PL180: update for indentifying SD
>   MmcDxe: expand to support multiple blocks
>
>  ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c    |  29 ++-
>  EmbeddedPkg/Include/Protocol/MmcHost.h           |  36 ++-
>  EmbeddedPkg/Universal/MmcDxe/Mmc.h               |  25 ++
>  EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c        | 176 +++++++++-----
>  EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 291 ++++++++++++++++++++++-
>  5 files changed, 487 insertions(+), 70 deletions(-)
>
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v7 1/4] MmcDxe: add interface to change io width and speed
  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
  0 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2016-11-23  8:56 UTC (permalink / raw)
  To: Haojian Zhuang; +Cc: Ryan Harkin, edk2-devel-01, Leif Lindholm

On 23 November 2016 at 07:08, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> By default, MMC is initialized with 1-bit mode and less than 400KHz bus
> clock. It causes MMC working inefficiently.
>
> Add the interface to change the bus width and speed.
>
> Set io bus width on both MMC controller and EXTCSD. Otherwise, it may
> cause unmatched failure case. And support more timing mode, high speed,
> HS200 & HS400 mode.
>
> 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           |  25 ++-
>  EmbeddedPkg/Universal/MmcDxe/Mmc.h               |   5 +
>  EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 185 ++++++++++++++++++++++-
>  3 files changed, 211 insertions(+), 4 deletions(-)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 89f2e80..9d7a604 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -49,6 +49,7 @@ typedef UINT32 MMC_CMD;
>  #define MMC_CMD2              (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
>  #define MMC_CMD3              (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD5              (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
> +#define MMC_CMD6              (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD7              (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD8              (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD9              (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
> @@ -82,6 +83,16 @@ typedef enum _MMC_STATE {
>      MmcDisconnectState,
>  } MMC_STATE;
>
> +#define EMMCBACKWARD         (0)
> +#define EMMCHS26             (1 << 0)      // High-Speed @26MHz at rated device voltages
> +#define EMMCHS52             (1 << 1)      // High-Speed @52MHz at rated device voltages
> +#define EMMCHS52DDR1V8       (1 << 2)      // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O
> +#define EMMCHS52DDR1V2       (1 << 3)      // High-Speed Dual Data Rate @52MHz 1.2V I/O
> +#define EMMCHS200SDR1V8      (1 << 4)      // HS200 Single Data Rate @200MHz 1.8V I/O
> +#define EMMCHS200SDR1V2      (1 << 5)      // HS200 Single Data Rate @200MHz 1.2V I/O
> +#define EMMCHS400DDR1V8      (1 << 6)      // HS400 Dual Data Rate @400MHz 1.8V I/O
> +#define EMMCHS400DDR1V2      (1 << 7)      // HS400 Dual Data Rate @400MHz 1.2V I/O
> +
>  ///
>  /// Forward declaration for EFI_MMC_HOST_PROTOCOL
>  ///
> @@ -131,6 +142,13 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
>    IN  UINT32                    *Buffer
>    );
>
> +typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
> +  IN  EFI_MMC_HOST_PROTOCOL     *This,
> +  IN  UINT32                    BusClockFreq,
> +  IN  UINT32                    BusWidth,
> +  IN  UINT32                    TimingMode
> +  );
> +
>
>  struct _EFI_MMC_HOST_PROTOCOL {
>
> @@ -147,9 +165,14 @@ struct _EFI_MMC_HOST_PROTOCOL {
>    MMC_READBLOCKDATA       ReadBlockData;
>    MMC_WRITEBLOCKDATA      WriteBlockData;
>
> +  MMC_SETIOS              SetIos;
> +
>  };
>
> -#define MMC_HOST_PROTOCOL_REVISION    0x00010001    // 1.1
> +#define MMC_HOST_PROTOCOL_REVISION    0x00010002    // 1.2
> +
> +#define MMC_HOST_HAS_SETIOS(Host)     (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
> +                                       Host->SetIos != NULL)
>

This looks fine now. But in patch 4/4 you increase the revision again,
which does not make a lot of sense.

I think the best solution is to split off the changes to the protocol
header, and add both new protocol methods in a single patch.

>  extern EFI_GUID gEfiMmcHostProtocolGuid;
>
> diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> index 112bc47..fb3f6c9 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> +++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> @@ -55,6 +55,11 @@
>  #define MMC_R0_STATE_TRAN       4
>  #define MMC_R0_STATE_DATA       5
>
> +#define EMMC_CMD6_ARG_ACCESS(x)             (((x) & 0x3) << 24)
> +#define EMMC_CMD6_ARG_INDEX(x)              (((x) & 0xFF) << 16)
> +#define EMMC_CMD6_ARG_VALUE(x)              (((x) & 0xFF) << 8)
> +#define EMMC_CMD6_ARG_CMD_SET(x)            (((x) & 0x7) << 0)
> +
>  typedef enum {
>    UNKNOWN_CARD,
>    MMC_CARD,              //MMC card
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> index 9aefb26..7441459 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> @@ -25,11 +25,111 @@ typedef union {
>  #define EMMC_CARD_SIZE          512
>  #define EMMC_ECSD_SIZE_OFFSET   53
>
> +#define EXTCSD_BUS_WIDTH        183
> +#define EXTCSD_HS_TIMING        185
> +
> +#define EMMC_TIMING_BACKWARD    0
> +#define EMMC_TIMING_HS          1
> +#define EMMC_TIMING_HS200       2
> +#define EMMC_TIMING_HS400       3
> +
> +#define EMMC_BUS_WIDTH_1BIT     0
> +#define EMMC_BUS_WIDTH_4BIT     1
> +#define EMMC_BUS_WIDTH_8BIT     2
> +#define EMMC_BUS_WIDTH_DDR_4BIT 5
> +#define EMMC_BUS_WIDTH_DDR_8BIT 6
> +
> +#define EMMC_SWITCH_ERROR       (1 << 7)
> +
> +#define DEVICE_STATE(x)         (((x) >> 9) & 0xf)
> +typedef enum _EMMC_DEVICE_STATE {
> +  EMMC_IDLE_STATE = 0,
> +  EMMC_READY_STATE,
> +  EMMC_IDENT_STATE,
> +  EMMC_STBY_STATE,
> +  EMMC_TRAN_STATE,
> +  EMMC_DATA_STATE,
> +  EMMC_RCV_STATE,
> +  EMMC_PRG_STATE,
> +  EMMC_DIS_STATE,
> +  EMMC_BTST_STATE,
> +  EMMC_SLP_STATE
> +} EMMC_DEVICE_STATE;
> +
>  UINT32 mEmmcRcaCount = 0;
>
>  STATIC
>  EFI_STATUS
>  EFIAPI
> +EmmcGetDeviceState (
> +  IN  MMC_HOST_INSTANCE    *MmcHostInstance,
> +  OUT EMMC_DEVICE_STATE    *State
> +  )
> +{
> +  EFI_MMC_HOST_PROTOCOL *Host;
> +  EFI_STATUS Status;
> +  UINT32     Data, RCA;
> +
> +  if (State == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Host = MmcHostInstance->MmcHost;
> +  RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
> +  Status = Host->SendCommand (Host, MMC_CMD13, RCA);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
> +    return Status;
> +  }
> +  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
> +    return Status;
> +  }
> +  if (Data & EMMC_SWITCH_ERROR) {
> +    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
> +    return EFI_DEVICE_ERROR;
> +  }
> +  *State = DEVICE_STATE(Data);
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +EmmcSetEXTCSD (
> +  IN MMC_HOST_INSTANCE     *MmcHostInstance,
> +  UINT32                   ExtCmdIndex,
> +  UINT32                   Value
> +  )
> +{
> +  EFI_MMC_HOST_PROTOCOL *Host;
> +  EMMC_DEVICE_STATE     State;
> +  EFI_STATUS Status;
> +  UINT32     Argument;
> +
> +  Host  = MmcHostInstance->MmcHost;
> +  Argument = EMMC_CMD6_ARG_ACCESS(3) | EMMC_CMD6_ARG_INDEX(ExtCmdIndex) |
> +             EMMC_CMD6_ARG_VALUE(Value) | EMMC_CMD6_ARG_CMD_SET(1);
> +  Status = Host->SendCommand (Host, MMC_CMD6, Argument);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
> +    return Status;
> +  }
> +  // Make sure device exiting prog mode
> +  do {
> +    Status = EmmcGetDeviceState (MmcHostInstance, &State);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
> +      return Status;
> +    }
> +  } while (State == EMMC_PRG_STATE);
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
>  EmmcIdentificationMode (
>    IN MMC_HOST_INSTANCE     *MmcHostInstance,
>    IN OCR_RESPONSE           Response
> @@ -38,6 +138,7 @@ EmmcIdentificationMode (
>    EFI_MMC_HOST_PROTOCOL *Host;
>    EFI_BLOCK_IO_MEDIA    *Media;
>    EFI_STATUS Status;
> +  EMMC_DEVICE_STATE     State;
>    UINT32     RCA;
>
>    Host  = MmcHostInstance->MmcHost;
> @@ -84,6 +185,22 @@ EmmcIdentificationMode (
>      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
>    }
>
> +  if (MMC_HOST_HAS_SETIOS(Host)) {
> +    // Set 1-bit bus width
> +    Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
> +      return Status;
> +    }
> +
> +    // Set 1-bit bus width for EXTCSD
> +    Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
> +      return Status;
> +    }
> +  }
> +
>    // Fetch ECSD
>    Status = Host->SendCommand (Host, MMC_CMD8, RCA);
>    if (EFI_ERROR (Status)) {
> @@ -96,6 +213,15 @@ EmmcIdentificationMode (
>      return Status;
>    }
>
> +  // Make sure device exiting data mode
> +  do {
> +    Status = EmmcGetDeviceState (MmcHostInstance, &State);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
> +      return Status;
> +    }
> +  } while (State == EMMC_DATA_STATE);
> +
>    // Set up media
>    Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
>    Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
> @@ -113,6 +239,57 @@ EmmcIdentificationMode (
>
>  STATIC
>  EFI_STATUS
> +InitializeEmmcDevice (
> +  IN  MMC_HOST_INSTANCE   *MmcHostInstance
> +  )
> +{
> +  EFI_MMC_HOST_PROTOCOL *Host;
> +  EFI_STATUS Status = EFI_SUCCESS;
> +  ECSD       *ECSDData;
> +  UINT32     BusClockFreq, Idx;
> +  UINT32     TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
> +
> +  Host  = MmcHostInstance->MmcHost;
> +  ECSDData = &MmcHostInstance->CardInfo.ECSDData;
> +  if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
> +    return EFI_SUCCESS;
> +
> +  if (!MMC_HOST_HAS_SETIOS(Host)) {
> +    return EFI_SUCCESS;
> +  }
> +  Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
> +    return Status;
> +  }
> +
> +  for (Idx = 0; Idx < 4; Idx++) {
> +    switch (TimingMode[Idx]) {
> +    case EMMCHS52DDR1V2:
> +    case EMMCHS52DDR1V8:
> +    case EMMCHS52:
> +      BusClockFreq = 52000000;
> +      break;
> +    case EMMCHS26:
> +      BusClockFreq = 26000000;
> +      break;
> +    default:
> +      return EFI_UNSUPPORTED;
> +    }
> +    Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
> +    if (!EFI_ERROR (Status)) {
> +      Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_DDR_8BIT);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
> +      }
> +      return Status;
> +    }
> +  }
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
>  InitializeSdMmcDevice (
>    IN  MMC_HOST_INSTANCE   *MmcHostInstance
>    )
> @@ -431,9 +608,11 @@ InitializeMmcDevice (
>
>    if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
>      Status = InitializeSdMmcDevice (MmcHostInstance);
> -    if (EFI_ERROR (Status)) {
> -      return Status;
> -    }
> +  } else {
> +    Status = InitializeEmmcDevice (MmcHostInstance);
> +  }
> +  if (EFI_ERROR (Status)) {
> +    return Status;
>    }
>
>    // Set Block Length
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v7 2/4] MmcDxe: set iospeed and bus width in SD stack
  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
  0 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2016-11-23  8:58 UTC (permalink / raw)
  To: Haojian Zhuang; +Cc: Ryan Harkin, edk2-devel-01, Leif Lindholm

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
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v7 3/4] PL180: update for indentifying SD
  2016-11-23  7:08 ` [PATCH v7 3/4] PL180: update for indentifying SD Haojian Zhuang
@ 2016-11-23  8:59   ` Ard Biesheuvel
  0 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2016-11-23  8:59 UTC (permalink / raw)
  To: Haojian Zhuang; +Cc: Ryan Harkin, edk2-devel-01, Leif Lindholm

On 23 November 2016 at 07:08, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> When CMD6 & ACMD51 are added into indentifying SD process, PL180
> should also support CMD6 & ACMD51. Otherwise, it'll hang when
> system tries to read expected data.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 ++++++++++++++++++++-------
>  1 file changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> index 5526aac..b2ba4c0 100644
> --- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> +++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> @@ -63,11 +63,6 @@ MciIsReadOnly (
>    return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
>  }
>
> -#if 0
> -//Note: This function has been commented out because it is not used yet.
> -//      This function could be used to remove the hardcoded BlockLen used
> -//      in MciPrepareDataPath
> -
>  // Convert block size to 2^n
>  STATIC
>  UINT32
> @@ -87,7 +82,6 @@ GetPow2BlockLen (
>
>    return Pow2BlockLen;
>  }
> -#endif
>
>  VOID
>  MciPrepareDataPath (
> @@ -126,6 +120,23 @@ MciSendCommand (
>      MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
>    } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
>      MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
> +  } else if (MmcCmd == MMC_CMD6) {
> +    MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
> +    MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
> +#ifndef USE_STREAM
> +    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
> +#else
> +    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
> +#endif
> +  } else if (MmcCmd == MMC_ACMD51) {
> +    MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
> +    /* SCR register is 8 bytes long. */
> +    MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
> +#ifndef USE_STREAM
> +    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
> +#else
> +    MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
> +#endif
>    }
>
>    // Create Command for PL180
> @@ -223,7 +234,11 @@ MciReadBlockData (
>
>    // Read data from the RX FIFO
>    Loop   = 0;
> -  Finish = MMCI0_BLOCKLEN / 4;
> +  if (Length < MMCI0_BLOCKLEN) {
> +    Finish = Length / 4;
> +  } else {
> +    Finish = MMCI0_BLOCKLEN / 4;
> +  }
>
>    // Raise the TPL at the highest level to disable Interrupts.
>    Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v7 4/4] MmcDxe: expand to support multiple blocks
  2016-11-23  7:08 ` [PATCH v7 4/4] MmcDxe: expand to support multiple blocks Haojian Zhuang
@ 2016-11-23  9:01   ` Ard Biesheuvel
  0 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2016-11-23  9:01 UTC (permalink / raw)
  To: Haojian Zhuang; +Cc: Ryan Harkin, edk2-devel-01, Leif Lindholm

On 23 November 2016 at 07:08, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> Make use of DMA to transfer multiple blocks at one time. It could
> improve the performance on MMC/SD driver.
>
> 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    |  10 +-
>  EmbeddedPkg/Universal/MmcDxe/Mmc.h        |   4 +
>  EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 176 ++++++++++++++++++++----------
>  3 files changed, 130 insertions(+), 60 deletions(-)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 445e53f..8c8c8a7 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -62,6 +62,7 @@ typedef UINT32 MMC_CMD;
>  #define MMC_CMD20             (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD23             (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
>  #define MMC_CMD24             (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
> +#define MMC_CMD25             (MMC_INDX(25) | 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)
> @@ -152,6 +153,10 @@ typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
>    IN  UINT32                    TimingMode
>    );
>
> +typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) (
> +  IN  EFI_MMC_HOST_PROTOCOL     *This
> +  );
> +
>
>  struct _EFI_MMC_HOST_PROTOCOL {
>
> @@ -169,13 +174,16 @@ struct _EFI_MMC_HOST_PROTOCOL {
>    MMC_WRITEBLOCKDATA      WriteBlockData;
>
>    MMC_SETIOS              SetIos;
> +  MMC_ISMULTIBLOCK        IsMultiBlock;
>
>  };
>
> -#define MMC_HOST_PROTOCOL_REVISION    0x00010002    // 1.2
> +#define MMC_HOST_PROTOCOL_REVISION    0x00010003    // 1.3
>
>  #define MMC_HOST_HAS_SETIOS(Host)     (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
>                                         Host->SetIos != NULL)
> +#define MMC_HOST_HAS_ISMULTIBLOCK(Host) (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \
> +                                         Host->IsMultiBlock != NULL)
>
>  extern EFI_GUID gEfiMmcHostProtocolGuid;
>

Please move this part into the new, separate patch I suggested in 1/4.
That way, we can keep the version at 1.2. Could you please also add a
comment next to the new methods to show that they were added in
revision 1.2?

> diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> index 6bc85e0..8e7a80a 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> +++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> @@ -34,6 +34,10 @@
>
>  #define MMC_OCR_POWERUP             0x80000000
>
> +#define MMC_OCR_ACCESS_MASK         0x3     /* bit[30-29] */
> +#define MMC_OCR_ACCESS_BYTE         0x1     /* bit[29] */
> +#define MMC_OCR_ACCESS_SECTOR       0x2     /* bit[30] */
> +
>  #define MMC_CSD_GET_CCC(Response)    (Response[2] >> 20)
>  #define MMC_CSD_GET_TRANSPEED(Response)    (Response[3] & 0xFF)
>  #define MMC_CSD_GET_READBLLEN(Response)    ((Response[2] >> 16) & 0xF)
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> index 0e1ef57..35570fd 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> @@ -126,6 +126,96 @@ MmcStopTransmission (
>  #define MMCI0_BLOCKLEN 512
>  #define MMCI0_TIMEOUT  10000
>
> +STATIC
> +EFI_STATUS
> +MmcTransferBlock (
> +  IN EFI_BLOCK_IO_PROTOCOL    *This,
> +  IN UINTN                    Cmd,
> +  IN UINTN                    Transfer,
> +  IN UINT32                   MediaId,
> +  IN EFI_LBA                  Lba,
> +  IN UINTN                    BufferSize,
> +  OUT VOID                    *Buffer
> +  )
> +{
> +  EFI_STATUS              Status;
> +  UINTN                   CmdArg;
> +  INTN                    Timeout;
> +  UINT32                  Response[4];
> +  MMC_HOST_INSTANCE       *MmcHostInstance;
> +  EFI_MMC_HOST_PROTOCOL   *MmcHost;
> +
> +  MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
> +  MmcHost = MmcHostInstance->MmcHost;
> +
> +  //Set command argument based on the card access mode (Byte mode or Block mode)
> +  if ((MmcHostInstance->CardInfo.OCRData.AccessMode & MMC_OCR_ACCESS_MASK) ==
> +      MMC_OCR_ACCESS_SECTOR) {
> +    CmdArg = Lba;
> +  } else {
> +    CmdArg = Lba * This->Media->BlockSize;
> +  }
> +
> +  Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
> +    return Status;
> +  }
> +
> +  if (Transfer == MMC_IOBLOCKS_READ) {
> +    // Read Data
> +    Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
> +      MmcStopTransmission (MmcHost);
> +      return Status;
> +    }
> +    Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
> +      return Status;
> +    }
> +  } else {
> +    // Write Data
> +    Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
> +      MmcStopTransmission (MmcHost);
> +      return Status;
> +    }
> +  }
> +
> +  // Command 13 - Read status and wait for programming to complete (return to tran)
> +  Timeout = MMCI0_TIMEOUT;
> +  CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> +  Response[0] = 0;
> +  while(!(Response[0] & MMC_R0_READY_FOR_DATA)
> +        && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
> +        && Timeout--) {
> +    Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
> +    if (!EFI_ERROR (Status)) {
> +      MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> +      if (Response[0] & MMC_R0_READY_FOR_DATA) {
> +        break;  // Prevents delay once finished
> +      }
> +    }
> +  }
> +
> +  if (BufferSize > This->Media->BlockSize) {
> +    Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
> +    }
> +  }
> +
> +  Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
> +    return Status;
> +  }
> +  return Status;
> +}
> +
>  EFI_STATUS
>  MmcIoBlocks (
>    IN EFI_BLOCK_IO_PROTOCOL    *This,
> @@ -145,6 +235,7 @@ MmcIoBlocks (
>    EFI_MMC_HOST_PROTOCOL   *MmcHost;
>    UINTN                   BytesRemainingToBeTransfered;
>    UINTN                   BlockCount;
> +  UINTN                   ConsumeSize;
>
>    BlockCount = 1;
>    MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
> @@ -165,6 +256,10 @@ MmcIoBlocks (
>      return EFI_NO_MEDIA;
>    }
>
> +  if (MmcHost->IsMultiBlock && MmcHost->IsMultiBlock(MmcHost)) {

Shouldn't you use the macro here?

> +    BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
> +  }
> +
>    // All blocks must be within the device
>    if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
>      return EFI_INVALID_PARAMETER;
> @@ -210,75 +305,38 @@ MmcIoBlocks (
>        return EFI_NOT_READY;
>      }
>
> -    //Set command argument based on the card access mode (Byte mode or Block mode)
> -    if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
> -      CmdArg = Lba;
> -    } else {
> -      CmdArg = Lba * This->Media->BlockSize;
> -    }
> -
>      if (Transfer == MMC_IOBLOCKS_READ) {
> -      // Read a single block
> -      Cmd = MMC_CMD17;
> -    } else {
> -      // Write a single block
> -      Cmd = MMC_CMD24;
> -    }
> -    Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
> -      return Status;
> -    }
> -
> -    if (Transfer == MMC_IOBLOCKS_READ) {
> -      // Read one block of Data
> -      Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
> -      if (EFI_ERROR (Status)) {
> -        DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
> -        MmcStopTransmission (MmcHost);
> -        return Status;
> -      }
> -      Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
> -      if (EFI_ERROR (Status)) {
> -        DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
> -        return Status;
> +      if (BlockCount == 1) {
> +        // Read a single block
> +        Cmd = MMC_CMD17;
> +      } else {
> +       // Read multiple blocks
> +       Cmd = MMC_CMD18;
>        }
>      } else {
> -      // Write one block of Data
> -      Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
> -      if (EFI_ERROR (Status)) {
> -        DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
> -        MmcStopTransmission (MmcHost);
> -        return Status;
> +      if (BlockCount == 1) {
> +        // Write a single block
> +        Cmd = MMC_CMD24;
> +      } else {
> +       // Write multiple blocks
> +       Cmd = MMC_CMD25;
>        }
>      }
>
> -    // Command 13 - Read status and wait for programming to complete (return to tran)
> -    Timeout = MMCI0_TIMEOUT;
> -    CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> -    Response[0] = 0;
> -    while(   (!(Response[0] & MMC_R0_READY_FOR_DATA))
> -          && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
> -          && Timeout--) {
> -      Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
> -      if (!EFI_ERROR (Status)) {
> -        MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> -        if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
> -          break;  // Prevents delay once finished
> -        }
> -      }
> -      gBS->Stall (1);
> +    ConsumeSize = BlockCount * This->Media->BlockSize;
> +    if (BytesRemainingToBeTransfered < ConsumeSize) {
> +      ConsumeSize = BytesRemainingToBeTransfered;
>      }
> -
> -    Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
> +    Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
>      if (EFI_ERROR (Status)) {
> -      DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
> -      return Status;
> +      DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
>      }
>
> -    BytesRemainingToBeTransfered -= This->Media->BlockSize;
> -    Lba    += BlockCount;
> -    Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
> +    BytesRemainingToBeTransfered -= ConsumeSize;
> +    if (BytesRemainingToBeTransfered > 0) {
> +      Lba    += BlockCount;
> +      Buffer = (UINT8 *)Buffer + ConsumeSize;
> +    }
>    }
>
>    return EFI_SUCCESS;
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-11-23  9:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox