From: muhammad.aiman.rosli@intel.com
To: devel@edk2.groups.io
Cc: Aiman Rosli <muhammad.aiman.rosli@intel.com>
Subject: [PATCH] MdeModulePkg: Enabling OS boot from SD card through UEFI payload
Date: Mon, 17 Jan 2022 10:40:46 +0800 [thread overview]
Message-ID: <29abb9443f6246488cd993e2766bddf694af6f1d.1642387164.git.muhammad.aiman.rosli@intel.com> (raw)
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
reply other threads:[~2022-01-17 2:41 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=29abb9443f6246488cd993e2766bddf694af6f1d.1642387164.git.muhammad.aiman.rosli@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox