]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
MdeModulePkg/Bus/Sd: Fix various typos
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / SdBlockIoPei / SdHci.c
index 48e4ae68caa7d9bf2d0e29d45149ecac874a3cd3..756c3063bbfff635b250134c127d59a8fbae5ea6 100644 (file)
@@ -1,13 +1,7 @@
 /** @file\r
 \r
-  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php.\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -929,7 +923,7 @@ BuildAdmaDescTable (
   UINT64                    Remaining;\r
   UINT32                    Address;\r
 \r
-  Data    = (EFI_PHYSICAL_ADDRESS)(UINTN)Trb->Data;\r
+  Data    = Trb->DataPhy;\r
   DataLen = Trb->DataLen;\r
   //\r
   // Only support 32bit ADMA Descriptor Table\r
@@ -998,6 +992,8 @@ SdPeimCreateTrb (
   SD_TRB                      *Trb;\r
   EFI_STATUS                  Status;\r
   SD_HC_SLOT_CAP              Capability;\r
+  EDKII_IOMMU_OPERATION       MapOp;\r
+  UINTN                       MapLength;\r
 \r
   //\r
   // Calculate a divisor for SD clock frequency\r
@@ -1007,7 +1003,7 @@ SdPeimCreateTrb (
     return NULL;\r
   }\r
 \r
-  Trb = SdPeimAllocateMem (Slot->Private->Pool, sizeof (SD_TRB));\r
+  Trb = AllocateZeroPool (sizeof (SD_TRB));\r
   if (Trb == NULL) {\r
     return NULL;\r
   }\r
@@ -1032,26 +1028,43 @@ 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 != 0) && (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
-  }\r
+  } else {\r
+    if (Trb->Read) {\r
+      MapOp = EdkiiIoMmuOperationBusMasterWrite;\r
+    } else {\r
+      MapOp = EdkiiIoMmuOperationBusMasterRead;\r
+    }\r
 \r
+    if (Trb->DataLen != 0) {\r
+      MapLength = Trb->DataLen;\r
+      Status = IoMmuMap (MapOp, Trb->Data, &MapLength, &Trb->DataPhy, &Trb->DataMap);\r
+\r
+      if (EFI_ERROR (Status) || (MapLength != Trb->DataLen)) {\r
+        DEBUG ((DEBUG_ERROR, "SdPeimCreateTrb: Fail to map data buffer.\n"));\r
+        goto Error;\r
+      }\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
+      Trb->Mode = SdPioMode;\r
+    }\r
+  }\r
   return Trb;\r
 \r
 Error:\r
@@ -1070,12 +1083,16 @@ SdPeimFreeTrb (
   IN SD_TRB           *Trb\r
   )\r
 {\r
+  if ((Trb != NULL) && (Trb->DataMap != NULL)) {\r
+    IoMmuUnmap (Trb->DataMap);\r
+  }\r
+\r
   if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {\r
     SdPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDescSize);\r
   }\r
 \r
   if (Trb != NULL) {\r
-    SdPeimFreeMem (Trb->Slot->Private->Pool, Trb, sizeof (SD_TRB));\r
+    FreePool (Trb);\r
   }\r
   return;\r
 }\r
@@ -1111,9 +1128,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
@@ -1243,11 +1257,11 @@ SdPeimExecTrb (
   SdPeimHcLedOnOff (Bar, TRUE);\r
 \r
   if (Trb->Mode == SdSdmaMode) {\r
-    if ((UINT64)(UINTN)Trb->Data >= 0x100000000ul) {\r
+    if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    SdmaAddr = (UINT32)(UINTN)Trb->Data;\r
+    SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;\r
     Status   = SdPeimHcRwMmio (Bar + SD_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -1273,7 +1287,13 @@ SdPeimExecTrb (
     return Status;\r
   }\r
 \r
-  BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
+  BlkCount = 0;\r
+  if (Trb->Mode != SdNoData) {\r
+    //\r
+    // Calculate 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 +1313,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 +1391,7 @@ SdPeimCheckTrbResult (
   UINT32                              SdmaAddr;\r
   UINT8                               Index;\r
   UINT8                               SwReset;\r
+  UINT32                              PioLength;\r
 \r
   SwReset = 0;\r
   Packet  = Trb->Packet;\r
@@ -1477,7 +1501,7 @@ SdPeimCheckTrbResult (
     //\r
     // Update SDMA Address register.\r
     //\r
-    SdmaAddr = SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->Data, SD_SDMA_BOUNDARY);\r
+    SdmaAddr = SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_SDMA_BOUNDARY);\r
     Status   = SdPeimHcRwMmio (\r
                  Bar + SD_HC_SDMA_ADDR,\r
                  FALSE,\r
@@ -1487,7 +1511,7 @@ SdPeimCheckTrbResult (
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
-    Trb->Data = (VOID*)(UINTN)SdmaAddr;\r
+    Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;\r
   }\r
 \r
   if ((Packet->SdCmdBlk->CommandType != SdCommandTypeAdtc) &&\r
@@ -1500,8 +1524,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
@@ -2166,6 +2208,7 @@ SdPeimSetBusWidth (
   @param[in]  DriveStrength The value for drive length group.\r
   @param[in]  PowerLimit    The value for power limit group.\r
   @param[in]  Mode          Switch or check function.\r
+  @param[out] SwitchResp    The return switch function status.\r
 \r
   @retval EFI_SUCCESS       The operation is done correctly.\r
   @retval Others            The operation fails.\r
@@ -2173,12 +2216,13 @@ SdPeimSetBusWidth (
 **/\r
 EFI_STATUS\r
 SdPeimSwitch (\r
-  IN SD_PEIM_HC_SLOT        *Slot,\r
-  IN UINT8                  AccessMode,\r
-  IN UINT8                  CommandSystem,\r
-  IN UINT8                  DriveStrength,\r
-  IN UINT8                  PowerLimit,\r
-  IN BOOLEAN                Mode\r
+  IN     SD_PEIM_HC_SLOT              *Slot,\r
+  IN     UINT8                        AccessMode,\r
+  IN     UINT8                        CommandSystem,\r
+  IN     UINT8                        DriveStrength,\r
+  IN     UINT8                        PowerLimit,\r
+  IN     BOOLEAN                      Mode,\r
+     OUT UINT8                        *SwitchResp\r
   )\r
 {\r
   SD_COMMAND_BLOCK                    SdCmdBlk;\r
@@ -2186,7 +2230,6 @@ SdPeimSwitch (
   SD_COMMAND_PACKET                   Packet;\r
   EFI_STATUS                          Status;\r
   UINT32                              ModeValue;\r
-  UINT8                               Data[64];\r
 \r
   ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
   ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
@@ -2204,8 +2247,8 @@ SdPeimSwitch (
   SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
                              ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
                              ModeValue;\r
-  Packet.InDataBuffer     = Data;\r
-  Packet.InTransferLength = sizeof (Data);\r
+  Packet.InDataBuffer     = SwitchResp;\r
+  Packet.InTransferLength = 64;\r
 \r
   Status = SdPeimExecCmd (Slot, &Packet);\r
 \r
@@ -2451,7 +2494,7 @@ SdPeimSendTuningBlk (
 }\r
 \r
 /**\r
-  Tunning the sampling point of SDR104 or SDR50 bus speed mode.\r
+  Tuning the sampling point of SDR104 or SDR50 bus speed mode.\r
 \r
   Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the\r
   tuning procedure.\r
@@ -2497,15 +2540,25 @@ SdPeimTuningClock (
       return Status;\r
     }\r
 \r
-    if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
+    if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {\r
       break;\r
     }\r
+\r
+    if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
+      return EFI_SUCCESS;\r
+    }\r
   } while (++Retry < 40);\r
 \r
-  if (Retry == 40) {\r
-    Status = EFI_TIMEOUT;\r
+  DEBUG ((EFI_D_ERROR, "SdPeimTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));\r
+  //\r
+  // Abort the tuning procedure and reset the tuning circuit.\r
+  //\r
+  HostCtrl2 = (UINT8)~(BIT6 | BIT7);\r
+  Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
-  return Status;\r
+  return EFI_DEVICE_ERROR;\r
 }\r
 \r
 /**\r
@@ -2581,6 +2634,7 @@ SdPeimSetBusMode (
   UINT8                        AccessMode;\r
   UINT8                        HostCtrl1;\r
   UINT8                        HostCtrl2;\r
+  UINT8                        SwitchResp[64];\r
 \r
   Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);\r
   if (EFI_ERROR (Status)) {\r
@@ -2607,33 +2661,48 @@ SdPeimSetBusMode (
   }\r
 \r
   //\r
-  // Calculate supported bus speed/bus width/clock frequency.\r
+  // Get the supported bus speed from SWITCH cmd return data group #1.\r
+  //\r
+  ZeroMem (SwitchResp, sizeof (SwitchResp));\r
+  Status = SdPeimSwitch (Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
   //\r
   ClockFreq = 0;\r
-  if (S18a && (Capability.Sdr104 != 0)) {\r
+  if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
     ClockFreq = 208;\r
     AccessMode = 3;\r
-  } else if (S18a && (Capability.Sdr50 != 0)) {\r
+  } else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
     ClockFreq = 100;\r
     AccessMode = 2;\r
-  } else if (S18a && (Capability.Ddr50 != 0)) {\r
+  } else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
     ClockFreq = 50;\r
     AccessMode = 4;\r
-  } else {\r
+  } else if ((SwitchResp[13] & BIT1) != 0) {\r
     ClockFreq = 50;\r
     AccessMode = 1;\r
+  } else {\r
+    ClockFreq = 25;\r
+    AccessMode = 0;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
+  DEBUG ((EFI_D_INFO, "SdPeimSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
 \r
-  Status = SdPeimSwitch (Slot, AccessMode, 0, 0, 0, TRUE);\r
+  Status = SdPeimSwitch (Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));\r
     return Status;\r
   }\r
 \r
+  if ((SwitchResp[16] & 0xF) != AccessMode) {\r
+    DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
   //\r
-  // Set to Hight Speed timing\r
+  // Set to High Speed timing\r
   //\r
   if (AccessMode == 1) {\r
     HostCtrl1 = BIT2;\r
@@ -2701,7 +2770,7 @@ SdPeimIdentification (
   UINT32                         PresentState;\r
   UINT8                          HostCtrl2;\r
   SD_HC_SLOT_CAP                 Capability;\r
-\r
+  UINTN                          Retry;\r
   //\r
   // 1. Send Cmd0 to the device\r
   //\r
@@ -2789,12 +2858,20 @@ SdPeimIdentification (
   //    Note here we only support the cards complied with SD physical\r
   //    layer simplified spec version 2.0 and version 3.0 and above.\r
   //\r
+  Ocr   = 0;\r
+  Retry = 0;\r
   do {\r
     Status = SdPeimSendOpCond (Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);\r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));\r
       return EFI_DEVICE_ERROR;\r
     }\r
+\r
+    if (Retry++ == 100) {\r
+      DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails too many times\n"));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    MicroSecondDelay (10 * 1000);\r
   } while ((Ocr & BIT31) == 0);\r
 \r
   //\r