[SPLIT] sdhci-tegra: fix tuning procedure
This commit is contained in:
@@ -415,7 +415,6 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
|
|||||||
if (!(mask & SDHCI_RESET_ALL))
|
if (!(mask & SDHCI_RESET_ALL))
|
||||||
return;
|
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);
|
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;
|
u32 avg_tap_dly, val, min_tap_dly, max_tap_dly;
|
||||||
u8 fixed_tap, start_tap, end_tap, window_width;
|
u8 fixed_tap, start_tap, end_tap, window_width;
|
||||||
u8 thdupper, thdlower;
|
u8 thdupper, thdlower;
|
||||||
u8 num_iter;
|
u16 num_iter;
|
||||||
u32 clk_rate_mhz, period_ps, bestcase, worstcase;
|
u32 clk_rate_mhz, period_ps, bestcase, worstcase;
|
||||||
|
|
||||||
/* retain HW tuned tap to use incase if no correction is needed */
|
/* 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) &
|
end_tap = (val >> SDHCI_TEGRA_VNDR_TUN_STATUS1_END_TAP_SHIFT) &
|
||||||
SDHCI_TEGRA_VNDR_TUN_STATUS1_TAP_MASK;
|
SDHCI_TEGRA_VNDR_TUN_STATUS1_TAP_MASK;
|
||||||
window_width = end_tap - start_tap;
|
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.
|
* partial window includes edges of the tuning range.
|
||||||
* merged window includes more taps so window width is higher
|
* 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));
|
mmc_hostname(host->mmc));
|
||||||
tegra_sdhci_tap_correction(host, thdupper, thdlower,
|
tegra_sdhci_tap_correction(host, thdupper, thdlower,
|
||||||
fixed_tap);
|
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_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||||
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_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 set_dqs_trim = false;
|
||||||
bool do_hs400_dll_cal = false;
|
bool do_hs400_dll_cal = false;
|
||||||
bool set_padpipe_clk_override = false;
|
bool set_padpipe_clk_override = false;
|
||||||
u8 iter = TRIES_256;
|
u32 ret;
|
||||||
u32 val;
|
|
||||||
|
|
||||||
tegra_host->ddr_signaling = false;
|
tegra_host->ddr_signaling = false;
|
||||||
switch (timing) {
|
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_UHS_SDR104:
|
||||||
case MMC_TIMING_MMC_HS200:
|
case MMC_TIMING_MMC_HS200:
|
||||||
/* Don't set default tap on tunable modes. */
|
/* Don't set default tap on tunable modes. */
|
||||||
iter = TRIES_128;
|
set_num_tun_iter = true;
|
||||||
break;
|
break;
|
||||||
case MMC_TIMING_MMC_HS400:
|
case MMC_TIMING_MMC_HS400:
|
||||||
set_dqs_trim = true;
|
set_dqs_trim = true;
|
||||||
do_hs400_dll_cal = true;
|
do_hs400_dll_cal = true;
|
||||||
iter = TRIES_128;
|
|
||||||
set_padpipe_clk_override = true;
|
set_padpipe_clk_override = true;
|
||||||
|
set_num_tun_iter = true;
|
||||||
break;
|
break;
|
||||||
case MMC_TIMING_MMC_DDR52:
|
case MMC_TIMING_MMC_DDR52:
|
||||||
case MMC_TIMING_UHS_DDR50:
|
case MMC_TIMING_UHS_DDR50:
|
||||||
@@ -1084,18 +1111,6 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
|
|||||||
break;
|
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);
|
sdhci_set_uhs_signaling(host, timing);
|
||||||
|
|
||||||
tegra_sdhci_pad_autocalib(host);
|
tegra_sdhci_pad_autocalib(host);
|
||||||
@@ -1107,8 +1122,26 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
|
|||||||
|
|
||||||
/*set padpipe_clk_override*/
|
/*set padpipe_clk_override*/
|
||||||
if (set_padpipe_clk_override) {
|
if (set_padpipe_clk_override) {
|
||||||
tegra_sdhci_write_prod_settings(host,
|
ret = tegra_prod_set_by_name_partially(&host->ioaddr,
|
||||||
prod_device_states[timing]);
|
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)
|
if (set_dqs_trim)
|
||||||
tegra_sdhci_set_dqs_trim(host, tegra_host->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,
|
static int tegra_sdhci_init_pinctrl_info(struct device *dev,
|
||||||
struct sdhci_tegra *tegra_host)
|
struct sdhci_tegra *tegra_host)
|
||||||
{
|
{
|
||||||
if (!(tegra_get_platform() == TEGRA_PLATFORM_SILICON))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tegra_host->prod_list = devm_tegra_prod_get(dev);
|
tegra_host->prod_list = devm_tegra_prod_get(dev);
|
||||||
if (IS_ERR_OR_NULL(tegra_host->prod_list)) {
|
if (IS_ERR_OR_NULL(tegra_host->prod_list)) {
|
||||||
dev_dbg(dev, "Prod-setting not available\n");
|
dev_dbg(dev, "Prod-setting not available\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user