From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.65, mailfrom: tien.hock.loh@intel.com) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by groups.io with SMTP; Wed, 01 May 2019 20:37:25 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 May 2019 20:37:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,420,1549958400"; d="scan'208";a="139175609" Received: from pg-nx11.altera.com ([10.104.4.26]) by orsmga008.jf.intel.com with ESMTP; 01 May 2019 20:37:23 -0700 From: "Loh, Tien Hock" To: devel@edk2.groups.io, thloh85@gmail.com Cc: "Tien Hock, Loh" , Leif Lindholm , Ard Biesheuvel Subject: [PATCH 1/1] EmbeddedPkg: Fix DwEmmc driver bugs Date: Thu, 2 May 2019 11:37:19 +0800 Message-Id: <1556768239-43239-1-git-send-email-tien.hock.loh@intel.com> X-Mailer: git-send-email 2.2.2 From: "Tien Hock, Loh" This fixes some issues with DwEmmc when using with SDMMC card: - clear CTYPE when controller initializes - change SendCommand polling mode to remove unnecessary delay - Add CMD6 support for SD support - For pending read/write command, send when DwEmmcReceiveResponse is called so that we can properly error check the response - Fix bug on reading block size less than DWEMMC_BLOCK_SIZE - Wait for DwEmmcReadBlockData and DwEmmacWriteBlockData to complete before returning the function Signed-off-by: "Tien Hock, Loh" Cc: Leif Lindholm Cc: Ard Biesheuvel --- EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c | 108 +++++++++++++++++++---- EmbeddedPkg/Include/Protocol/MmcHost.h | 1 + EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 2 + 3 files changed, 92 insertions(+), 19 deletions(-) diff --git a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c index 68c523a..92b5176 100644 --- a/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c +++ b/EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c @@ -39,6 +39,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 ( @@ -205,6 +206,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 { @@ -284,17 +286,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; } @@ -323,6 +323,15 @@ DwEmmcSendCommand ( Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 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; @@ -330,9 +339,12 @@ DwEmmcSendCommand ( Cmd = 0; break; case MMC_INDX(8): - Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | - BIT_CMD_WAIT_PRVDATA_COMPLETE; + if (!This->IsEmmc) + Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | + BIT_CMD_WAIT_PRVDATA_COMPLETE ; + else + Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | + BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_READ | BIT_CMD_DATA_EXPECTED; break; case MMC_INDX(9): Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | @@ -364,21 +376,38 @@ DwEmmcSendCommand ( 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; } @@ -389,6 +418,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; } @@ -406,7 +440,7 @@ DwEmmcReceiveResponse ( Buffer[2] = MmioRead32 (DWEMMC_RESP2); Buffer[3] = MmioRead32 (DWEMMC_RESP3); } - return EFI_SUCCESS; + return Status; } VOID @@ -461,7 +495,10 @@ 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 = DWEMMC_BLOCK_SIZE * Blks; + } for (Idx = 0; Idx < Cnt; Idx++) { (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH | @@ -499,11 +536,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 @@ -515,8 +559,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); @@ -539,6 +584,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); @@ -554,8 +611,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); @@ -578,6 +636,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); diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h index 9e07082..ae8ea5d 100644 --- a/EmbeddedPkg/Include/Protocol/MmcHost.h +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h @@ -169,6 +169,7 @@ struct _EFI_MMC_HOST_PROTOCOL { MMC_SETIOS SetIos; MMC_ISMULTIBLOCK IsMultiBlock; + BOOLEAN IsEmmc; }; #define MMC_HOST_PROTOCOL_REVISION 0x00010002 // 1.2 diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c index 4dc0be1..fa1eda2 100755 --- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c +++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c @@ -770,8 +770,10 @@ InitializeMmcDevice ( } if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) { + MmcHostInstance->MmcHost->IsEmmc = FALSE; Status = InitializeSdMmcDevice (MmcHostInstance); } else { + MmcHostInstance->MmcHost->IsEmmc = TRUE; Status = InitializeEmmcDevice (MmcHostInstance); } if (EFI_ERROR (Status)) { -- 2.2.2