summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe.Li <B37916@freescale.com>2014-09-05 16:29:44 +0800
committerYe.Li <B37916@freescale.com>2014-09-05 20:12:32 +0800
commit5caea2f86191c72e97651425a58dd8349c69ab3c (patch)
tree1c28de0e7ab11c77e6c45c13bcc23f1f72ec49e4
parent06552584b64b3906ad45a37edbee66ed722b3fe6 (diff)
downloadu-boot-imx-5caea2f86191c72e97651425a58dd8349c69ab3c.zip
u-boot-imx-5caea2f86191c72e97651425a58dd8349c69ab3c.tar.gz
u-boot-imx-5caea2f86191c72e97651425a58dd8349c69ab3c.tar.bz2
ENGR00329930-2 MMC: Fix debounce problem in the tuning algorithm
The boundary value for the tuning is not stable. It is not always can tune successfully. Current algorithm picks up the boundary value as min vertex, when starting finding the max vertex, the bounday value may fail and set the max vertex same to min. So a incorrect tuning value is got, and causes the SD card failed. Change the tuning algorithm to select a max window that every value in the window can tune successfully. So the debounce problem is fixed. Signed-off-by: Ye.Li <B37916@freescale.com> (cherry picked from commit b36fd693586dc70191b1d684f04410bd61325477)
-rw-r--r--drivers/mmc/mmc.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index efb6537..f1901c7 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2014 Freescale Semiconductor, Inc.
* Terry Lv
*
* Copyright 2008, Freescale Semiconductor, Inc
@@ -1085,7 +1085,8 @@ int sd_send_tuning_cmd(struct mmc *mmc)
void sd_uhsi_tuning(struct mmc *mmc)
{
- int min, max, avg;
+ int min, max_len, avg, len, temp;
+ int ret;
/* Tuning only required for SDR50 and SDR104 modes */
if (mmc->card_uhs_mode != SD_UHSI_FUNC_SDR50 &&
@@ -1093,30 +1094,36 @@ void sd_uhsi_tuning(struct mmc *mmc)
return;
/* Start with lowest value, increase it until CMD19 succeeds */
- min = mmc->tuning_min;
- while (min < mmc->tuning_max) {
- mmc->set_tuning(mmc, min);
- if (!sd_send_tuning_cmd(mmc))
- break;
- min += mmc->tuning_step;
- }
+ len = 0;
+ max_len = 0;
+ temp = mmc->tuning_min;
+ while (temp < mmc->tuning_max) {
+ mmc->set_tuning(mmc, temp);
+ if (!sd_send_tuning_cmd(mmc)) {
+ len++;
+ } else {
- /* Start with last successful value, increase it until CMD19 fails */
- max = min;
- while (max < mmc->tuning_max) {
- mmc->set_tuning(mmc, max);
- if (sd_send_tuning_cmd(mmc))
- break;
- max += mmc->tuning_step;
+ /* Searching the max window where CMD 19 succeeds for every value */
+ if (len > max_len) {
+ min = temp - len;
+ max_len = len;
+ }
+
+ len = 0;
+ }
+ temp += mmc->tuning_step;
}
/* Set tuning value to average of
* [lowest successful val, highest successful val]
*/
- avg = (min + max) / 2;
+ avg = min + (max_len / 2);
mmc->set_tuning(mmc, avg);
- sd_send_tuning_cmd(mmc);
- sd_send_tuning_cmd(mmc);
+ ret = sd_send_tuning_cmd(mmc);
+ ret |= sd_send_tuning_cmd(mmc);
+
+ if (ret)
+ printf("SD UHS-I tuning failed\n");
}
/* frequency bases */