[edk2-devel] [PATCH] MdeModulePkg: Enabling OS boot from SD card through UEFI payload

Aiman Rosli posted 1 patch 2 years, 3 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 273 ++++++++++--------
1 file changed, 146 insertions(+), 127 deletions(-)
[edk2-devel] [PATCH] MdeModulePkg: Enabling OS boot from SD card through UEFI payload
Posted by Aiman Rosli 2 years, 3 months ago
This changes is by  adding 50ms delay during voltage swithcing from 3.3V to 1.8V,
plus adding a while loop for 3.3V checking and retrying.

Signed-off-by: Aiman Rosli <muhammad.aiman.rosli@intel.com>
---
 MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 273 ++++++++++--------
 1 file changed, 146 insertions(+), 127 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
index 662f9f483c..e91251d457 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
@@ -1213,167 +1213,186 @@ SdCardIdentification (
   UINT32                         PresentState;
   UINT8                          HostCtrl2;
   UINTN                          Retry;
+  BOOLEAN                        Force3p3v;
+
+  Force3p3v = FALSE;
 
   PciIo    = Private->PciIo;
   PassThru = &Private->PassThru;
-  //
-  // 1. Send Cmd0 to the device
-  //
-  Status = SdCardReset (PassThru, Slot);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));
-    return Status;
-  }
-
-  //
-  // 2. Send Cmd8 to the device
-  //
-  Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));
-    return Status;
-  }
-
-  //
-  // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.
-  //
-  Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);
-  if (!EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));
-    return EFI_DEVICE_ERROR;
-  }
 
-  //
-  // 4. Send Acmd41 with voltage window 0 to the device
-  //
-  Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));
-    return EFI_DEVICE_ERROR;
-  }
-
-  if (Private->Capability[Slot].Voltage33 != 0) {
+  do {
     //
-    // Support 3.3V
+    // 1. Send Cmd0 to the device
     //
-    MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;
-  } else if (Private->Capability[Slot].Voltage30 != 0) {
+    Status = SdCardReset (PassThru, Slot);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));
+      return Status;
+    }
+
     //
-    // Support 3.0V
+    // 2. Send Cmd8 to the device
     //
-    MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;
-  } else if (Private->Capability[Slot].Voltage18 != 0) {
+    Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));
+      return Status;
+    }
+
     //
-    // Support 1.8V
+    // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.
     //
-    MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;
-  } else {
-    ASSERT (FALSE);
-    return EFI_DEVICE_ERROR;
-  }
-
-  if (MaxCurrent >= 150) {
-    Xpc = TRUE;
-  } else {
-    Xpc = FALSE;
-  }
-
-  Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
-      ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420))
-  {
-    S18r = TRUE;
-  } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {
-    S18r = FALSE;
-  } else {
-    ASSERT (FALSE);
-    return EFI_UNSUPPORTED;
-  }
+    Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));
+      return EFI_DEVICE_ERROR;
+    }
 
-  //
-  // 5. Repeatly send Acmd41 with supply voltage window to the device.
-  //    Note here we only support the cards complied with SD physical
-  //    layer simplified spec version 2.0 and version 3.0 and above.
-  //
-  Ocr   = 0;
-  Retry = 0;
-  do {
-    Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
+    //
+    // 4. Send Acmd41 with voltage window 0 to the device
+    //
+    Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
     if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
+      DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));
       return EFI_DEVICE_ERROR;
     }
 
-    if (Retry++ == 100) {
-      DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails too many times\n"));
+    if (Private->Capability[Slot].Voltage33 != 0) {
+      //
+      // Support 3.3V
+      //
+      MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;
+    } else if (Private->Capability[Slot].Voltage30 != 0) {
+      //
+      // Support 3.0V
+      //
+      MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;
+    } else if (Private->Capability[Slot].Voltage18 != 0) {
+      //
+      // Support 1.8V
+      //
+      MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;
+    } else {
+      ASSERT (FALSE);
       return EFI_DEVICE_ERROR;
     }
 
-    gBS->Stall (10 * 1000);
-  } while ((Ocr & BIT31) == 0);
+    if (MaxCurrent >= 150) {
+      Xpc = TRUE;
+    } else {
+      Xpc = FALSE;
+    }
 
-  //
-  // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling
-  //    (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
-  //    Capabilities register), switch its voltage to 1.8V.
-  //
-  if (((Private->Capability[Slot].Sdr50 != 0) ||
-       (Private->Capability[Slot].Sdr104 != 0) ||
-       (Private->Capability[Slot].Ddr50 != 0)) &&
-      ((Ocr & BIT24) != 0))
-  {
-    Status = SdCardVoltageSwitch (PassThru, Slot);
+    Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
     if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));
