From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web11.6341.1642387290280943867 for ; Sun, 16 Jan 2022 18:41:30 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=oHZoulKO; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: muhammad.aiman.rosli@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642387290; x=1673923290; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=X0qi37yYVBk/sjFJGxFUWd9AnvpEGEeOmi/z5raNxd0=; b=oHZoulKObp17luV5nY0bTeRuBaSluAkGGelYqbmkCa1JELIfAoGccs6o TkXJYzTbrVu6ymvvMB4vxqmF6422UPwUUe5EUGBvXOzb+TZ/oYPBR+RMD Y/87BZZ04j0FD/fe4mupwHxYuoSawwMj6BaBaA4NXyzShIumat+NSbHD8 5koFCzU+uO4rqYLonz4wSjMyrGz2ssuvWSs5YUIloJQf2LwTeK89bBYQ0 xuyedoENKU+bBj4hUDhOLBaZltT5sk+eMH/aRPPkvUX5Kwt/kX6Gv25/t jYhritz8nWe+rk+ilAHnIpyN9E61a5C0oVrdsdOE6G/MgPTmkpwrNqeFG A==; X-IronPort-AV: E=McAfee;i="6200,9189,10229"; a="305272943" X-IronPort-AV: E=Sophos;i="5.88,294,1635231600"; d="scan'208";a="305272943" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jan 2022 18:41:24 -0800 X-IronPort-AV: E=Sophos;i="5.88,294,1635231600"; d="scan'208";a="577904327" Received: from roslim1-mobl1.gar.corp.intel.com ([10.249.70.75]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jan 2022 18:41:23 -0800 From: muhammad.aiman.rosli@intel.com To: devel@edk2.groups.io Cc: Aiman Rosli Subject: [PATCH] MdeModulePkg: Enabling OS boot from SD card through UEFI payload Date: Mon, 17 Jan 2022 10:40:46 +0800 Message-Id: <29abb9443f6246488cd993e2766bddf694af6f1d.1642387164.git.muhammad.aiman.rosli@intel.com> X-Mailer: git-send-email 2.34.1.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- 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