]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/SdMmcPciHcDxe: Using PIO rather than DMA for clock tuning
authorFeng Tian <feng.tian@intel.com>
Fri, 29 Apr 2016 08:02:50 +0000 (16:02 +0800)
committerFeng Tian <feng.tian@intel.com>
Fri, 6 May 2016 08:09:59 +0000 (16:09 +0800)
The original code is using ADMA mode to do clock tuning procedure. It
may have problem on some SD/MMC host controllers as there is no way to
know when to send next tuning cmd.

Update it to PIO mode to strictly follow SD Host Controller Simplified
Specification 3.0 Figure 2-29. By this way, if the Buffer Read Ready
interrupt is set, we could know it's ok to send the next clock tuning
cmd.

Cc: Wu, Hao A <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c

index 72af1e7a1b1dbc2c40b7512f96e83616a4132d19..8978182f9e35cbeb77fe174cafaa6f2f565d4f36 100644 (file)
@@ -1265,48 +1265,53 @@ SdMmcCreateTrb (
     goto Error;\r
   }\r
 \r
-  if (Trb->Read) {\r
-    Flag = EfiPciIoOperationBusMasterWrite;\r
+  if (Trb->DataLen < Trb->BlockSize) {\r
+    Trb->BlockSize = (UINT16)Trb->DataLen;\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
+    Trb->Mode = SdMmcPioMode;\r
   } else {\r
-    Flag = EfiPciIoOperationBusMasterRead;\r
-  }\r
-\r
-  PciIo = Private->PciIo;\r
-  if (Trb->DataLen != 0) {\r
-    MapLength = Trb->DataLen;\r
-    Status = PciIo->Map (\r
-                      PciIo,\r
-                      Flag,\r
-                      Trb->Data,\r
-                      &MapLength,\r
-                      &Trb->DataPhy,\r
-                      &Trb->DataMap\r
-                      );\r
-    if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
-      Status = EFI_BAD_BUFFER_SIZE;\r
-      goto Error;\r
+    if (Trb->Read) {\r
+      Flag = EfiPciIoOperationBusMasterWrite;\r
+    } else {\r
+      Flag = EfiPciIoOperationBusMasterRead;\r
     }\r
-  }\r
 \r
-  if ((Trb->DataLen % Trb->BlockSize) != 0) {\r
-    if (Trb->DataLen < Trb->BlockSize) {\r
-      Trb->BlockSize = (UINT16)Trb->DataLen;\r
+    PciIo = Private->PciIo;\r
+    if (Trb->DataLen != 0) {\r
+      MapLength = Trb->DataLen;\r
+      Status = PciIo->Map (\r
+                        PciIo,\r
+                        Flag,\r
+                        Trb->Data,\r
+                        &MapLength,\r
+                        &Trb->DataPhy,\r
+                        &Trb->DataMap\r
+                        );\r
+      if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
+        Status = EFI_BAD_BUFFER_SIZE;\r
+        goto Error;\r
+      }\r
     }\r
-  }\r
 \r
-  if (Trb->DataLen == 0) {\r
-    Trb->Mode = SdMmcNoData;\r
-  } else if (Private->Capability[Slot].Adma2 != 0) {\r
-    Trb->Mode = SdMmcAdmaMode;\r
-    Status = BuildAdmaDescTable (Trb);\r
-    if (EFI_ERROR (Status)) {\r
-      PciIo->Unmap (PciIo, Trb->DataMap);\r
-      goto Error;\r
+    if (Trb->DataLen == 0) {\r
+      Trb->Mode = SdMmcNoData;\r
+    } else if (Private->Capability[Slot].Adma2 != 0) {\r
+      Trb->Mode = SdMmcAdmaMode;\r
+      Status = BuildAdmaDescTable (Trb);\r
+      if (EFI_ERROR (Status)) {\r
+        PciIo->Unmap (PciIo, Trb->DataMap);\r
+        goto Error;\r
+      }\r
+    } else if (Private->Capability[Slot].Sdma != 0) {\r
+      Trb->Mode = SdMmcSdmaMode;\r
+    } else {\r
+      Trb->Mode = SdMmcPioMode;\r
     }\r
-  } else if (Private->Capability[Slot].Sdma != 0) {\r
-    Trb->Mode = SdMmcSdmaMode;\r
-  } else {\r
-    Trb->Mode = SdMmcPioMode;\r
   }\r
 \r
   if (Event != NULL) {\r
@@ -1392,15 +1397,6 @@ SdMmcCheckTrbEnv (
     // the Present State register to be 0\r
     //\r
     PresentState = BIT0 | BIT1;\r
-    //\r
-    // For Send Tuning Block cmd, just wait for Command Inhibit (CMD) to be 0\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
-      PresentState = BIT0;\r
-    }\r
   } else {\r
     //\r
     // Wait Command Inhibit (CMD) in the Present State register\r
@@ -1565,7 +1561,13 @@ SdMmcExecTrb (
     return Status;\r
   }\r
 \r
-  BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  BlkCount = 0;\r
+  if (Trb->Mode != SdMmcNoData) {\r
+    //\r
+    // Calcuate Block Count.\r
+    //\r
+    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  }\r
   Status   = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -1585,7 +1587,7 @@ SdMmcExecTrb (
     if (Trb->Read) {\r
       TransMode |= BIT4;\r
     }\r
-    if (BlkCount != 0) {\r
+    if (BlkCount > 1) {\r
       TransMode |= BIT5 | BIT1;\r
     }\r
     //\r
@@ -1665,6 +1667,7 @@ SdMmcCheckTrbResult (
   UINT32                              SdmaAddr;\r
   UINT8                               Index;\r
   UINT8                               SwReset;\r
+  UINT32                              PioLength;\r
 \r
   SwReset = 0;\r
   Packet  = Trb->Packet;\r
@@ -1814,12 +1817,25 @@ SdMmcCheckTrbResult (
       ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
        (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
     //\r
-    // While performing tuning procedure (Execute Tuning is set to 1),\r
-    // Transfer Completeis not set to 1\r
-    // Refer to SD Host Controller Simplified Specification 3.0 table 2-23 for details.\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
-    Status = EFI_SUCCESS;\r
-    goto Done;\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
index 569a86a6e14af2652d183ab76157db5973acb7a2..3ffc4779d948f0a111798f4121e670381b2dfeb0 100644 (file)
@@ -1032,26 +1032,27 @@ EmmcPeimCreateTrb (
     goto Error;\r
   }\r
 \r
-  if ((Trb->DataLen % Trb->BlockSize) != 0) {\r
-    if (Trb->DataLen < Trb->BlockSize) {\r
-      Trb->BlockSize = (UINT16)Trb->DataLen;\r
-    }\r
+  if (Trb->DataLen < Trb->BlockSize) {\r
+    Trb->BlockSize = (UINT16)Trb->DataLen;\r
   }\r
 \r
-  if (Trb->DataLen == 0) {\r
-    Trb->Mode = EmmcNoData;\r
-  } else if (Capability.Adma2 != 0) {\r
-    Trb->Mode = EmmcAdmaMode;\r
-    Status = BuildAdmaDescTable (Trb);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-  } else if (Capability.Sdma != 0) {\r
-    Trb->Mode = EmmcSdmaMode;\r
-  } else {\r
+  if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {\r
     Trb->Mode = EmmcPioMode;\r
+  } else {\r
+    if (Trb->DataLen == 0) {\r
+      Trb->Mode = EmmcNoData;\r
+    } else if (Capability.Adma2 != 0) {\r
+      Trb->Mode = EmmcAdmaMode;\r
+      Status = BuildAdmaDescTable (Trb);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Error;\r
+      }\r
+    } else if (Capability.Sdma != 0) {\r
+      Trb->Mode = EmmcSdmaMode;\r
+    } else {\r
+      Trb->Mode = EmmcPioMode;\r
+    }\r
   }\r
-\r
   return Trb;\r
 \r
 Error:\r
@@ -1111,9 +1112,6 @@ EmmcPeimCheckTrbEnv (
     // the Present State register to be 0\r
     //\r
     PresentState = BIT0 | BIT1;\r
-    if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {\r
-      PresentState = BIT0;\r
-    }\r
   } else {\r
     //\r
     // Wait Command Inhibit (CMD) in the Present State register\r
@@ -1273,7 +1271,14 @@ EmmcPeimExecTrb (
     return Status;\r
   }\r
 \r
-  BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  BlkCount = 0;\r
+  if (Trb->Mode != EmmcNoData) {\r
+    //\r
+    // Calcuate Block Count.\r
+    //\r
+    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  }\r
+\r
   Status   = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -1293,7 +1298,7 @@ EmmcPeimExecTrb (
     if (Trb->Read) {\r
       TransMode |= BIT4;\r
     }\r
-    if (BlkCount != 0) {\r
+    if (BlkCount > 1) {\r
       TransMode |= BIT5 | BIT1;\r
     }\r
   }\r
@@ -1365,6 +1370,7 @@ EmmcPeimCheckTrbResult (
   UINT32                              SdmaAddr;\r
   UINT8                               Index;\r
   UINT8                               SwReset;\r
+  UINT32                              PioLength;\r
 \r
   SwReset = 0;\r
   Packet  = Trb->Packet;\r
@@ -1497,8 +1503,26 @@ EmmcPeimCheckTrbResult (
   }\r
 \r
   if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {\r
-    Status = EFI_SUCCESS;\r
-    goto Done;\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
+      EmmcPeimHcRwMmio (Bar + EMMC_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
+        EmmcPeimHcRwMmio (Bar + EMMC_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
index 48e4ae68caa7d9bf2d0e29d45149ecac874a3cd3..3f327f8b393552f0cdb1545a784de22c71306d79 100644 (file)
@@ -1032,26 +1032,27 @@ SdPeimCreateTrb (
     goto Error;\r
   }\r
 \r
-  if ((Trb->DataLen % Trb->BlockSize) != 0) {\r
-    if (Trb->DataLen < Trb->BlockSize) {\r
-      Trb->BlockSize = (UINT16)Trb->DataLen;\r
-    }\r
+  if (Trb->DataLen < Trb->BlockSize) {\r
+    Trb->BlockSize = (UINT16)Trb->DataLen;\r
   }\r
 \r
-  if (Trb->DataLen == 0) {\r
-    Trb->Mode = SdNoData;\r
-  } else if (Capability.Adma2 != 0) {\r
-    Trb->Mode = SdAdmaMode;\r
-    Status = BuildAdmaDescTable (Trb);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-  } else if (Capability.Sdma != 0) {\r
-    Trb->Mode = SdSdmaMode;\r
-  } else {\r
+  if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {\r
     Trb->Mode = SdPioMode;\r
+  } else {\r
+    if (Trb->DataLen == 0) {\r
+      Trb->Mode = SdNoData;\r
+    } else if (Capability.Adma2 != 0) {\r
+      Trb->Mode = SdAdmaMode;\r
+      Status = BuildAdmaDescTable (Trb);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Error;\r
+      }\r
+    } else if (Capability.Sdma != 0) {\r
+      Trb->Mode = SdSdmaMode;\r
+    } else {\r
+      Trb->Mode = SdPioMode;\r
+    }\r
   }\r
-\r
   return Trb;\r
 \r
 Error:\r
@@ -1111,9 +1112,6 @@ SdPeimCheckTrbEnv (
     // the Present State register to be 0\r
     //\r
     PresentState = BIT0 | BIT1;\r
-    if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {\r
-      PresentState = BIT0;\r
-    }\r
   } else {\r
     //\r
     // Wait Command Inhibit (CMD) in the Present State register\r
@@ -1273,7 +1271,13 @@ SdPeimExecTrb (
     return Status;\r
   }\r
 \r
-  BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  BlkCount = 0;\r
+  if (Trb->Mode != SdNoData) {\r
+    //\r
+    // Calcuate Block Count.\r
+    //\r
+    BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  }\r
   Status   = SdPeimHcRwMmio (Bar + SD_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -1293,9 +1297,12 @@ SdPeimExecTrb (
     if (Trb->Read) {\r
       TransMode |= BIT4;\r
     }\r
-    if (BlkCount != 0) {\r
+    if (BlkCount > 1) {\r
       TransMode |= BIT5 | BIT1;\r
     }\r
+    //\r
+    // SD memory card needs to use AUTO CMD12 feature.\r
+    //\r
     if (BlkCount > 1) {\r
       TransMode |= BIT2;\r
     }\r
@@ -1368,6 +1375,7 @@ SdPeimCheckTrbResult (
   UINT32                              SdmaAddr;\r
   UINT8                               Index;\r
   UINT8                               SwReset;\r
+  UINT32                              PioLength;\r
 \r
   SwReset = 0;\r
   Packet  = Trb->Packet;\r
@@ -1500,8 +1508,26 @@ SdPeimCheckTrbResult (
   }\r
 \r
   if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {\r
-    Status = EFI_SUCCESS;\r
-    goto Done;\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
+      SdPeimHcRwMmio (Bar + SD_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
+        SdPeimHcRwMmio (Bar + SD_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