diff options
author | Ye.Li <B37916@freescale.com> | 2014-09-05 16:29:44 +0800 |
---|---|---|
committer | Ye.Li <B37916@freescale.com> | 2014-09-05 20:12:32 +0800 |
commit | 5caea2f86191c72e97651425a58dd8349c69ab3c (patch) | |
tree | 1c28de0e7ab11c77e6c45c13bcc23f1f72ec49e4 | |
parent | 06552584b64b3906ad45a37edbee66ed722b3fe6 (diff) | |
download | u-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.c | 45 |
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 */ |