ArmPkg/MmcDxe: Fix some returned conditions for MMC/SD commands

Additional support for some states covered by the specifications.

 



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11465 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin
2011-03-31 11:16:02 +00:00
parent 6102636abc
commit a1ab9143e2
2 changed files with 116 additions and 58 deletions

View File

@ -16,6 +16,8 @@
#ifndef __MMC_H #ifndef __MMC_H
#define __MMC_H #define __MMC_H
#include <Uefi.h>
#include <Protocol/DiskIo.h> #include <Protocol/DiskIo.h>
#include <Protocol/BlockIo.h> #include <Protocol/BlockIo.h>
#include <Protocol/DevicePath.h> #include <Protocol/DevicePath.h>

View File

@ -22,7 +22,8 @@
// Untested ... // Untested ...
//#define USE_STREAM //#define USE_STREAM
#define MAX_RETRY_COUNT 200 #define MAX_RETRY_COUNT 1000
#define CMD_RETRY_COUNT 20
EFI_STATUS EFI_STATUS
MmcNotifyState ( MmcNotifyState (
@ -107,19 +108,53 @@ VOID PrintRCA(UINT32 rca) {
} }
VOID PrintResponseR1(UINT32 response) { VOID PrintResponseR1(UINT32 response) {
DEBUG((EFI_D_ERROR, "Response: 0x%X\n",response)); DEBUG((EFI_D_INFO, "Response: 0x%X\n",response));
if (response & (1 << 8)) DEBUG((EFI_D_ERROR, "\t- READY_FOR_DATA\n")); if (response & (1 << 8)) DEBUG((EFI_D_INFO, "\t- READY_FOR_DATA\n"));
if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_ERROR, "\t- State: Idle\n")); if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_INFO, "\t- State: Idle\n"));
else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_ERROR, "\t- State: Ready\n")); else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_INFO, "\t- State: Ready\n"));
else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_ERROR, "\t- State: Ident\n")); else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_INFO, "\t- State: Ident\n"));
else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_ERROR, "\t- State: StandBy\n")); else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_INFO, "\t- State: StandBy\n"));
else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_ERROR, "\t- State: Tran\n")); else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_INFO, "\t- State: Tran\n"));
else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_ERROR, "\t- State: Data\n")); else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_INFO, "\t- State: Data\n"));
else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_ERROR, "\t- State: Rcv\n")); else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_INFO, "\t- State: Rcv\n"));
else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_ERROR, "\t- State: Prg\n")); else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_INFO, "\t- State: Prg\n"));
else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_ERROR, "\t- State: Dis\n")); else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_INFO, "\t- State: Dis\n"));
else DEBUG((EFI_D_ERROR, "\t- State: Reserved\n")); else DEBUG((EFI_D_INFO, "\t- State: Reserved\n"));
}
EFI_STATUS
EFIAPI
MmcGetCardStatus(
MMC_HOST_INSTANCE *MmcHostInstance
){
EFI_STATUS Status=EFI_SUCCESS;
UINT32 Response[4];
UINTN CmdArg;
EFI_MMC_HOST_PROTOCOL *MmcHost;
MmcHost = MmcHostInstance->MmcHost;
CmdArg = 0;
if (MmcHost == NULL) {
return EFI_INVALID_PARAMETER;
}
if(MmcHostInstance->State != MmcHwInitializationState){
//Get the Status of the card.
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));
ASSERT(0);
return Status;
}
//Read Response
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
PrintResponseR1(Response[0]);
}
return Status;
} }
EFI_STATUS EFI_STATUS
@ -129,10 +164,11 @@ MmcIdentificationMode (
) { ) {
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Response[4]; UINT32 Response[4];
UINTN timer; UINTN Timeout;
UINTN CmdArg; UINTN CmdArg;
BOOLEAN bHCS; BOOLEAN bHCS;
EFI_MMC_HOST_PROTOCOL *MmcHost; EFI_MMC_HOST_PROTOCOL *MmcHost;
UINTN CmdRetryCnt;
MmcHost = MmcHostInstance->MmcHost; MmcHost = MmcHostInstance->MmcHost;
CmdArg = 0; CmdArg = 0;
@ -180,13 +216,18 @@ MmcIdentificationMode (
bHCS = TRUE; bHCS = TRUE;
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response);
PrintResponseR1(Response[0]); PrintResponseR1(Response[0]);
//check if it is valid response
if(Response[0] != CmdArg){
DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
return EFI_UNSUPPORTED;
}
} else { } else {
DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n")); DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
} }
// We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1) // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)
timer = MAX_RETRY_COUNT; Timeout = MAX_RETRY_COUNT;
while (timer > 0) { while (Timeout > 0) {
// SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
Status = MmcHost->SendCommand(MMC_CMD55, 0); Status = MmcHost->SendCommand(MMC_CMD55, 0);
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
@ -203,38 +244,39 @@ MmcIdentificationMode (
CmdArg |= BIT30; CmdArg |= BIT30;
} }
Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg); Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg);
if (EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(ACMD41): Error\n")); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
return Status; ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
} }
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
} else { } else {
DEBUG ((EFI_D_INFO, "Card should be MMC\n")); DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
MmcHostInstance->CardInfo.CardType = MMC_CARD; MmcHostInstance->CardInfo.CardType = MMC_CARD;
Status = MmcHost->SendCommand(MMC_CMD1, 0x800000); Status = MmcHost->SendCommand(MMC_CMD1, 0x800000);
if (EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(ACMD41): Error\n")); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
return Status; ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
} }
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
} }
if (MmcHostInstance->CardInfo.OCRData.Busy == 0) { if (!EFI_ERROR(Status)) {
MicroSecondDelay(10*1000); if (MmcHostInstance->CardInfo.OCRData.Busy == 0) {
timer--; MicroSecondDelay(1);
Timeout--;
} else {
if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
}
break; // The MMC/SD card is ready. Continue the Identification Mode
}
} else { } else {
if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) { MicroSecondDelay(1);
MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH; Timeout--;
DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
}
break; // The MMC/SD card is ready. Continue the Identification Mode
} }
} }
if (timer == 0) { if (Timeout == 0) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n")); DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
ASSERT(0); ASSERT(0);
return EFI_NO_MEDIA; return EFI_NO_MEDIA;
@ -264,13 +306,17 @@ MmcIdentificationMode (
} }
CmdArg = 0; CmdArg = 0;
Status = MmcHost->SendCommand(MMC_CMD3, CmdArg); CmdRetryCnt = CMD_RETRY_COUNT;
if (EFI_ERROR(Status)) { //Keep sending CMD 3 until card enters to Standby mode and Card status is ready
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n")); while((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_STDBY) && CmdRetryCnt-- ){
return Status; Status = MmcHost->SendCommand(MMC_CMD3, CmdArg);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
return Status;
}
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);
PrintRCA(Response[0]);
} }
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);
PrintRCA(Response[0]);
// For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
if (MmcHostInstance->CardInfo.CardType != MMC_CARD) { if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
@ -325,7 +371,7 @@ EFI_STATUS MmcIoBlocks (
UINT32 Response[4]; UINT32 Response[4];
EFI_STATUS Status; EFI_STATUS Status;
UINTN CardSize, NumBlocks, BlockSize, CmdArg; UINTN CardSize, NumBlocks, BlockSize, CmdArg;
UINTN timer; UINTN Timeout;
UINTN Cmd; UINTN Cmd;
MMC_HOST_INSTANCE *MmcHostInstance; MMC_HOST_INSTANCE *MmcHostInstance;
EFI_MMC_HOST_PROTOCOL *MmcHost; EFI_MMC_HOST_PROTOCOL *MmcHost;
@ -354,17 +400,18 @@ EFI_STATUS MmcIoBlocks (
if (MmcHostInstance->State == MmcHwInitializationState) { if (MmcHostInstance->State == MmcHwInitializationState) {
MmcIdentificationMode (MmcHostInstance); MmcIdentificationMode (MmcHostInstance);
//Send a command to get Card specific data
CmdArg = MmcHostInstance->CardInfo.RCA << 16; CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Status = MmcHost->SendCommand(MMC_CMD9, CmdArg); Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error\n")); DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));
ASSERT(0); ASSERT(0);
return Status; return Status;
} }
//Read Response
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);
PrintCSD(Response); PrintCSD(Response);
if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) { if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
ASSERT(0); //TODO: Implementation needed ASSERT(0); //TODO: Implementation needed
CardSize = MMC_CSD_GET_DEVICESIZE(Response); CardSize = MMC_CSD_GET_DEVICESIZE(Response);
@ -391,11 +438,11 @@ EFI_STATUS MmcIoBlocks (
CmdArg = MmcHostInstance->CardInfo.RCA << 16; CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Status = MmcHost->SendCommand(MMC_CMD7, CmdArg); Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error\n")); DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));
ASSERT(0); ASSERT(0);
return Status; return Status;
} }
Status = MmcNotifyState (MmcHostInstance, MmcTransferState); Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n")); DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));
@ -424,11 +471,22 @@ EFI_STATUS MmcIoBlocks (
BytesRemainingToBeTransfered = BufferSize; BytesRemainingToBeTransfered = BufferSize;
while (BytesRemainingToBeTransfered > 0) { while (BytesRemainingToBeTransfered > 0) {
//Check if the Card is in Ready status
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Response[0] = 0;
Timeout = 20;
while((Response[0] & (1 << 8)) && Timeout-- ){
Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);
if (!EFI_ERROR(Status)){
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
}
}
// Set Block Length // Set Block Length
Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize); Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d\n",This->Media->BlockSize)); DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d and Error = %r\n",This->Media->BlockSize, Status));
ASSERT(0);
return Status; return Status;
} }
@ -459,8 +517,7 @@ EFI_STATUS MmcIoBlocks (
} }
Status = MmcHost->SendCommand(Cmd, CmdArg); Status = MmcHost->SendCommand(Cmd, CmdArg);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error\n",Cmd)); DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error %r\n",Cmd, Status));
ASSERT(0);
return Status; return Status;
} }
@ -469,8 +526,7 @@ EFI_STATUS MmcIoBlocks (
// Read one block of Data // Read one block of Data
Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer); Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data")); DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data and Status = %r\n", Status));
ASSERT(0);
return Status; return Status;
} }
#else #else
@ -487,8 +543,7 @@ EFI_STATUS MmcIoBlocks (
// Write one block of Data // Write one block of Data
Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer); Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data")); DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data and Status = %r\n", Status));
ASSERT(0);
return Status; return Status;
} }
#else #else
@ -502,12 +557,13 @@ EFI_STATUS MmcIoBlocks (
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response);
// Command 13 - Read status and wait for programming to complete (return to tran) // Command 13 - Read status and wait for programming to complete (return to tran)
timer = MMCI0_TIMEOUT; Timeout = MMCI0_TIMEOUT;
while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && timer) { CmdArg = MmcHostInstance->CardInfo.RCA << 16;
MmcHost->SendCommand(MMC_CMD13, 0); while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && Timeout) {
MmcHost->SendCommand(MMC_CMD13, CmdArg);
MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response); MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
NanoSecondDelay(100); NanoSecondDelay(100);
timer--; Timeout--;
} }
Status = MmcNotifyState (MmcHostInstance, MmcTransferState); Status = MmcNotifyState (MmcHostInstance, MmcTransferState);