]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/SdMmcPciHcDxe: Read response on command completion
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHci.c
index d6294eb4c88a15d126f30eeeeda4711661618ca4..1fa6823cbb18b3963e38a7470475723831fde9c7 100644 (file)
@@ -1712,6 +1712,7 @@ SdMmcPrintTrb (
   DEBUG ((DebugLevel, "AdmaLengthMode: %d\n", Trb->AdmaLengthMode));\r
   DEBUG ((DebugLevel, "Event: %p\n", Trb->Event));\r
   DEBUG ((DebugLevel, "Started: %d\n", Trb->Started));\r
+  DEBUG ((DebugLevel, "CommandComplete: %d\n", Trb->CommandComplete));\r
   DEBUG ((DebugLevel, "Timeout: %ld\n", Trb->Timeout));\r
   DEBUG ((DebugLevel, "Retries: %d\n", Trb->Retries));\r
   DEBUG ((DebugLevel, "Adma32Desc: %p\n", Trb->Adma32Desc));\r
@@ -1762,6 +1763,7 @@ SdMmcCreateTrb (
   Trb->Packet    = Packet;\r
   Trb->Event     = Event;\r
   Trb->Started   = FALSE;\r
+  Trb->CommandComplete = FALSE;\r
   Trb->Timeout   = Packet->Timeout;\r
   Trb->Retries   = SD_MMC_TRB_RETRIES;\r
   Trb->Private   = Private;\r
@@ -2352,6 +2354,99 @@ SdMmcCheckAndRecoverErrors (
   return ErrorStatus;\r
 }\r
 \r
+/**\r
+  Reads the response data into the TRB buffer.\r
+  This function assumes that caller made sure that\r
+  command has completed.\r
+\r
+  @param[in] Private  A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb      The pointer to the SD_MMC_HC_TRB instance.\r
+\r
+  @retval EFI_SUCCESS  Response read successfully.\r
+  @retval Others       Failed to get response.\r
+**/\r
+EFI_STATUS\r
+SdMmcGetResponse (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb\r
+  )\r
+{\r
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  *Packet;\r
+  UINT8                                Index;\r
+  UINT32                               Response[4];\r
+  EFI_STATUS                           Status;\r
+\r
+  Packet = Trb->Packet;\r
+\r
+  if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeBc) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_RESPONSE + Index * 4,\r
+               TRUE,\r
+               sizeof (UINT32),\r
+               &Response[Index]\r
+               );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+  CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Checks if the command completed. If the command\r
+  completed it gets the response and records the\r
+  command completion in the TRB.\r
+\r
+  @param[in] Private    A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb        The pointer to the SD_MMC_HC_TRB instance.\r
+  @param[in] IntStatus  Snapshot of the normal interrupt status register.\r
+\r
+  @retval EFI_SUCCESS   Command completed successfully.\r
+  @retval EFI_NOT_READY Command completion still pending.\r
+  @retval Others        Command failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcCheckCommandComplete (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb,\r
+  IN UINT16                  IntStatus\r
+  )\r
+{\r
+  UINT16      Data16;\r
+  EFI_STATUS  Status;\r
+\r
+  if ((IntStatus & BIT0) != 0) {\r
+    Data16 = BIT0;\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_NOR_INT_STS,\r
+               FALSE,\r
+               sizeof (Data16),\r
+               &Data16\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Status = SdMmcGetResponse (Private, Trb);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Trb->CommandComplete = TRUE;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_READY;\r
+}\r
+\r
 /**\r
   Check the TRB execution result.\r
 \r
@@ -2372,9 +2467,7 @@ SdMmcCheckTrbResult (
   EFI_STATUS                          Status;\r
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
   UINT16                              IntStatus;\r
-  UINT32                              Response[4];\r
   UINT64                              SdmaAddr;\r
-  UINT8                               Index;\r
   UINT32                              PioLength;\r
 \r
   Packet  = Trb->Packet;\r
@@ -2402,6 +2495,54 @@ SdMmcCheckTrbResult (
     goto Done;\r
   }\r
 \r
+  //\r
+  // Tuning commands are the only ones that do not generate command\r
+  // complete interrupt. Process them here before entering the code\r
+  // that waits for command completion.\r
+  //\r
+  if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
+       (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
+      ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
+       (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
+    //\r
+    // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
+    // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
+    // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
+    //\r
+    if ((IntStatus & BIT5) == BIT5) {\r
+      //\r
+      // Clear Buffer Read Ready interrupt at first.\r
+      //\r
+      IntStatus = BIT5;\r
+      SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
+      //\r
+      // Read data out from Buffer Port register\r
+      //\r
+      for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
+        SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
+      }\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  if (!Trb->CommandComplete) {\r
+    Status = SdMmcCheckCommandComplete (Private, Trb, IntStatus);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    } else {\r
+      //\r
+      // If the command doesn't require data transfer skip the transfer\r
+      // complete checking.\r
+      //\r
+      if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
+          (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
+          (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
   //\r
   // Check Transfer Complete bit is set or not.\r
   //\r
@@ -2459,65 +2600,9 @@ SdMmcCheckTrbResult (
     Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
   }\r
 \r
-  if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
-      (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
-      (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
-    if ((IntStatus & BIT0) == BIT0) {\r
-      Status = EFI_SUCCESS;\r
-      goto Done;\r
-    }\r
-  }\r
-\r
-  if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
-       (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
-      ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
-       (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
-    //\r
-    // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
-    // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
-    // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
-    //\r
-    if ((IntStatus & BIT5) == BIT5) {\r
-      //\r
-      // Clear Buffer Read Ready interrupt at first.\r
-      //\r
-      IntStatus = BIT5;\r
-      SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
-      //\r
-      // Read data out from Buffer Port register\r
-      //\r
-      for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
-        SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
-      }\r
-      Status = EFI_SUCCESS;\r
-      goto Done;\r
-    }\r
-  }\r
 \r
   Status = EFI_NOT_READY;\r
 Done:\r
-  //\r
-  // Get response data when the cmd is executed successfully.\r
-  //\r
-  if (!EFI_ERROR (Status)) {\r
-    if (Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeBc) {\r
-      for (Index = 0; Index < 4; Index++) {\r
-        Status = SdMmcHcRwMmio (\r
-                   Private->PciIo,\r
-                   Trb->Slot,\r
-                   SD_MMC_HC_RESPONSE + Index * 4,\r
-                   TRUE,\r
-                   sizeof (UINT32),\r
-                   &Response[Index]\r
-                   );\r
-        if (EFI_ERROR (Status)) {\r
-          SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
-          return Status;\r
-        }\r
-      }\r
-      CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
-    }\r
-  }\r
 \r
   if (Status != EFI_NOT_READY) {\r
     SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r