[SPLIT] sdhci-tegra: fix tuning procedure

This commit is contained in:
2025-12-27 03:00:47 +00:00
parent f7485a509b
commit c29dd5c99e

View File

@@ -415,7 +415,6 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
if (!(mask & SDHCI_RESET_ALL))
return;
if (tegra_get_platform() == TEGRA_PLATFORM_SILICON)
tegra_sdhci_write_prod_settings(host, "prod");
tegra_sdhci_set_tap(host, tegra_host->default_tap);
@@ -985,7 +984,7 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
u32 avg_tap_dly, val, min_tap_dly, max_tap_dly;
u8 fixed_tap, start_tap, end_tap, window_width;
u8 thdupper, thdlower;
u8 num_iter;
u16 num_iter;
u32 clk_rate_mhz, period_ps, bestcase, worstcase;
/* retain HW tuned tap to use incase if no correction is needed */
@@ -1017,7 +1016,33 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
end_tap = (val >> SDHCI_TEGRA_VNDR_TUN_STATUS1_END_TAP_SHIFT) &
SDHCI_TEGRA_VNDR_TUN_STATUS1_TAP_MASK;
window_width = end_tap - start_tap;
num_iter = host->tuning_loop_count;
num_iter = (sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0) &
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_MASK) >>
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT;
switch (num_iter) {
case 0:
num_iter = 40;
break;
case 1:
num_iter = 64;
break;
case 2:
num_iter = 128;
break;
case 3:
num_iter = 196;
break;
case 4:
num_iter = 256;
break;
default:
WARN_ON("Invalid value of number of tuning iterations");
}
host->tuning_loop_count = num_iter;
/*
* partial window includes edges of the tuning range.
* merged window includes more taps so window width is higher
@@ -1029,6 +1054,8 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
mmc_hostname(host->mmc));
tegra_sdhci_tap_correction(host, thdupper, thdlower,
fixed_tap);
pr_info("%s: Tap value after applying correction %u\n",
mmc_hostname(host->mmc), tegra_host->tuned_tap_delay);
}
}
@@ -1052,12 +1079,12 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
bool set_default_tap = false;
bool set_default_tap = false; // opposite of tuning_mode
bool set_num_tun_iter = false;
bool set_dqs_trim = false;
bool do_hs400_dll_cal = false;
bool set_padpipe_clk_override = false;
u8 iter = TRIES_256;
u32 val;
u32 ret;
tegra_host->ddr_signaling = false;
switch (timing) {
@@ -1066,13 +1093,13 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_MMC_HS200:
/* Don't set default tap on tunable modes. */
iter = TRIES_128;
set_num_tun_iter = true;
break;
case MMC_TIMING_MMC_HS400:
set_dqs_trim = true;
do_hs400_dll_cal = true;
iter = TRIES_128;
set_padpipe_clk_override = true;
set_num_tun_iter = true;
break;
case MMC_TIMING_MMC_DDR52:
case MMC_TIMING_UHS_DDR50:
@@ -1084,18 +1111,6 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
break;
}
val = sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0);
val &= ~(SDHCI_VNDR_TUN_CTRL0_TUN_ITER_MASK |
SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_MASK |
SDHCI_VNDR_TUN_CTRL0_MUL_M_MASK);
val |= (iter << SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT |
0 << SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_SHIFT |
1 << SDHCI_VNDR_TUN_CTRL0_MUL_M_SHIFT);
sdhci_writel(host, val, SDHCI_VNDR_TUN_CTRL0_0);
sdhci_writel(host, 0, SDHCI_TEGRA_VNDR_TUN_CTRL1_0);
host->tuning_loop_count = (iter == TRIES_128) ? 128 : 256;
sdhci_set_uhs_signaling(host, timing);
tegra_sdhci_pad_autocalib(host);
@@ -1107,8 +1122,26 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
/*set padpipe_clk_override*/
if (set_padpipe_clk_override) {
tegra_sdhci_write_prod_settings(host,
prod_device_states[timing]);
ret = tegra_prod_set_by_name_partially(&host->ioaddr,
prod_device_states[timing], tegra_host->prod_list,
0, SDHCI_TEGRA_VENDOR_CLOCK_CTRL,
SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"Failed to set padpipe clk override value for timing %d, %d\n",
timing, ret);
}
/* Set number of tuning iterations */
if (set_num_tun_iter) {
ret = tegra_prod_set_by_name_partially(&host->ioaddr,
prod_device_states[timing], tegra_host->prod_list,
0, SDHCI_VNDR_TUN_CTRL0_0,
SDHCI_VNDR_TUN_CTRL0_TUN_WORD_SEL_MASK <<
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"Failed to set number of iterations for timing %d, %d\n",
timing, ret);
}
if (set_dqs_trim)
tegra_sdhci_set_dqs_trim(host, tegra_host->dqs_trim);
@@ -1180,9 +1213,6 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
static int tegra_sdhci_init_pinctrl_info(struct device *dev,
struct sdhci_tegra *tegra_host)
{
if (!(tegra_get_platform() == TEGRA_PLATFORM_SILICON))
return 0;
tegra_host->prod_list = devm_tegra_prod_get(dev);
if (IS_ERR_OR_NULL(tegra_host->prod_list)) {
dev_dbg(dev, "Prod-setting not available\n");