[edk2] [PATCH 1/4] EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay

2019-02-22 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Existing implementation checks for error regardless of if
DWEMMC_INT_CMD_DONE is set, causing the loop check to errors out
even when it shouldn't if the MicroSecondDelay doesn't do long
enough delays. This removes MicroSecondDelay and updates the
function to check for CMD_DONE before doing any error checking.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 0437e30..6d0f472 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -290,17 +290,15 @@ SendCommand (
   ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
 DWEMMC_INT_RCRC | DWEMMC_INT_RE;
   ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
   do {
-MicroSecondDelay(500);
 Data = MmioRead32 (DWEMMC_RINTSTS);
-
-if (Data & ErrMask) {
-  return EFI_DEVICE_ERROR;
-}
-if (Data & DWEMMC_INT_DTO) { // Transfer Done
-  break;
-}
   } while (!(Data & DWEMMC_INT_CMD_DONE));
+
+  if (Data & ErrMask) {
+return EFI_DEVICE_ERROR;
+  }
+
   return EFI_SUCCESS;
 }
 
-- 
2.2.2

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


[edk2] [PATCH 4/4] EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

2019-02-22 Thread tien . hock . loh
From: "Tien Hock, Loh" 

DwEmmcReadBlockData and DwEmmcWriteBlockData needs to check for the
transfer completion before returning. This also adds error checking
to the DMA transfer.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Tien Hock, Loh 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 36 +--
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index c232309..c13cd97 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -212,6 +212,7 @@ DwEmmcNotifyState (
 MmioWrite32 (DWEMMC_TMOUT, ~0);
 MmioWrite32 (DWEMMC_IDINTEN, 0);
 MmioWrite32 (DWEMMC_BMOD, DWEMMC_IDMAC_SWRESET);
+MmioWrite32 (DWEMMC_CTYPE, 0);
 
 MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
 do {
@@ -497,10 +498,7 @@ PrepareDmaData (
   Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
   Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
 
-  if(Length < DWEMMC_BLOCK_SIZE) {
-Length = Length;
-  }
-  else {
+  if(Length >= DWEMMC_BLOCK_SIZE) {
 Length = DWEMMC_BLOCK_SIZE * Blks;
   }
 
@@ -563,8 +561,9 @@ DwEmmcReadBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts = 0;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -587,6 +586,18 @@ DwEmmcReadBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
@@ -602,8 +613,9 @@ DwEmmcWriteBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts = 0;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -626,6 +638,18 @@ DwEmmcWriteBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
-- 
2.2.2

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


[edk2] [PATCH 3/4] EmbeddedPkg/DwEmmc: Fix DMA transfer length

2019-02-22 Thread tien . hock . loh
From: "Loh, Tien Hock" 

DMA should not transfer more than requested length otherwise FIFO might run
into buffer underrun and causes errors in future transfers.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 600ab01..c232309 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -496,7 +496,13 @@ PrepareDmaData (
 
   Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
   Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
-  Length = DWEMMC_BLOCK_SIZE * Blks;
+
+  if(Length < DWEMMC_BLOCK_SIZE) {
+Length = Length;
+  }
+  else {
+Length = DWEMMC_BLOCK_SIZE * Blks;
+  }
 
   for (Idx = 0; Idx < Cnt; Idx++) {
 (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |
@@ -534,11 +540,18 @@ StartDma (
   Data |= DWEMMC_CTRL_INT_EN | DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;
   MmioWrite32 (DWEMMC_CTRL, Data);
   Data = MmioRead32 (DWEMMC_BMOD);
+
   Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;
   MmioWrite32 (DWEMMC_BMOD, Data);
 
-  MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
-  MmioWrite32 (DWEMMC_BYTCNT, Length);
+  if(Length < DWEMMC_BLOCK_SIZE) {
+MmioWrite32 (DWEMMC_BLKSIZ, Length);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
+  else {
+MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
 }
 
 EFI_STATUS
-- 
2.2.2

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


[edk2] [PATCH 2/4] EmbeddedPkg/DwEmmc: Fix SendCommand parameters

2019-02-22 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Only send BIT_CMD_CHECK_RESPONSE_CRC if MMC commands needs it.

Fixes parameters to ACMD6 where if CMD is application command, ie. CMD55 is
sent before ACMD6, to do response instead of data transfer.

Added CMD51 handling as CMD51 is a data transfer, and needs BIT_CMD_READ
and BIT_CMD_DATA_EXPECTED to be set.

Updates DwEmmcReceiveResponse to SendCommand only if IsPendingReadCommand
or IsPendingWriteCommand is true.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 59 +++
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 6d0f472..600ab01 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -45,6 +45,7 @@ DWEMMC_IDMAC_DESCRIPTOR   *gpIdmacDesc;
 EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;
 STATIC UINT32 mDwEmmcCommand;
 STATIC UINT32 mDwEmmcArgument;
+STATIC BOOLEAN mIsACmd = FALSE;
 
 EFI_STATUS
 DwEmmcReadBlockData (
@@ -321,68 +322,93 @@ DwEmmcSendCommand (
 break;
   case MMC_INDX(2):
 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
-   BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
+   BIT_CMD_SEND_INIT;
 break;
   case MMC_INDX(3):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_SEND_INIT;
 break;
+  case MMC_INDX(6):
+if(mIsACmd) {
+  Cmd = BIT_CMD_RESPONSE_EXPECT ;
+}
+else {
+  Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+BIT_CMD_READ;
+}
+break;
   case MMC_INDX(7):
 if (Argument)
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT;
 else
 Cmd = 0;
 break;
   case MMC_INDX(8):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
-   BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(9):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_LONG_RESPONSE;
 break;
   case MMC_INDX(12):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_STOP_ABORT_CMD;
 break;
   case MMC_INDX(13):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(16):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(17):
   case MMC_INDX(18):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(24):
   case MMC_INDX(25):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(30):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED;
 break;
+  case MMC_INDX(51):
+Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+   BIT_CMD_READ | BIT_CMD_WAIT_PRVDATA_COMPLETE;
+break;
   default:
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT ;
 break;
   }
 
   Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
+
+  if(MMC_INDX(55) == MMC_GET_INDX(MmcCmd))
+mIsACmd = TRUE;
+  else
+mIsACmd = FALSE;
+
+  if (!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) {
+Cmd |= BIT_CMD_CHECK_RESPONSE_CRC;
+  }
+
   if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {
 mDwEmmcCommand = Cmd;
 mDwEmmcArgument = Argument;
   } else {
+mDwEmmcCommand = Cmd;
+mDwEmmcArgument = Argument;
 Status = SendCommand (Cmd, Argument);
   }
+
   return Status;
 }
 
@@ -393,6 +419,11 @@ DwEmmcReceiveResponse (
   IN UINT32*Buffer
   )
 {
+  EFI_STATUS Status = EFI_SUCCESS;
+
+  if(IsPendingReadCommand (mDwEmmcCommand) || 
IsPendingWriteCommand(mDwEmmcCommand))
+Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
+
   if (Buffer == NULL) {
 return EFI_INVALID_PARAMETER;
   }
@@ -410,7 +441,7 @@ DwEmmcReceiveResponse (
 Buffer[2] = MmioRead32 (DWEMMC_RESP2);
 Buffer[3] = MmioRead32 (DWEMMC_RESP3);
   }
-  return EFI_SUCCESS;
+  return Status;
 }
 
 VOID
-- 
2.2.2


[edk2] [PATCH 0/4] EmbeddedPkg/DwEmmc: Fix bugs causing DwEmmc to fail to initialize

2019-02-22 Thread tien . hock . loh
From: "Tien Hock, Loh" 

This patch series fixes bugs with DwEmmc driver, namely:
* Added CMD6 handling
* Fixed workaround querying SendCommand using delays
* Fix DMA transfer length causing buffer underrun in FIFO
* Check DMA completion before returning from SendCommand

Loh, Tien Hock (3):
  EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay
  EmbeddedPkg/DwEmmc: Fix SendCommand parameters
  EmbeddedPkg/DwEmmc: Fix DMA transfer length

Tien Hock, Loh (1):
  EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 120 +++---
 1 file changed, 93 insertions(+), 27 deletions(-)

-- 
2.2.2

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


[edk2] [PATCH 1/1] SD : Continue setting up sd even if SD_HIGH_SPEED is not supported

2019-02-21 Thread tien . hock . loh
From: "Loh, Tien Hock" 

If SD doesn't support SD_HIGH_SPEED, function should still continue to
setup SD to go into 4 bits more if it is supported.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c 
b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index f661a0c..8fd5c31 100755
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -474,18 +474,17 @@ InitializeSdMmcDevice (
 
 if (!(Buffer[3] & SD_HIGH_SPEED_SUPPORTED)) {
   DEBUG ((DEBUG_ERROR, "%a : High Speed not supported by Card %r\n", 
__FUNCTION__, Status));
-  return Status;
 }
+else {
+  Speed = SD_HIGH_SPEED;
 
-Speed = SD_HIGH_SPEED;
-
-/* SD Switch, Mode:1, Group:0, Value:1 */
-CmdArg = CreateSwitchCmdArgument(1, 0, 1);
-Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
-if (EFI_ERROR (Status)) {
-  DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", 
__FUNCTION__, Status));
-   return Status;
-} else {
+  /* SD Switch, Mode:1, Group:0, Value:1 */
+  CmdArg = CreateSwitchCmdArgument(1, 0, 1);
+  Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
+  if (EFI_ERROR (Status)) {
+DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", 
__FUNCTION__, Status));
+return Status;
+  } else {
   Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, 
Buffer);
   if (EFI_ERROR (Status)) {
 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = 
%r\n", __FUNCTION__, Status));
@@ -495,6 +494,7 @@ InitializeSdMmcDevice (
   if ((Buffer[4] & SWITCH_CMD_SUCCESS_MASK) != 0x0100) {
 DEBUG((DEBUG_ERROR, "Problem switching SD card into high-speed 
mode\n"));
 return Status;
+}
   }
 }
   }
-- 
2.2.2

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


[edk2] [PATCH 4/4] EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

2019-02-21 Thread tien . hock . loh
From: "Loh, Tien Hock" 

DwEmmcReadBlockData and DwEmmcWriteBlockData needs to check for the
transfer completion before returning. This also adds error checking
to the DMA transfer.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 30 --
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index c232309..baf299d 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -563,8 +563,9 @@ DwEmmcReadBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -587,6 +588,18 @@ DwEmmcReadBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
@@ -602,8 +615,9 @@ DwEmmcWriteBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -626,6 +640,18 @@ DwEmmcWriteBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
-- 
2.2.2

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


[edk2] [PATCH 0/4] EmbeddedPkg/DwEmmc: Fix bugs causing DwEmmc to fail to initialize

2019-02-21 Thread tien . hock . loh
From: Loh Tien Hock 

This patch series fixes bugs with DwEmmc driver, namely:
* Added CMD6 handling
* Fixed workaround querying SendCommand using delays
* Fix DMA transfer length causing buffer underrun in FIFO
* Check DMA completion before returning from SendCommand

Loh, Tien Hock (4):
  EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay
  EmbeddedPkg/DwEmmc: Fix SendCommand parameters
  EmbeddedPkg/DwEmmc: Fix DMA transfer length
  EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 122 +++---
 1 file changed, 95 insertions(+), 27 deletions(-)

-- 
2.2.2

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


[edk2] [PATCH 2/4] EmbeddedPkg/DwEmmc: Fix SendCommand parameters

2019-02-21 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Only send BIT_CMD_CHECK_RESPONSE_CRC if MMC commands needs it.

Fixes parameters to ACMD6 where if CMD is application command, ie. CMD55 is
sent before ACMD6, to do response instead of data transfer.

Added CMD51 handling as CMD51 is a data transfer, and needs BIT_CMD_READ
and BIT_CMD_DATA_EXPECTED to be set.

Updates DwEmmcReceiveResponse to SendCommand only if IsPendingReadCommand
or IsPendingWriteCommand is true.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 59 +++
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 6d0f472..600ab01 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -45,6 +45,7 @@ DWEMMC_IDMAC_DESCRIPTOR   *gpIdmacDesc;
 EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;
 STATIC UINT32 mDwEmmcCommand;
 STATIC UINT32 mDwEmmcArgument;
+STATIC BOOLEAN mIsACmd = FALSE;
 
 EFI_STATUS
 DwEmmcReadBlockData (
@@ -321,68 +322,93 @@ DwEmmcSendCommand (
 break;
   case MMC_INDX(2):
 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
-   BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
+   BIT_CMD_SEND_INIT;
 break;
   case MMC_INDX(3):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_SEND_INIT;
 break;
+  case MMC_INDX(6):
+if(mIsACmd) {
+  Cmd = BIT_CMD_RESPONSE_EXPECT ;
+}
+else {
+  Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+BIT_CMD_READ;
+}
+break;
   case MMC_INDX(7):
 if (Argument)
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT;
 else
 Cmd = 0;
 break;
   case MMC_INDX(8):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
-   BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(9):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_LONG_RESPONSE;
 break;
   case MMC_INDX(12):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_STOP_ABORT_CMD;
 break;
   case MMC_INDX(13):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(16):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(17):
   case MMC_INDX(18):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(24):
   case MMC_INDX(25):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(30):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED;
 break;
+  case MMC_INDX(51):
+Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+   BIT_CMD_READ | BIT_CMD_WAIT_PRVDATA_COMPLETE;
+break;
   default:
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT ;
 break;
   }
 
   Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
+
+  if(MMC_INDX(55) == MMC_GET_INDX(MmcCmd))
+mIsACmd = TRUE;
+  else
+mIsACmd = FALSE;
+
+  if (!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) {
+Cmd |= BIT_CMD_CHECK_RESPONSE_CRC;
+  }
+
   if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {
 mDwEmmcCommand = Cmd;
 mDwEmmcArgument = Argument;
   } else {
+mDwEmmcCommand = Cmd;
+mDwEmmcArgument = Argument;
 Status = SendCommand (Cmd, Argument);
   }
+
   return Status;
 }
 
@@ -393,6 +419,11 @@ DwEmmcReceiveResponse (
   IN UINT32*Buffer
   )
 {
+  EFI_STATUS Status = EFI_SUCCESS;
+
+  if(IsPendingReadCommand (mDwEmmcCommand) || 
IsPendingWriteCommand(mDwEmmcCommand))
+Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
+
   if (Buffer == NULL) {
 return EFI_INVALID_PARAMETER;
   }
@@ -410,7 +441,7 @@ DwEmmcReceiveResponse (
 Buffer[2] = MmioRead32 (DWEMMC_RESP2);
 Buffer[3] = MmioRead32 (DWEMMC_RESP3);
   }
-  return EFI_SUCCESS;
+  return Status;
 }
 
 VOID
-- 
2.2.2


[edk2] [PATCH 3/4] EmbeddedPkg/DwEmmc: Fix DMA transfer length

2019-02-21 Thread tien . hock . loh
From: "Loh, Tien Hock" 

DMA should not transfer more than requested length otherwise FIFO might run
into buffer underrun and causes errors in future transfers.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 600ab01..c232309 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -496,7 +496,13 @@ PrepareDmaData (
 
   Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
   Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
-  Length = DWEMMC_BLOCK_SIZE * Blks;
+
+  if(Length < DWEMMC_BLOCK_SIZE) {
+Length = Length;
+  }
+  else {
+Length = DWEMMC_BLOCK_SIZE * Blks;
+  }
 
   for (Idx = 0; Idx < Cnt; Idx++) {
 (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |
@@ -534,11 +540,18 @@ StartDma (
   Data |= DWEMMC_CTRL_INT_EN | DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;
   MmioWrite32 (DWEMMC_CTRL, Data);
   Data = MmioRead32 (DWEMMC_BMOD);
+
   Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;
   MmioWrite32 (DWEMMC_BMOD, Data);
 
-  MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
-  MmioWrite32 (DWEMMC_BYTCNT, Length);
+  if(Length < DWEMMC_BLOCK_SIZE) {
+MmioWrite32 (DWEMMC_BLKSIZ, Length);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
+  else {
+MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
 }
 
 EFI_STATUS
-- 
2.2.2

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


[edk2] [PATCH 1/4] EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay

2019-02-21 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Existing implementation checks for error regardless of if
DWEMMC_INT_CMD_DONE is set, causing the loop check to errors out
even when it shouldn't if the MicroSecondDelay doesn't do long
enough delays. This removes MicroSecondDelay and updates the
function to check for CMD_DONE before doing any error checking.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 0437e30..6d0f472 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -290,17 +290,15 @@ SendCommand (
   ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
 DWEMMC_INT_RCRC | DWEMMC_INT_RE;
   ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
   do {
-MicroSecondDelay(500);
 Data = MmioRead32 (DWEMMC_RINTSTS);
-
-if (Data & ErrMask) {
-  return EFI_DEVICE_ERROR;
-}
-if (Data & DWEMMC_INT_DTO) { // Transfer Done
-  break;
-}
   } while (!(Data & DWEMMC_INT_CMD_DONE));
+
+  if (Data & ErrMask) {
+return EFI_DEVICE_ERROR;
+  }
+
   return EFI_SUCCESS;
 }
 
-- 
2.2.2

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


[edk2] [PATCH 1/1] SD : Continue setting up sd even if SD_HIGH_SPEED is not supported

2018-10-25 Thread tien . hock . loh
From: "Loh, Tien Hock" 

If SD doesn't support SD_HIGH_SPEED, function should still continue to
setup SD to go into 4 bits more if it is supported.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c 
b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index f661a0c..8fd5c31 100755
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -474,18 +474,17 @@ InitializeSdMmcDevice (
 
 if (!(Buffer[3] & SD_HIGH_SPEED_SUPPORTED)) {
   DEBUG ((DEBUG_ERROR, "%a : High Speed not supported by Card %r\n", 
__FUNCTION__, Status));
-  return Status;
 }
+else {
+  Speed = SD_HIGH_SPEED;
 
-Speed = SD_HIGH_SPEED;
-
-/* SD Switch, Mode:1, Group:0, Value:1 */
-CmdArg = CreateSwitchCmdArgument(1, 0, 1);
-Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
-if (EFI_ERROR (Status)) {
-  DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", 
__FUNCTION__, Status));
-   return Status;
-} else {
+  /* SD Switch, Mode:1, Group:0, Value:1 */
+  CmdArg = CreateSwitchCmdArgument(1, 0, 1);
+  Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
+  if (EFI_ERROR (Status)) {
+DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", 
__FUNCTION__, Status));
+return Status;
+  } else {
   Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, 
Buffer);
   if (EFI_ERROR (Status)) {
 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = 
%r\n", __FUNCTION__, Status));
@@ -495,6 +494,7 @@ InitializeSdMmcDevice (
   if ((Buffer[4] & SWITCH_CMD_SUCCESS_MASK) != 0x0100) {
 DEBUG((DEBUG_ERROR, "Problem switching SD card into high-speed 
mode\n"));
 return Status;
+}
   }
 }
   }
-- 
2.2.2

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


[edk2] [PATCH 4/4] EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

2018-10-24 Thread tien . hock . loh
From: "Loh, Tien Hock" 

DwEmmcReadBlockData and DwEmmcWriteBlockData needs to check for the
transfer completion before returning. This also adds error checking
to the DMA transfer.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 30 --
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index c232309..baf299d 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -563,8 +563,9 @@ DwEmmcReadBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -587,6 +588,18 @@ DwEmmcReadBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
@@ -602,8 +615,9 @@ DwEmmcWriteBlockData (
   )
 {
   EFI_STATUS  Status;
-  UINT32  DescPages, CountPerPage, Count;
+  UINT32  DescPages, CountPerPage, Count, ErrMask;
   EFI_TPL Tpl;
+  UINTN Rintsts;
 
   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 
@@ -626,6 +640,18 @@ DwEmmcWriteBlockData (
 DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, 
mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
 goto out;
   }
+
+  while(!((MmioRead32(DWEMMC_RINTSTS) & (DWEMMC_INT_DTO {
+Rintsts = MmioRead32 (DWEMMC_RINTSTS);
+  }
+  ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
+DWEMMC_INT_RCRC | DWEMMC_INT_RE | DWEMMC_INT_DCRC |
+DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
+  if (Rintsts & ErrMask) {
+Status = EFI_DEVICE_ERROR;
+goto out;
+  }
 out:
   // Restore Tpl
   gBS->RestoreTPL (Tpl);
-- 
2.2.2

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


[edk2] [PATCH 2/4] EmbeddedPkg/DwEmmc: Fix SendCommand parameters

2018-10-24 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Only send BIT_CMD_CHECK_RESPONSE_CRC if MMC commands needs it.

Fixes parameters to ACMD6 where if CMD is application command, ie. CMD55 is
sent before ACMD6, to do response instead of data transfer.

Added CMD51 handling as CMD51 is a data transfer, and needs BIT_CMD_READ
and BIT_CMD_DATA_EXPECTED to be set.

Updates DwEmmcReceiveResponse to SendCommand only if IsPendingReadCommand
or IsPendingWriteCommand is true.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 59 +++
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 6d0f472..600ab01 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -45,6 +45,7 @@ DWEMMC_IDMAC_DESCRIPTOR   *gpIdmacDesc;
 EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;
 STATIC UINT32 mDwEmmcCommand;
 STATIC UINT32 mDwEmmcArgument;
+STATIC BOOLEAN mIsACmd = FALSE;
 
 EFI_STATUS
 DwEmmcReadBlockData (
@@ -321,68 +322,93 @@ DwEmmcSendCommand (
 break;
   case MMC_INDX(2):
 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
-   BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
+   BIT_CMD_SEND_INIT;
 break;
   case MMC_INDX(3):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_SEND_INIT;
 break;
+  case MMC_INDX(6):
+if(mIsACmd) {
+  Cmd = BIT_CMD_RESPONSE_EXPECT ;
+}
+else {
+  Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+BIT_CMD_READ;
+}
+break;
   case MMC_INDX(7):
 if (Argument)
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT;
 else
 Cmd = 0;
 break;
   case MMC_INDX(8):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
-   BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(9):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_LONG_RESPONSE;
 break;
   case MMC_INDX(12):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_STOP_ABORT_CMD;
 break;
   case MMC_INDX(13):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(16):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(17):
   case MMC_INDX(18):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(24):
   case MMC_INDX(25):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
BIT_CMD_WAIT_PRVDATA_COMPLETE;
 break;
   case MMC_INDX(30):
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+Cmd = BIT_CMD_RESPONSE_EXPECT  |
BIT_CMD_DATA_EXPECTED;
 break;
+  case MMC_INDX(51):
+Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_DATA_EXPECTED |
+   BIT_CMD_READ | BIT_CMD_WAIT_PRVDATA_COMPLETE;
+break;
   default:
-Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+Cmd = BIT_CMD_RESPONSE_EXPECT ;
 break;
   }
 
   Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
+
+  if(MMC_INDX(55) == MMC_GET_INDX(MmcCmd))
+mIsACmd = TRUE;
+  else
+mIsACmd = FALSE;
+
+  if (!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) {
+Cmd |= BIT_CMD_CHECK_RESPONSE_CRC;
+  }
+
   if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {
 mDwEmmcCommand = Cmd;
 mDwEmmcArgument = Argument;
   } else {
+mDwEmmcCommand = Cmd;
+mDwEmmcArgument = Argument;
 Status = SendCommand (Cmd, Argument);
   }
+
   return Status;
 }
 
@@ -393,6 +419,11 @@ DwEmmcReceiveResponse (
   IN UINT32*Buffer
   )
 {
+  EFI_STATUS Status = EFI_SUCCESS;
+
+  if(IsPendingReadCommand (mDwEmmcCommand) || 
IsPendingWriteCommand(mDwEmmcCommand))
+Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
+
   if (Buffer == NULL) {
 return EFI_INVALID_PARAMETER;
   }
@@ -410,7 +441,7 @@ DwEmmcReceiveResponse (
 Buffer[2] = MmioRead32 (DWEMMC_RESP2);
 Buffer[3] = MmioRead32 (DWEMMC_RESP3);
   }
-  return EFI_SUCCESS;
+  return Status;
 }
 
 VOID
-- 
2.2.2


[edk2] [PATCH 3/4] EmbeddedPkg/DwEmmc: Fix DMA transfer length

2018-10-24 Thread tien . hock . loh
From: "Loh, Tien Hock" 

DMA should not transfer more than requested length otherwise FIFO might run
into buffer underrun and causes errors in future transfers.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 600ab01..c232309 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -496,7 +496,13 @@ PrepareDmaData (
 
   Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
   Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
-  Length = DWEMMC_BLOCK_SIZE * Blks;
+
+  if(Length < DWEMMC_BLOCK_SIZE) {
+Length = Length;
+  }
+  else {
+Length = DWEMMC_BLOCK_SIZE * Blks;
+  }
 
   for (Idx = 0; Idx < Cnt; Idx++) {
 (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |
@@ -534,11 +540,18 @@ StartDma (
   Data |= DWEMMC_CTRL_INT_EN | DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;
   MmioWrite32 (DWEMMC_CTRL, Data);
   Data = MmioRead32 (DWEMMC_BMOD);
+
   Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;
   MmioWrite32 (DWEMMC_BMOD, Data);
 
-  MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
-  MmioWrite32 (DWEMMC_BYTCNT, Length);
+  if(Length < DWEMMC_BLOCK_SIZE) {
+MmioWrite32 (DWEMMC_BLKSIZ, Length);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
+  else {
+MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
+MmioWrite32 (DWEMMC_BYTCNT, Length);
+  }
 }
 
 EFI_STATUS
-- 
2.2.2

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


[edk2] [PATCH 0/4] EmbeddedPkg/DwEmmc: Fix bugs causing DwEmmc to fail to initialize

2018-10-24 Thread tien . hock . loh
From: Loh Tien Hock 

This patch series fixes bugs with DwEmmc driver, namely:
* Added CMD6 handling
* Fixed workaround querying SendCommand using delays
* Fix DMA transfer length causing buffer underrun in FIFO
* Check DMA completion before returning from SendCommand

Loh, Tien Hock (4):
  EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay
  EmbeddedPkg/DwEmmc: Fix SendCommand parameters
  EmbeddedPkg/DwEmmc: Fix DMA transfer length
  EmbeddedPkg/DwEmmc: Check DMA completion in SendCommand

 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 122 +++---
 1 file changed, 95 insertions(+), 27 deletions(-)

-- 
2.2.2

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


[edk2] [PATCH 1/4] EmbeddedPkg/DwEmmc: Remove unnecessary MicroSecondDelay

2018-10-24 Thread tien . hock . loh
From: "Loh, Tien Hock" 

Existing implementation checks for error regardless of if
DWEMMC_INT_CMD_DONE is set, causing the loop check to errors out
even when it shouldn't if the MicroSecondDelay doesn't do long
enough delays. This removes MicroSecondDelay and updates the
function to check for CMD_DONE before doing any error checking.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Loh Tien Hock 
---
 EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c 
b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 0437e30..6d0f472 100644
--- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -290,17 +290,15 @@ SendCommand (
   ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
 DWEMMC_INT_RCRC | DWEMMC_INT_RE;
   ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;
+
   do {
-MicroSecondDelay(500);
 Data = MmioRead32 (DWEMMC_RINTSTS);
-
-if (Data & ErrMask) {
-  return EFI_DEVICE_ERROR;
-}
-if (Data & DWEMMC_INT_DTO) { // Transfer Done
-  break;
-}
   } while (!(Data & DWEMMC_INT_CMD_DONE));
+
+  if (Data & ErrMask) {
+return EFI_DEVICE_ERROR;
+  }
+
   return EFI_SUCCESS;
 }
 
-- 
2.2.2

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