diff options
author | Bibek Basu <bbasu@nvidia.com> | 2015-06-23 11:11:44 +0530 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2015-06-24 14:53:54 -0700 |
commit | 56c637648a297c98c1e8b7de1438168cf56cfcf9 (patch) | |
tree | b7bbbe056c6daf1dab78395b407afb77bb832aaf | |
parent | c041d757963de9373a1ae5ef9d2940bb57a2d14b (diff) |
mmc: tegra: reverify tuning best tap
tuning best_tap_value at times throws wrong value leading
to data crc error. To make the SW robust, reverify tuning
best_tap_value with previously calculated and then only
proceed.
Bug 200107220
Bug 200102727
Change-Id: If58194bcfd1f025b15f827b233b534b8fc999327
Signed-off-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-on: http://git-master/r/761054
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shreshtha Sahu <ssahu@nvidia.com>
Tested-by: Shreshtha Sahu <ssahu@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r-- | drivers/mmc/host/sdhci-tegra.c | 99 |
1 files changed, 59 insertions, 40 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 52aeac80ca31..4e70b5bd7413 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1963,6 +1963,7 @@ static int find_best_tap_value(struct tegra_tuning_data *tuning_data, u8 i = 0, sel_win = 0; int pref_win = 0, curr_win_size = 0; int best_tap_value = 0; + static int prev_best_tap; for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) { tap_data = &temp_tap_data[i]; @@ -1999,9 +2000,16 @@ static int find_best_tap_value(struct tegra_tuning_data *tuning_data, tuning_data->calc_values.t2t_vmax); } - pr_info("best tap win - (%d-%d), best tap value %d\n", - tap_data->win_start, tap_data->win_end, best_tap_value); - return best_tap_value; + pr_info("best tap win - (%d-%d), best tap value %d prev_best_tap %d\n", + tap_data->win_start, tap_data->win_end, + best_tap_value, prev_best_tap); + if (prev_best_tap >= tap_data->win_start && + prev_best_tap <= tap_data->win_end) + return best_tap_value; + else { + prev_best_tap = best_tap_value; + return -EAGAIN; + } } static int sdhci_tegra_calculate_best_tap(struct sdhci_host *sdhci, @@ -2053,6 +2061,10 @@ static int sdhci_tegra_calculate_best_tap(struct sdhci_host *sdhci, best_tap_value = find_best_tap_value(tuning_data, temp_tap_data, vmin); + if (best_tap_value == -EAGAIN) { + err = -EAGAIN; + break; + } if (best_tap_value < 0) vmin += 50; } while (best_tap_value < 0); @@ -3120,7 +3132,7 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode) struct sdhci_tegra *tegra_host = pltfm_host->priv; struct tegra_tuning_data *tuning_data; const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; - int err; + int err = 0; u16 ctrl_2; u32 misc_ctrl; u32 ier; @@ -3188,49 +3200,56 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode) force_retuning = true; tegra_host->force_retune = false; } + do { + tegra_host->tuning_status = 0; + err = sdhci_tegra_get_tuning_constraints(sdhci, force_retuning); + if (err) { + dev_err(mmc_dev(sdhci->mmc), + "Failed to get tuning constraints\n"); + goto out; + } - tegra_host->tuning_status = 0; - err = sdhci_tegra_get_tuning_constraints(sdhci, force_retuning); - if (err) { - dev_err(mmc_dev(sdhci->mmc), - "Failed to get tuning constraints\n"); - goto out; - } + for (i = 0; i < tegra_host->tuning_freq_count; i++) { + tuning_data = &tegra_host->tuning_data[i]; + if (tuning_data->tuning_done && !force_retuning) + continue; - for (i = 0; i < tegra_host->tuning_freq_count; i++) { - tuning_data = &tegra_host->tuning_data[i]; - if (tuning_data->tuning_done && !force_retuning) - continue; + SDHCI_TEGRA_DBG("%s: Setting tuning freq%d\n", + mmc_hostname(sdhci->mmc), tuning_data->freq_hz); + tegra_sdhci_set_clock(sdhci, tuning_data->freq_hz); - SDHCI_TEGRA_DBG("%s: Setting tuning freq%d\n", - mmc_hostname(sdhci->mmc), tuning_data->freq_hz); - tegra_sdhci_set_clock(sdhci, tuning_data->freq_hz); - - SDHCI_TEGRA_DBG("%s: Calculating estimated tuning values\n", - mmc_hostname(sdhci->mmc)); - err = calculate_estimated_tuning_values(tegra_host->speedo, - tuning_data, tegra_host->boot_vcore_mv); - if (err) - goto out; + SDHCI_TEGRA_DBG( + "%s: Calculating estimated tuning values\n", + mmc_hostname(sdhci->mmc)); + err = calculate_estimated_tuning_values( + tegra_host->speedo, tuning_data, + tegra_host->boot_vcore_mv); + if (err) + goto out; - SDHCI_TEGRA_DBG("Running tuning...\n"); - err = sdhci_tegra_run_tuning(sdhci, tuning_data); - if (err) - goto out; + SDHCI_TEGRA_DBG("Running tuning...\n"); + err = sdhci_tegra_run_tuning(sdhci, tuning_data); + if (err) + goto out; - SDHCI_TEGRA_DBG("calculating best tap value\n"); - err = sdhci_tegra_calculate_best_tap(sdhci, tuning_data); - if (err) - goto out; + SDHCI_TEGRA_DBG("calculating best tap value\n"); + err = sdhci_tegra_calculate_best_tap(sdhci, + tuning_data); + if (err == -EAGAIN) + break; + else if (err) + goto out; - err = sdhci_tegra_verify_best_tap(sdhci); - if (!err && !set_retuning) { - tuning_data->tuning_done = true; - tegra_host->tuning_status |= TUNING_STATUS_DONE; - } else { - tegra_host->tuning_status |= TUNING_STATUS_RETUNE; + err = sdhci_tegra_verify_best_tap(sdhci); + if (!err && !set_retuning) { + tuning_data->tuning_done = true; + tegra_host->tuning_status |= TUNING_STATUS_DONE; + } else { + tegra_host->tuning_status |= + TUNING_STATUS_RETUNE; + } } - } + } while (err == -EAGAIN); out: /* Release any override core voltages set */ sdhci_tegra_set_tuning_voltage(sdhci, 0); |