-      Status = EFI_DEVICE_ERROR;
-      goto Error;
+      return Status;
+    }
+
+    if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
+        ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420))
+    {
+      S18r = TRUE;
+    } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {
+      S18r = FALSE;
     } else {
-      Status = SdMmcHcStopClock (PciIo, Slot);
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+
+    //
+    // 1.8V had failed in the previous run, forcing a retry with 3.3V instead
+    //
+    if (Force3p3v == TRUE) {
+      S18r      = FALSE;
+      Force3p3v = FALSE;
+    }
+
+    //
+    // 5. Repeatly send Acmd41 with supply voltage window to the device.
+    //    Note here we only support the cards complied with SD physical
+    //    layer simplified spec version 2.0 and version 3.0 and above.
+    //
+    Ocr   = 0;
+    Retry = 0;
+    do {
+      Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
       if (EFI_ERROR (Status)) {
-        Status = EFI_DEVICE_ERROR;
-        goto Error;
+        DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
+        return EFI_DEVICE_ERROR;
       }
 
-      SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
-      if (((PresentState >> 20) & 0xF) != 0) {
-        DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));
-        Status = EFI_DEVICE_ERROR;
-        goto Error;
+      if (Retry++ == 100) {
+        DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails too many times\n"));
+        return EFI_DEVICE_ERROR;
       }
 
-      HostCtrl2 = BIT3;
-      SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
-
-      gBS->Stall (5000);
+      gBS->Stall (10 * 1000);
+    } while ((Ocr & BIT31) == 0);
 
-      SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
-      if ((HostCtrl2 & BIT3) == 0) {
-        DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));
+    //
+    // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling
+    //    (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
+    //    Capabilities register), switch its voltage to 1.8V.
+    //
+    if (((Private->Capability[Slot].Sdr50 != 0) ||
+         (Private->Capability[Slot].Sdr104 != 0) ||
+         (Private->Capability[Slot].Ddr50 != 0)) &&
+        ((Ocr & BIT24) != 0))
+    {
+      Status = SdCardVoltageSwitch (PassThru, Slot);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));
         Status = EFI_DEVICE_ERROR;
         goto Error;
-      }
+      } else {
+        Status = SdMmcHcStopClock (PciIo, Slot);
+        if (EFI_ERROR (Status)) {
+          Status = EFI_DEVICE_ERROR;
+          goto Error;
+        }
 
-      Status = SdMmcHcStartSdClock (PciIo, Slot);
-      if (EFI_ERROR (Status)) {
-        goto Error;
-      }
+        SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
+        if (((PresentState >> 20) & 0xF) != 0) {
+          DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));
+          Status = EFI_DEVICE_ERROR;
+          goto Error;
+        }
 
-      gBS->Stall (1000);
+        HostCtrl2 = BIT3;
+        SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
 
-      SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
-      if (((PresentState >> 20) & 0xF) != 0xF) {
-        DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));
-        Status = EFI_DEVICE_ERROR;
-        goto Error;
+        gBS->Stall (5000);
+
+        SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
+        if ((HostCtrl2 & BIT3) == 0) {
+          DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));
+          Status = EFI_DEVICE_ERROR;
+          goto Error;
+        }
+
+        Status = SdMmcHcStartSdClock (PciIo, Slot);
+        if (EFI_ERROR (Status)) {
+          goto Error;
+        }
+
+        // Workaround to add a delay of 100ms in order for clock to stabilize before turning on the SD card again.
+        gBS->Stall (50000);
+
+        gBS->Stall (1000);
+
+        SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
+        if (((PresentState >> 20) & 0xF) != 0xF) {
+          DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));
+          Status    = SdMmcHcReset (Private, Slot);
+          Status    = SdMmcHcInitHost (Private, Slot);
+          Force3p3v = TRUE;
+          DEBUG ((DEBUG_ERROR, "SdCardIdentification: Switching to 1.8V had failed in the previous run, forcing a retry with 3.3V instead\n"));
+        }
       }
-    }
 
-    DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));
-  }
+      DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));
+    }
+  } while (Force3p3v);
 
   Status = SdCardAllSendCid (PassThru, Slot);
   if (EFI_ERROR (Status)) {
-- 
2.34.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#85723): https://edk2.groups.io/g/devel/message/85723
Mute This Topic: https://groups.io/mt/88477724/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-