From: Tomasz Michalec <t...@semihalf.com> Some SD Host Controlers use different values in Host Control 2 Register to select UHS Mode. This patch adds new UhsSignaling callback to the SdMmcOverride protocol. UHS signaling configuration is moved to a common, default routine (SdMmcHcUhsSignaling), which is called when SdMmcOverride does not cover this functionality.
Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Marcin Wojtas <m...@semihalf.com> --- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 50 +++++++ MdeModulePkg/Include/Protocol/SdMmcOverride.h | 26 ++++ MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 150 ++++++++++++-------- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 36 +++-- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 69 +++++++++ 5 files changed, 263 insertions(+), 68 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h index e3fadb5..525828c 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h @@ -68,6 +68,39 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define SD_MMC_HC_HOST_CTRL1_HS_ENABLE (1 << 2) // +// SD Host Controler bits to HOST_CTRL2 register +// +#define SD_MMC_HC_CTRL_UHS_MASK 0x0007 +#define SD_MMC_HC_CTRL_UHS_SDR12 0x0000 +#define SD_MMC_HC_CTRL_UHS_SDR25 0x0001 +#define SD_MMC_HC_CTRL_UHS_SDR50 0x0002 +#define SD_MMC_HC_CTRL_UHS_SDR104 0x0003 +#define SD_MMC_HC_CTRL_UHS_DDR50 0x0004 +#define SD_MMC_HC_CTRL_MMC_DDR52 0x0004 +#define SD_MMC_HC_CTRL_MMC_SDR50 0x0002 +#define SD_MMC_HC_CTRL_MMC_SDR25 0x0001 +#define SD_MMC_HC_CTRL_MMC_SDR12 0x0000 +#define SD_MMC_HC_CTRL_HS200 0x0003 +#define SD_MMC_HC_CTRL_HS400 0x0005 + +// +// Timing modes for uhs +// +typedef enum { + SdMmcUhsSdr12, + SdMmcUhsSdr25, + SdMmcUhsSdr50, + SdMmcUhsSdr104, + SdMmcUhsDdr50, + SdMmcMmcDdr52, + SdMmcMmcSdr50, + SdMmcMmcSdr25, + SdMmcMmcSdr12, + SdMmcMmcHs200, + SdMmcMmcHs400, +} SD_MMC_UHS_TIMING; + +// // The transfer modes supported by SD Host Controller // Simplified Spec 3.0 Table 1-2 // @@ -513,4 +546,21 @@ SdMmcHcInitTimeoutCtrl ( IN UINT8 Slot ); +/** + Set SD Host Controler control 2 registry according to selected speed. + + @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] Timing The timing to select. + + @retval EFI_SUCCESS The timing is set successfully. + @retval Others The timing isn't set successfully. +**/ +EFI_STATUS +SdMmcHcUhsSignaling ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_UHS_TIMING Timing + ); + #endif diff --git a/MdeModulePkg/Include/Protocol/SdMmcOverride.h b/MdeModulePkg/Include/Protocol/SdMmcOverride.h index 0766252..a7a57e8 100644 --- a/MdeModulePkg/Include/Protocol/SdMmcOverride.h +++ b/MdeModulePkg/Include/Protocol/SdMmcOverride.h @@ -17,6 +17,7 @@ #ifndef __SD_MMC_OVERRIDE_H__ #define __SD_MMC_OVERRIDE_H__ +#include <Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h> #include <Protocol/SdMmcPassThru.h> #define EDKII_SD_MMC_OVERRIDE_PROTOCOL_GUID \ @@ -77,6 +78,27 @@ EFI_STATUS IN EDKII_SD_MMC_PHASE_TYPE PhaseType ); +/** + + Override function for uhs signaling + + @param[in] ControllerHandle The EFI_HANDLE of the controller. + @param[in] Slot The 0 based slot index. + @param[in] Timing The timing which should be set by + host controller. + + @retval EFI_SUCCESS The override function completed successfully. + @retval EFI_NOT_FOUND The specified controller or slot does not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI * EDKII_SD_MMC_UHS_SIGNALING) ( + IN EFI_HANDLE ControllerHandle, + IN UINT8 Slot, + IN SD_MMC_UHS_TIMING Timing + ); + struct _EDKII_SD_MMC_OVERRIDE { // // Protocol version of this implementation @@ -90,6 +112,10 @@ struct _EDKII_SD_MMC_OVERRIDE { // Callback to invoke SD/MMC override hooks // EDKII_SD_MMC_NOTIFY_PHASE NotifyPhase; + // + // Callback to override SD/MMC host controller uhs signaling + // + EDKII_SD_MMC_UHS_SIGNALING UhsSignaling; }; extern EFI_GUID gEdkiiSdMmcOverrideProtocolGuid; diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c index b3903b4..d285249 100755 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c @@ -740,10 +740,13 @@ EmmcSwitchToHighSpeed ( IN UINT8 BusWidth ) { - EFI_STATUS Status; - UINT8 HsTiming; - UINT8 HostCtrl1; - UINT8 HostCtrl2; + EFI_STATUS Status; + UINT8 HsTiming; + UINT8 HostCtrl1; + SD_MMC_UHS_TIMING Timing; + SD_MMC_HC_PRIVATE_DATA *Private; + + Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth); if (EFI_ERROR (Status)) { @@ -758,27 +761,36 @@ EmmcSwitchToHighSpeed ( return Status; } - // - // Clean UHS Mode Select field of Host Control 2 reigster before update - // - HostCtrl2 = (UINT8)~0x7; - Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50 - // if (IsDdr) { - HostCtrl2 = BIT2; + Timing = SdMmcMmcDdr52; } else if (ClockFreq == 52) { - HostCtrl2 = BIT0; + Timing = SdMmcMmcSdr50; + } else if (ClockFreq == 26) { + Timing = SdMmcMmcSdr25; } else { - HostCtrl2 = 0; + Timing = SdMmcMmcSdr12; } - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; + + if (mOverride != NULL && mOverride->UhsSignaling != NULL) { + Status = mOverride->UhsSignaling ( + Private->ControllerHandle, + Slot, + Timing + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC uhs signaling notifier callback failed - %r\n", + __FUNCTION__, + Status + )); + return Status; + } + } else { + Status = SdMmcHcUhsSignaling (PciIo, Slot, Timing); + if (EFI_ERROR (Status)) { + return Status; + } } HsTiming = 1; @@ -814,10 +826,13 @@ EmmcSwitchToHS200 ( IN UINT8 BusWidth ) { - EFI_STATUS Status; - UINT8 HsTiming; - UINT8 HostCtrl1; - UINT8 HostCtrl2; + EFI_STATUS Status; + UINT8 HsTiming; + UINT8 HostCtrl1; + SD_MMC_UHS_TIMING Timing; + SD_MMC_HC_PRIVATE_DATA *Private; + + Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); if ((BusWidth != 4) && (BusWidth != 8)) { return EFI_INVALID_PARAMETER; @@ -835,21 +850,29 @@ EmmcSwitchToHS200 ( if (EFI_ERROR (Status)) { return Status; } - // - // Clean UHS Mode Select field of Host Control 2 reigster before update - // - HostCtrl2 = (UINT8)~0x7; - Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Set UHS Mode Select field of Host Control 2 reigster to SDR104 - // - HostCtrl2 = BIT0 | BIT1; - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; + + Timing = SdMmcMmcHs200; + + if (mOverride != NULL && mOverride->UhsSignaling != NULL) { + Status = mOverride->UhsSignaling ( + Private->ControllerHandle, + Slot, + Timing + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC uhs signaling notifier callback failed - %r\n", + __FUNCTION__, + Status + )); + return Status; + } + } else { + Status = SdMmcHcUhsSignaling (PciIo, Slot, Timing); + if (EFI_ERROR (Status)) { + return Status; + } } HsTiming = 2; @@ -888,9 +911,12 @@ EmmcSwitchToHS400 ( IN UINT32 ClockFreq ) { - EFI_STATUS Status; - UINT8 HsTiming; - UINT8 HostCtrl2; + EFI_STATUS Status; + UINT8 HsTiming; + SD_MMC_UHS_TIMING Timing; + SD_MMC_HC_PRIVATE_DATA *Private; + + Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8); if (EFI_ERROR (Status)) { @@ -911,21 +937,29 @@ EmmcSwitchToHS400 ( if (EFI_ERROR (Status)) { return Status; } - // - // Clean UHS Mode Select field of Host Control 2 reigster before update - // - HostCtrl2 = (UINT8)~0x7; - Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Set UHS Mode Select field of Host Control 2 reigster to HS400 - // - HostCtrl2 = BIT0 | BIT2; - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; + + Timing = SdMmcMmcHs400; + + if (mOverride != NULL && mOverride->UhsSignaling != NULL) { + Status = mOverride->UhsSignaling ( + Private->ControllerHandle, + Slot, + Timing + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC uhs signaling notifier callback failed - %r\n", + __FUNCTION__, + Status + )); + return Status; + } + } else { + Status = SdMmcHcUhsSignaling (PciIo, Slot, Timing); + if (EFI_ERROR (Status)) { + return Status; + } } HsTiming = 3; diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c index 8c93933..f45a367 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c @@ -784,8 +784,8 @@ SdCardSetBusMode ( UINT8 BusWidth; UINT8 AccessMode; UINT8 HostCtrl1; - UINT8 HostCtrl2; UINT8 SwitchResp[64]; + SD_MMC_UHS_TIMING Timing; SD_MMC_HC_PRIVATE_DATA *Private; Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); @@ -817,18 +817,23 @@ SdCardSetBusMode ( if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) { ClockFreq = 208; AccessMode = 3; + Timing = SdMmcUhsSdr104; } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) { ClockFreq = 100; AccessMode = 2; + Timing = SdMmcUhsSdr50; } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) { ClockFreq = 50; AccessMode = 4; + Timing = SdMmcUhsDdr50; } else if ((SwitchResp[13] & BIT1) != 0) { ClockFreq = 50; AccessMode = 1; + Timing = SdMmcUhsSdr25; } else { ClockFreq = 25; AccessMode = 0; + Timing = SdMmcUhsSdr12; } Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp); @@ -854,15 +859,26 @@ SdCardSetBusMode ( } } - HostCtrl2 = (UINT8)~0x7; - Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; - } - HostCtrl2 = AccessMode; - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - if (EFI_ERROR (Status)) { - return Status; + if (mOverride != NULL && mOverride->UhsSignaling != NULL) { + Status = mOverride->UhsSignaling ( + Private->ControllerHandle, + Slot, + Timing + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC uhs signaling notifier callback failed - %r\n", + __FUNCTION__, + Status + )); + return Status; + } + } else { + Status = SdMmcHcUhsSignaling (PciIo, Slot, Timing); + if (EFI_ERROR (Status)) { + return Status; + } } Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability); diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 9672b5b..95627da 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -1133,6 +1133,75 @@ SdMmcHcInitHost ( } /** + Set SD Host Controler control 2 registry according to selected speed. + + @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] Timing The timing to select. + + @retval EFI_SUCCESS The timing is set successfully. + @retval Others The timing isn't set successfully. +**/ +EFI_STATUS +SdMmcHcUhsSignaling ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_UHS_TIMING Timing + ) +{ + EFI_STATUS Status; + UINT8 HostCtrl2; + + HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + + switch (Timing) { + case SdMmcUhsSdr12: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12; + break; + case SdMmcUhsSdr25: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25; + break; + case SdMmcUhsSdr50: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50; + break; + case SdMmcUhsSdr104: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104; + break; + case SdMmcUhsDdr50: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50; + break; + case SdMmcMmcDdr52: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_DDR52; + break; + case SdMmcMmcSdr50: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_SDR50; + break; + case SdMmcMmcSdr25: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_SDR25; + break; + case SdMmcMmcSdr12: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_SDR12; + break; + case SdMmcMmcHs200: + HostCtrl2 = SD_MMC_HC_CTRL_HS200; + break; + case SdMmcMmcHs400: + HostCtrl2 = SD_MMC_HC_CTRL_HS400; + break; + default: + HostCtrl2 = 0; + break; + } + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + + return Status; +} + +/** Turn on/off LED. @param[in] PciIo The PCI IO protocol instance. -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel