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