-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Silicon/Rockchip: Add SdMmcPciHcDxe-based eMMC driver
This replaces the old SdhciHostDxe driver which is quite limited and has some issues around the DMA code. It supports all speed modes with the exception of HS400ES (requires a few changes in SdMmcPciHcDxe). Derived from Quartz64-UEFI's EmmcDxe.
- Loading branch information
1 parent
a4b551c
commit 0d5f7fe
Showing
12 changed files
with
572 additions
and
2 deletions.
There are no files selected for viewing
251 changes: 251 additions & 0 deletions
251
edk2-rockchip/Silicon/Rockchip/Drivers/DwcSdhciDxe/DwcSdhciDxe.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
/** @file | ||
* | ||
* Synopsys DesignWare Cores SDHCI eMMC driver | ||
* | ||
* Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR> | ||
* Copyright (c) 2022, Patrick Wildt <patrick@blueri.se> | ||
* Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause-Patent | ||
* | ||
**/ | ||
|
||
#include <Library/DebugLib.h> | ||
#include <Library/IoLib.h> | ||
#include <Library/NonDiscoverableDeviceRegistrationLib.h> | ||
#include <Library/UefiBootServicesTableLib.h> | ||
#include <Library/DwcSdhciPlatformLib.h> | ||
|
||
#include <Protocol/NonDiscoverableDevice.h> | ||
#include <Protocol/SdMmcOverride.h> | ||
|
||
#include "DwcSdhciDxe.h" | ||
|
||
#define EMMC_FORCE_HIGH_SPEED FixedPcdGetBool(PcdDwcSdhciForceHighSpeed) | ||
|
||
STATIC EFI_HANDLE mSdMmcControllerHandle; | ||
|
||
/** | ||
Override function for SDHCI capability bits | ||
@param[in] ControllerHandle The EFI_HANDLE of the controller. | ||
@param[in] Slot The 0 based slot index. | ||
@param[in,out] SdMmcHcSlotCapability The SDHCI capability structure. | ||
@param[in,out] BaseClkFreq The base clock frequency value that | ||
optionally can be updated. | ||
@retval EFI_SUCCESS The override function completed successfully. | ||
@retval EFI_NOT_FOUND The specified controller or slot does not exist. | ||
@retval EFI_INVALID_PARAMETER SdMmcHcSlotCapability is NULL | ||
**/ | ||
STATIC | ||
EFI_STATUS | ||
EFIAPI | ||
EmmcSdMmcCapability ( | ||
IN EFI_HANDLE ControllerHandle, | ||
IN UINT8 Slot, | ||
IN OUT VOID *SdMmcHcSlotCapability, | ||
IN OUT UINT32 *BaseClkFreq | ||
) | ||
{ | ||
SD_MMC_HC_SLOT_CAP *Capability = SdMmcHcSlotCapability; | ||
|
||
if (SdMmcHcSlotCapability == NULL) { | ||
return EFI_INVALID_PARAMETER; | ||
} | ||
if (ControllerHandle != mSdMmcControllerHandle) { | ||
return EFI_NOT_FOUND; | ||
} | ||
|
||
Capability->Hs400 = 1; | ||
|
||
if (EMMC_FORCE_HIGH_SPEED) { | ||
Capability->BaseClkFreq = 52; | ||
Capability->Sdr50 = 0; | ||
Capability->Ddr50 = 0; | ||
Capability->Sdr104 = 0; | ||
Capability->Hs400 = 0; | ||
} | ||
|
||
return EFI_SUCCESS; | ||
} | ||
|
||
/** | ||
Override function for SDHCI controller operations | ||
@param[in] ControllerHandle The EFI_HANDLE of the controller. | ||
@param[in] Slot The 0 based slot index. | ||
@param[in] PhaseType The type of operation and whether the | ||
hook is invoked right before (pre) or | ||
right after (post) | ||
@param[in,out] PhaseData The pointer to a phase-specific data. | ||
@retval EFI_SUCCESS The override function completed successfully. | ||
@retval EFI_NOT_FOUND The specified controller or slot does not exist. | ||
@retval EFI_INVALID_PARAMETER PhaseType is invalid | ||
**/ | ||
STATIC | ||
EFI_STATUS | ||
EFIAPI | ||
EmmcSdMmcNotifyPhase ( | ||
IN EFI_HANDLE ControllerHandle, | ||
IN UINT8 Slot, | ||
IN EDKII_SD_MMC_PHASE_TYPE PhaseType, | ||
IN OUT VOID *PhaseData | ||
) | ||
{ | ||
SD_MMC_BUS_MODE *Timing; | ||
UINTN MaxClockFreq; | ||
UINT32 Value, i; | ||
|
||
DEBUG ((DEBUG_INFO, "%a\n", __FUNCTION__)); | ||
|
||
if (ControllerHandle != mSdMmcControllerHandle) { | ||
return EFI_SUCCESS; | ||
} | ||
|
||
ASSERT (Slot == 0); | ||
|
||
switch (PhaseType) { | ||
case EdkiiSdMmcInitHostPost: | ||
/* | ||
* Just before this Notification POWER_CTRL is toggled to power off | ||
* and on the card. On this controller implementation, toggling | ||
* power off also removes SDCLK_ENABLE (BIT2) from from CLOCK_CTRL. | ||
* Since the clock has already been set up prior to the power toggle, | ||
* re-add the SDCLK_ENABLE bit to start the clock. | ||
*/ | ||
MmioOr16((UINT32) SD_MMC_HC_CLOCK_CTRL, CLOCK_CTRL_SDCLK_ENABLE); | ||
break; | ||
|
||
case EdkiiSdMmcUhsSignaling: | ||
if (PhaseData == NULL) { | ||
return EFI_INVALID_PARAMETER; | ||
} | ||
|
||
Timing = (SD_MMC_BUS_MODE *)PhaseData; | ||
if (*Timing == SdMmcMmcHs400) { | ||
/* HS400 uses a non-standard setting */ | ||
MmioOr16((UINT32) SD_MMC_HC_HOST_CTRL2, HOST_CTRL2_HS400); | ||
} | ||
break; | ||
|
||
case EdkiiSdMmcSwitchClockFreqPost: | ||
if (PhaseData == NULL) { | ||
return EFI_INVALID_PARAMETER; | ||
} | ||
|
||
Timing = (SD_MMC_BUS_MODE *)PhaseData; | ||
switch (*Timing) { | ||
case SdMmcMmcHs400: | ||
case SdMmcMmcHs200: | ||
MaxClockFreq = 200000000UL; | ||
break; | ||
case SdMmcMmcHsSdr: | ||
case SdMmcMmcHsDdr: | ||
MaxClockFreq = 52000000UL; | ||
break; | ||
default: | ||
MaxClockFreq = 26000000UL; | ||
break; | ||
} | ||
|
||
DwcSdhciSetClockRate (MaxClockFreq); | ||
|
||
if (MaxClockFreq <= 52000000UL) { | ||
MmioWrite32 (EMMC_DLL_CTRL, 0); | ||
MmioWrite32 (EMMC_DLL_RXCLK, 0); | ||
MmioWrite32 (EMMC_DLL_TXCLK, 0); | ||
MmioWrite32 (EMMC_DLL_CMDOUT, 0); | ||
MmioWrite32 (EMMC_DLL_STRBIN, EMMC_DLL_DLYENA | | ||
EMMC_DLL_STRBIN_DELAY_NUM_SEL | | ||
EMMC_DLL_STRBIN_DELAY_NUM_DEFAULT << EMMC_DLL_STRBIN_DELAY_NUM_OFFSET); | ||
break; | ||
} | ||
|
||
/* Switch to eMMC mode */ | ||
MmioOr32 (EMMC_EMMC_CTRL, EMMC_CTRL_CARD_IS_EMMC); | ||
|
||
MmioWrite32(EMMC_DLL_CTRL, EMMC_DLL_CTRL_SRST); | ||
gBS->Stall (1); | ||
MmioWrite32(EMMC_DLL_CTRL, 0); | ||
|
||
MmioWrite32(EMMC_DLL_CTRL, EMMC_DLL_CTRL_START_POINT_DEFAULT | | ||
EMMC_DLL_CTRL_INCREMENT_DEFAULT | EMMC_DLL_CTRL_START); | ||
|
||
for (i = 0; i < 500; i++) { | ||
Value = MmioRead32(EMMC_DLL_STATUS0); | ||
if (Value & EMMC_DLL_STATUS0_DLL_LOCK && | ||
!(Value & EMMC_DLL_STATUS0_DLL_TIMEOUT)) { | ||
break; | ||
} | ||
gBS->Stall (1); | ||
} | ||
|
||
MmioWrite32(EMMC_DLL_RXCLK, EMMC_DLL_DLYENA | | ||
EMMC_DLL_RXCLK_NO_INVERTER); | ||
MmioWrite32(EMMC_DLL_TXCLK, EMMC_DLL_DLYENA | | ||
EMMC_DLL_TXCLK_TAPNUM_DEFAULT | EMMC_DLL_TXCLK_TAPNUM_FROM_SW); | ||
MmioWrite32(EMMC_DLL_STRBIN, EMMC_DLL_DLYENA | | ||
EMMC_DLL_STRBIN_TAPNUM_DEFAULT); | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
return EFI_SUCCESS; | ||
} | ||
|
||
STATIC EDKII_SD_MMC_OVERRIDE mSdMmcOverride = { | ||
EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION, | ||
EmmcSdMmcCapability, | ||
EmmcSdMmcNotifyPhase, | ||
}; | ||
|
||
EFI_STATUS | ||
EFIAPI | ||
DwcSdhciDxeInitialize ( | ||
IN EFI_HANDLE ImageHandle, | ||
IN EFI_SYSTEM_TABLE *SystemTable | ||
) | ||
{ | ||
EFI_STATUS Status; | ||
EFI_HANDLE Handle; | ||
|
||
DEBUG ((DEBUG_BLKIO, "%a\n", __FUNCTION__)); | ||
|
||
/* Start card on 375 kHz */ | ||
DwcSdhciSetClockRate (375000UL); | ||
|
||
/* Configure pins */ | ||
DwcSdhciSetIoMux (); | ||
|
||
/* Disable Command Conflict Check */ | ||
MmioWrite32 (EMMC_HOST_CTRL3, 0); | ||
|
||
/* Disable DLL for identification */ | ||
MmioWrite32 (EMMC_DLL_CTRL, 0); | ||
MmioWrite32 (EMMC_DLL_RXCLK, 0); | ||
MmioWrite32 (EMMC_DLL_TXCLK, 0); | ||
MmioWrite32 (EMMC_DLL_STRBIN, 0); | ||
|
||
Status = RegisterNonDiscoverableMmioDevice ( | ||
NonDiscoverableDeviceTypeSdhci, | ||
NonDiscoverableDeviceDmaTypeNonCoherent, | ||
NULL, | ||
&mSdMmcControllerHandle, | ||
1, | ||
DWC_SDHCI_BASE, 0x10000); | ||
ASSERT_EFI_ERROR (Status); | ||
|
||
Handle = NULL; | ||
Status = gBS->InstallProtocolInterface (&Handle, | ||
&gEdkiiSdMmcOverrideProtocolGuid, | ||
EFI_NATIVE_INTERFACE, (VOID **)&mSdMmcOverride); | ||
ASSERT_EFI_ERROR (Status); | ||
|
||
return EFI_SUCCESS; | ||
} |
93 changes: 93 additions & 0 deletions
93
edk2-rockchip/Silicon/Rockchip/Drivers/DwcSdhciDxe/DwcSdhciDxe.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/** @file | ||
* | ||
* Synopsys DesignWare Cores SDHCI eMMC driver | ||
* | ||
* Copyright (c) 2022, Patrick Wildt <patrick@blueri.se> | ||
* Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause-Patent | ||
* | ||
**/ | ||
|
||
#ifndef __DWCSDHCIDXE_H__ | ||
#define __DWCSDHCIDXE_H__ | ||
|
||
#define DWC_SDHCI_BASE PcdGet32 (PcdSdhciDxeBaseAddress) | ||
|
||
#define SD_MMC_HC_CLOCK_CTRL (DWC_SDHCI_BASE + 0x2C) | ||
#define SD_MMC_HC_HOST_CTRL2 (DWC_SDHCI_BASE + 0x3E) | ||
|
||
// eMMC Registers | ||
#define EMMC_HOST_CTRL3 (DWC_SDHCI_BASE + 0x508) | ||
#define EMMC_EMMC_CTRL (DWC_SDHCI_BASE + 0x52C) | ||
#define EMMC_DLL_CTRL (DWC_SDHCI_BASE + 0x800) | ||
#define EMMC_DLL_RXCLK (DWC_SDHCI_BASE + 0x804) | ||
#define EMMC_DLL_TXCLK (DWC_SDHCI_BASE + 0x808) | ||
#define EMMC_DLL_STRBIN (DWC_SDHCI_BASE + 0x80C) | ||
#define EMMC_DLL_CMDOUT (DWC_SDHCI_BASE + 0x810) | ||
#define EMMC_DLL_STATUS0 (DWC_SDHCI_BASE + 0x840) | ||
#define EMMC_DLL_STATUS1 (DWC_SDHCI_BASE + 0x844) | ||
|
||
#define CLOCK_CTRL_SDCLK_ENABLE BIT2 | ||
|
||
#define HOST_CTRL2_HS400 (BIT2 | BIT1 | BIT0) | ||
|
||
#define EMMC_CTRL_CARD_IS_EMMC BIT0 | ||
|
||
#define EMMC_DLL_CTRL_SRST BIT1 | ||
#define EMMC_DLL_CTRL_START BIT0 | ||
#define EMMC_DLL_CTRL_START_POINT_DEFAULT (5 << 16) | ||
#define EMMC_DLL_CTRL_INCREMENT_DEFAULT (2 << 8) | ||
|
||
#define EMMC_DLL_DLYENA BIT27 | ||
|
||
#define EMMC_DLL_RXCLK_NO_INVERTER BIT29 | ||
|
||
#define EMMC_DLL_TXCLK_TAPNUM_DEFAULT (0x10 << 0) | ||
#define EMMC_DLL_TXCLK_TAPNUM_FROM_SW BIT24 | ||
|
||
#define EMMC_DLL_STRBIN_TAPNUM_DEFAULT (0x3 << 0) | ||
#define EMMC_DLL_STRBIN_DELAY_NUM_SEL BIT26 | ||
#define EMMC_DLL_STRBIN_DELAY_NUM_OFFSET 16 | ||
#define EMMC_DLL_STRBIN_DELAY_NUM_DEFAULT 0x10 | ||
|
||
#define EMMC_DLL_STATUS0_DLL_LOCK BIT8 | ||
#define EMMC_DLL_STATUS0_DLL_TIMEOUT BIT9 | ||
|
||
typedef struct { | ||
UINT32 TimeoutFreq : 6; // bit 0:5 | ||
UINT32 Reserved : 1; // bit 6 | ||
UINT32 TimeoutUnit : 1; // bit 7 | ||
UINT32 BaseClkFreq : 8; // bit 8:15 | ||
UINT32 MaxBlkLen : 2; // bit 16:17 | ||
UINT32 BusWidth8 : 1; // bit 18 | ||
UINT32 Adma2 : 1; // bit 19 | ||
UINT32 Reserved2 : 1; // bit 20 | ||
UINT32 HighSpeed : 1; // bit 21 | ||
UINT32 Sdma : 1; // bit 22 | ||
UINT32 SuspRes : 1; // bit 23 | ||
UINT32 Voltage33 : 1; // bit 24 | ||
UINT32 Voltage30 : 1; // bit 25 | ||
UINT32 Voltage18 : 1; // bit 26 | ||
UINT32 SysBus64V4 : 1; // bit 27 | ||
UINT32 SysBus64V3 : 1; // bit 28 | ||
UINT32 AsyncInt : 1; // bit 29 | ||
UINT32 SlotType : 2; // bit 30:31 | ||
UINT32 Sdr50 : 1; // bit 32 | ||
UINT32 Sdr104 : 1; // bit 33 | ||
UINT32 Ddr50 : 1; // bit 34 | ||
UINT32 Reserved3 : 1; // bit 35 | ||
UINT32 DriverTypeA : 1; // bit 36 | ||
UINT32 DriverTypeC : 1; // bit 37 | ||
UINT32 DriverTypeD : 1; // bit 38 | ||
UINT32 DriverType4 : 1; // bit 39 | ||
UINT32 TimerCount : 4; // bit 40:43 | ||
UINT32 Reserved4 : 1; // bit 44 | ||
UINT32 TuningSDR50 : 1; // bit 45 | ||
UINT32 RetuningMod : 2; // bit 46:47 | ||
UINT32 ClkMultiplier : 8; // bit 48:55 | ||
UINT32 Reserved5 : 7; // bit 56:62 | ||
UINT32 Hs400 : 1; // bit 63 | ||
} SD_MMC_HC_SLOT_CAP; | ||
|
||
#endif // __DWCSDHCIDXE_H__ |
49 changes: 49 additions & 0 deletions
49
edk2-rockchip/Silicon/Rockchip/Drivers/DwcSdhciDxe/DwcSdhciDxe.inf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#/** @file | ||
# | ||
# Synopsys DesignWare Cores SDHCI eMMC driver | ||
# | ||
# Copyright (c) 2014-2017, Linaro Limited. All rights reserved. | ||
# Copyright (c) 2022, Patrick Wildt <patrick@blueri.se> | ||
# Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com> | ||
# | ||
# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
# | ||
#**/ | ||
|
||
[Defines] | ||
INF_VERSION = 0x00010019 | ||
BASE_NAME = DwcSdhciDxe | ||
FILE_GUID = 4cd3a91b-990e-46a6-b609-9fa5d70d1f5f | ||
MODULE_TYPE = UEFI_DRIVER | ||
VERSION_STRING = 1.0 | ||
|
||
ENTRY_POINT = DwcSdhciDxeInitialize | ||
|
||
[Sources.common] | ||
DwcSdhciDxe.c | ||
|
||
[Packages] | ||
MdePkg/MdePkg.dec | ||
MdeModulePkg/MdeModulePkg.dec | ||
Silicon/Rockchip/RockchipPkg.dec | ||
|
||
[LibraryClasses] | ||
UefiDriverEntryPoint | ||
DebugLib | ||
IoLib | ||
NonDiscoverableDeviceRegistrationLib | ||
UefiBootServicesTableLib | ||
DwcSdhciPlatformLib | ||
|
||
[Protocols] | ||
gEdkiiNonDiscoverableDeviceProtocolGuid ## PRODUCES | ||
gEdkiiSdMmcOverrideProtocolGuid ## PRODUCES | ||
gEfiCpuArchProtocolGuid | ||
gEfiDevicePathProtocolGuid | ||
|
||
[Pcd] | ||
gRockchipTokenSpaceGuid.PcdSdhciDxeBaseAddress | ||
gRockchipTokenSpaceGuid.PcdDwcSdhciForceHighSpeed | ||
|
||
[Depex] | ||
TRUE |
Oops, something went wrong.