From cea64af8854a7785e6ac3ecdcc47f46779940b21 Mon Sep 17 00:00:00 2001 From: mattp Date: Fri, 18 Jul 2025 08:23:43 -0400 Subject: [PATCH] SD fixup --- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 32 ++++---- .../Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 77 +++++++++++++++++++ .../Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 28 ++++++- MdeModulePkg/Include/Protocol/SdMmcOverride.h | 10 ++- 4 files changed, 128 insertions(+), 19 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c index 8bf452e9d0..acb98c4a6a 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c @@ -1215,6 +1215,7 @@ SdCardIdentification ( EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; + EFI_HANDLE ControllerHandle; UINT32 Ocr; UINT16 Rca; BOOLEAN Xpc; @@ -1223,7 +1224,6 @@ SdCardIdentification ( UINT16 ControllerVer; UINT8 PowerCtrl; UINT32 PresentState; - UINT8 HostCtrl2; UINTN Retry; BOOLEAN ForceVoltage33; BOOLEAN SdVersion1; @@ -1231,10 +1231,22 @@ SdCardIdentification ( ForceVoltage33 = FALSE; SdVersion1 = FALSE; - PciIo = Private->PciIo; - PassThru = &Private->PassThru; + PciIo = Private->PciIo; + PassThru = &Private->PassThru; + ControllerHandle = Private->ControllerHandle; Voltage33Retry: + // + // Start at 3.3V. + // Note that if we got here from a failed 1.8V switching attempt, + // the card should've been power cycled to reset its own voltage level. + // + Status = SdMmcHcSetSignalingVoltage (ControllerHandle, PciIo, Slot, SdMmcSignalingVoltage33); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdCardIdentification: Couldn't set 3.3V signaling: %r\n", Status)); + return Status; + } + // // 1. Send Cmd0 to the device // @@ -1371,16 +1383,10 @@ Voltage33Retry: goto Error; } - HostCtrl2 = BIT3; - SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - - 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 = SdMmcHcSetSignalingVoltage (ControllerHandle, PciIo, Slot, SdMmcSignalingVoltage18); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdCardIdentification: Couldn't set 1.8V signaling: %r\n", Status)); + return Status; } Status = SdMmcHcStartSdClock (PciIo, Slot); diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 9e8a7f4e43..2e334c67e2 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -1175,6 +1175,83 @@ SdMmcHcInitPowerVoltage ( return Status; } +/** + Set the voltage regulator for I/O signaling. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[in] Voltage The signaling voltage. + + @retval EFI_SUCCESS The voltage is supplied successfully. + @retval Others The voltage isn't supplied successfully. + +**/ +EFI_STATUS +SdMmcHcSetSignalingVoltage ( + IN EFI_HANDLE ControllerHandle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_SIGNALING_VOLTAGE Voltage + ) +{ + EFI_STATUS Status; + UINT8 HostCtrl2; + + // + // Set the internal regulator first. + // + switch (Voltage) { + case SdMmcSignalingVoltage33: + HostCtrl2 = ~SD_MMC_HC_CTRL_1V8_SIGNAL; + SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + break; + case SdMmcSignalingVoltage18: + HostCtrl2 = SD_MMC_HC_CTRL_1V8_SIGNAL; + SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + break; + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Some controllers rely on an external regulator. + // + if ((mOverride != NULL) && (mOverride->NotifyPhase != NULL)) { + Status = mOverride->NotifyPhase ( + ControllerHandle, + Slot, + EdkiiSdMmcSetSignalingVoltage, + &Voltage + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC set signaling voltage notifier callback failed - %r\n", + __func__, + Status + )); + return Status; + } + } + + gBS->Stall (5000); + + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + + HostCtrl2 &= SD_MMC_HC_CTRL_1V8_SIGNAL; + if (((Voltage == SdMmcSignalingVoltage33) && (HostCtrl2 != 0)) || + ((Voltage == SdMmcSignalingVoltage18) && (HostCtrl2 == 0))) + { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + /** Initialize the Timeout Control register with most conservative value at initialization. diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h index e436a7d11a..e771ba7bad 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h @@ -2,10 +2,10 @@ Provides some data structure definitions used by the SD/MMC host controller driver. - Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. - Copyright (c) 2015, Intel Corporation. All rights reserved.
- Copyright (C) 2023, Apple Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent +Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (C) 2023, Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent @par Specification Reference: - SD Host Controller Simplified Specification, Version 4.20, July 25, 2018 @@ -63,6 +63,7 @@ // // SD Host Controller bits to HOST_CTRL2 register // +#define SD_MMC_HC_CTRL_1V8_SIGNAL 0x0008 #define SD_MMC_HC_CTRL_UHS_MASK 0x0007 #define SD_MMC_HC_CTRL_UHS_SDR12 0x0000 #define SD_MMC_HC_CTRL_UHS_SDR25 0x0001 @@ -559,6 +560,25 @@ SdMmcHcInitPowerVoltage ( IN SD_MMC_HC_SLOT_CAP Capability ); +/** + Set the voltage regulator for I/O signaling. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[in] Voltage The signaling voltage. + + @retval EFI_SUCCESS The voltage is supplied successfully. + @retval Others The voltage isn't supplied successfully. + +**/ +EFI_STATUS +SdMmcHcSetSignalingVoltage ( + IN EFI_HANDLE ControllerHandle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_SIGNALING_VOLTAGE Voltage + ); + /** Initialize the Timeout Control register with most conservative value at initialization. diff --git a/MdeModulePkg/Include/Protocol/SdMmcOverride.h b/MdeModulePkg/Include/Protocol/SdMmcOverride.h index 4fd12b9ad4..d611bb04d8 100644 --- a/MdeModulePkg/Include/Protocol/SdMmcOverride.h +++ b/MdeModulePkg/Include/Protocol/SdMmcOverride.h @@ -16,7 +16,7 @@ #define EDKII_SD_MMC_OVERRIDE_PROTOCOL_GUID \ { 0xeaf9e3c1, 0xc9cd, 0x46db, { 0xa5, 0xe5, 0x5a, 0x12, 0x4c, 0x83, 0x23, 0x23 } } -#define EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION 0x3 +#define EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION 0x4 typedef struct _EDKII_SD_MMC_OVERRIDE EDKII_SD_MMC_OVERRIDE; @@ -83,6 +83,11 @@ typedef enum { SdMmcMmcHs400, } SD_MMC_BUS_MODE; +typedef enum { + SdMmcSignalingVoltage33, + SdMmcSignalingVoltage18 +} SD_MMC_SIGNALING_VOLTAGE; + typedef enum { EdkiiSdMmcResetPre, EdkiiSdMmcResetPost, @@ -90,7 +95,8 @@ typedef enum { EdkiiSdMmcInitHostPost, EdkiiSdMmcUhsSignaling, EdkiiSdMmcSwitchClockFreqPost, - EdkiiSdMmcGetOperatingParam + EdkiiSdMmcGetOperatingParam, + EdkiiSdMmcSetSignalingVoltage } EDKII_SD_MMC_PHASE_TYPE; /** -- 2.51.2