mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
mmc: sdhci-cadence: Set controller and PHY speed modes for SD and eMMC cards
Replace the legacy clock frequency-based timing mode selection with proper MMC timing mode constants. Changes to sdhci-cadence.c: - Add sdhci_cdns_get_hrs06_mode() helper function for mode selection - Replace clock frequency logic with mmc->selected_mode switch statement - Use proper MMC timing constants (MMC_HS, UHS_SDR104, etc.) - Add SD card specific handling with standard SDHCI control register setup Changes to sdhci-cadence6.c: - Add SD high speed PHY and control configuration arrays - Update sdhci_cdns6_phy_adj() to use timing modes instead of HRS06 modes - Support both SD and eMMC timing modes with appropriate PHY settings Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> Reviewed-by: Balsundar Ponnusamy <balsundar.ponnusamy@altera.com> Reviewed-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
committed by
Peng Fan
parent
1e40e419ae
commit
fa7e82127f
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Socionext Inc.
|
||||
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
* Copyright (C) 2025 Altera Corporation <www.altera.com>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
@@ -84,39 +85,74 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int sdhci_cdns_get_hrs06_mode(struct mmc *mmc)
|
||||
{
|
||||
unsigned int mode;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
mode = SDHCI_CDNS_HRS06_MODE_SD;
|
||||
} else {
|
||||
switch (mmc->selected_mode) {
|
||||
case MMC_LEGACY:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */
|
||||
break;
|
||||
|
||||
case MMC_HS:
|
||||
case MMC_HS_52:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
|
||||
break;
|
||||
|
||||
case UHS_DDR50:
|
||||
case MMC_DDR_52:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
|
||||
break;
|
||||
|
||||
case UHS_SDR104:
|
||||
case MMC_HS_200:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
|
||||
break;
|
||||
|
||||
case MMC_HS_400:
|
||||
case MMC_HS_400_ES:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
|
||||
break;
|
||||
|
||||
default:
|
||||
mode = SDHCI_CDNS_HRS06_MODE_SD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void sdhci_cdns_set_control_reg(struct sdhci_host *host)
|
||||
{
|
||||
struct mmc *mmc = host->mmc;
|
||||
struct sdhci_cdns_plat *plat = dev_get_plat(mmc->dev);
|
||||
unsigned int clock = mmc->clock;
|
||||
u32 mode, tmp;
|
||||
|
||||
/*
|
||||
* REVISIT:
|
||||
* The mode should be decided by MMC_TIMING_* like Linux, but
|
||||
* U-Boot does not support timing. Use the clock frequency instead.
|
||||
* Select HRS06 mode based on card type and selected timing mode.
|
||||
* For SD cards, always use SD mode (000b) as per Cadence user guide,
|
||||
* section 12.7 (HRS06), Part Number: IP6061.
|
||||
* For eMMC, use selected_mode to pick the appropriate mode.
|
||||
*/
|
||||
if (clock <= 26000000) {
|
||||
mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */
|
||||
} else if (clock <= 52000000) {
|
||||
if (mmc->ddr_mode)
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
|
||||
else
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
|
||||
} else {
|
||||
if (mmc->ddr_mode)
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
|
||||
else
|
||||
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
|
||||
}
|
||||
mode = sdhci_cdns_get_hrs06_mode(mmc);
|
||||
|
||||
tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS06);
|
||||
tmp &= ~SDHCI_CDNS_HRS06_MODE;
|
||||
tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_MODE, mode);
|
||||
writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06);
|
||||
|
||||
/*
|
||||
* For SD cards, program standard SDHCI Host Control2 UHS/voltage
|
||||
* registers for UHS-I support.
|
||||
*/
|
||||
if (IS_SD(mmc))
|
||||
sdhci_set_control_reg(host);
|
||||
|
||||
if (device_is_compatible(mmc->dev, "cdns,sd6hc"))
|
||||
sdhci_cdns6_phy_adj(mmc->dev, plat, mode);
|
||||
sdhci_cdns6_phy_adj(mmc->dev, plat, mmc->selected_mode);
|
||||
}
|
||||
|
||||
static const struct sdhci_ops sdhci_cdns_ops = {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Starfive.
|
||||
* Author: Kuan Lim Lee <kuanlim.lee@starfivetech.com>
|
||||
* Copyright (C) 2025 Altera Corporation <www.altera.com>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
@@ -77,6 +78,13 @@ static struct sdhci_cdns6_phy_cfg sd_ds_phy_cfgs[] = {
|
||||
{ "cdns,phy-dq-timing-delay-sd-ds", 0x00000001, },
|
||||
};
|
||||
|
||||
static struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
|
||||
{ "cdns,phy-dqs-timing-delay-sd-hs", 0x00380004, },
|
||||
{ "cdns,phy-gate-lpbk_ctrl-delay-sd-hs", 0x01A00040, },
|
||||
{ "cdns,phy-dll-slave-ctrl-sd-hs", 0x00000000, },
|
||||
{ "cdns,phy-dq-timing-delay-sd-hs", 0x00000001, },
|
||||
};
|
||||
|
||||
static struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
|
||||
{ "cdns,phy-dqs-timing-delay-semmc-sdr", 0x00380004, },
|
||||
{ "cdns,phy-gate-lpbk_ctrl-delay-emmc-sdr", 0x01A00040, },
|
||||
@@ -112,6 +120,13 @@ static struct sdhci_cdns6_ctrl_cfg sd_ds_ctrl_cfgs[] = {
|
||||
{ "cdns,ctrl-hrs07-timing-delay-sd-ds", 0x00080000, },
|
||||
};
|
||||
|
||||
static struct sdhci_cdns6_ctrl_cfg sd_hs_ctrl_cfgs[] = {
|
||||
{ "cdns,ctrl-hrs09-timing-delay-sd-hs", 0x0001800C, },
|
||||
{ "cdns,ctrl-hrs10-lpbk_ctrl-delay-sd-hs", 0x00030000, },
|
||||
{ "cdns,ctrl-hrs16-slave-ctrl-sd-hs", 0x00000000, },
|
||||
{ "cdns,ctrl-hrs07-timing-delay-sd-hs", 0x00080000, },
|
||||
};
|
||||
|
||||
static struct sdhci_cdns6_ctrl_cfg emmc_sdr_ctrl_cfgs[] = {
|
||||
{ "cdns,ctrl-hrs09-timing-delay-emmc-sdr", 0x0001800C, },
|
||||
{ "cdns,ctrl-hrs10-lpbk_ctrl-delay-emmc-sdr", 0x00030000, },
|
||||
@@ -186,27 +201,39 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
|
||||
int i, ret;
|
||||
|
||||
switch (mode) {
|
||||
case SDHCI_CDNS_HRS06_MODE_SD:
|
||||
case UHS_SDR12:
|
||||
case MMC_LEGACY:
|
||||
sdhci_cdns6_phy_cfgs = sd_ds_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = sd_ds_ctrl_cfgs;
|
||||
break;
|
||||
|
||||
case SDHCI_CDNS_HRS06_MODE_MMC_SDR:
|
||||
case SD_HS:
|
||||
case UHS_SDR25:
|
||||
case MMC_HS:
|
||||
sdhci_cdns6_phy_cfgs = sd_hs_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = sd_hs_ctrl_cfgs;
|
||||
break;
|
||||
|
||||
case UHS_SDR50:
|
||||
case MMC_HS_52:
|
||||
sdhci_cdns6_phy_cfgs = emmc_sdr_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = emmc_sdr_ctrl_cfgs;
|
||||
break;
|
||||
|
||||
case SDHCI_CDNS_HRS06_MODE_MMC_DDR:
|
||||
case UHS_DDR50:
|
||||
case MMC_DDR_52:
|
||||
sdhci_cdns6_phy_cfgs = emmc_ddr_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = emmc_ddr_ctrl_cfgs;
|
||||
break;
|
||||
|
||||
case SDHCI_CDNS_HRS06_MODE_MMC_HS200:
|
||||
case UHS_SDR104:
|
||||
case MMC_HS_200:
|
||||
sdhci_cdns6_phy_cfgs = emmc_hs200_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = emmc_hs200_ctrl_cfgs;
|
||||
break;
|
||||
|
||||
case SDHCI_CDNS_HRS06_MODE_MMC_HS400:
|
||||
case MMC_HS_400:
|
||||
case MMC_HS_400_ES:
|
||||
sdhci_cdns6_phy_cfgs = emmc_hs400_phy_cfgs;
|
||||
sdhci_cdns6_ctrl_cfgs = emmc_hs400_ctrl_cfgs;
|
||||
break;
|
||||
@@ -263,7 +290,7 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
|
||||
|
||||
int sdhci_cdns6_phy_init(struct udevice *dev, struct sdhci_cdns_plat *plat)
|
||||
{
|
||||
return sdhci_cdns6_phy_adj(dev, plat, SDHCI_CDNS_HRS06_MODE_SD);
|
||||
return sdhci_cdns6_phy_adj(dev, plat, MMC_LEGACY);
|
||||
}
|
||||
|
||||
int sdhci_cdns6_set_tune_val(struct sdhci_cdns_plat *plat, unsigned int val)
|
||||
|
||||
Reference in New Issue
Block a user