From c29dd5c99ecd487bdd64717151134cef54de0425 Mon Sep 17 00:00:00 2001 From: Thomas Makin Date: Sat, 27 Dec 2025 03:00:47 +0000 Subject: [PATCH] [SPLIT] sdhci-tegra: fix tuning procedure --- drivers/mmc/host/sdhci-tegra.c | 82 +++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 9af96a021187..026bd5634d1b 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -415,8 +415,7 @@ 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_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");