summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorJeetesh Burman <jburman@nvidia.com>2015-03-24 23:16:48 +0530
committerMatthew Pedro <mapedro@nvidia.com>2015-05-04 13:46:42 -0700
commit0bb08ee76692a7ded9fb063b3bd77e1848658ced (patch)
treeb8e6364e4fe4d2366a28f07945b3e7cb4a5a416a /drivers/mmc
parent28c9354b7cbade8813e0e5dbe9937300219fbeb9 (diff)
mmc: tegra: Abort tuning if device is removed
For removable devices, check for the card presence status before issuing each tuning command. If the device is removed, abort tuning and return -ENOMEDIUM error. bug 1625262 Change-Id: I19d5dfe8e8bf4b9fc7ecc2c00cdfa01343012e68 Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com> Reviewed-on: http://git-master/r/398855 (cherry picked from commit 6e82d03dca5b421138e1c4f348efee71df2a865f) Signed-off-by: Jeetesh Burman <jburman@nvidia.com> Reviewed-on: http://git-master/r/721906 Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Tested-by: Matthew Pedro <mapedro@nvidia.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-tegra.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 9c2d1c1508ea..7b5eae384cc6 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -2168,6 +2168,11 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
int flags;
u32 intstatus;
+ if (gpio_is_valid(tegra_host->plat->cd_gpio) &&
+ (gpio_get_value(tegra_host->plat->cd_gpio) != 0)) {
+ dev_err(mmc_dev(sdhci->mmc), "device removed during tuning\n");
+ return -ENOMEDIUM;
+ }
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
while (sdhci_readl(sdhci, SDHCI_PRESENT_STATE) & mask) {
if (timeout == 0) {
@@ -2247,7 +2252,7 @@ out:
}
static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci,
- unsigned int starting_tap, bool expect_failure)
+ unsigned int starting_tap, bool expect_failure, int *status)
{
unsigned int tap_value = starting_tap;
int err;
@@ -2259,6 +2264,10 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci,
/* Run frequency tuning */
err = sdhci_tegra_issue_tuning_cmd(sdhci);
+ if (err == -ENOMEDIUM) {
+ *status = err;
+ return -1;
+ }
if (err && retry) {
retry--;
continue;
@@ -2271,6 +2280,7 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci,
tap_value++;
} while (tap_value <= MAX_TAP_VALUES);
+ *status = 0;
return tap_value;
}
@@ -2594,8 +2604,8 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
struct sdhci_tegra *tegra_host = pltfm_host->priv;
struct tap_window_data *tap_data;
struct tuning_ui tuning_ui[10];
- int err = 0, partial_win_start = 0, temp_margin = 0;
- unsigned int tap_value, calc_ui = 0;
+ int err = 0, partial_win_start = 0, temp_margin = 0, tap_value;
+ unsigned int calc_ui = 0;
u8 prev_boundary_end = 0, num_of_wins = 0;
u8 num_of_uis = 0, valid_num_uis = 0;
u8 ref_ui, first_valid_full_win = 0;
@@ -2620,7 +2630,12 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
do {
tap_data = &tuning_data->tap_data[num_of_wins];
/* Get the window start */
- tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true);
+ tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true,
+ &err);
+ if ((tap_value < 0) && (err == -ENOMEDIUM)) {
+ spin_unlock(&sdhci->lock);
+ return err;
+ }
tap_data->win_start = min_t(u8, tap_value, MAX_TAP_VALUES);
tap_value++;
if (tap_value >= MAX_TAP_VALUES) {
@@ -2638,7 +2653,11 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
/* Get the window end */
tap_value = sdhci_tegra_scan_tap_values(sdhci,
- tap_value, false);
+ tap_value, false, &err);
+ if ((tap_value < 0) && (err == -ENOMEDIUM)) {
+ spin_unlock(&sdhci->lock);
+ return err;
+ }
tap_data->win_end = min_t(u8, (tap_value - 1), MAX_TAP_VALUES);
tap_data->win_size = tap_data->win_end - tap_data->win_start;
tap_value++;