diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 240469a881a27..3b63c3136412f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -668,7 +668,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) if (!mmc_host_is_spi(card->host) && (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || card->host->ios.timing == MMC_TIMING_UHS_DDR50 || - card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { + card->host->ios.timing == MMC_TIMING_UHS_SDR104) && + !card->host->skip_init_tune) { err = mmc_execute_tuning(card); /* @@ -681,6 +682,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) { pr_warn("%s: ddr50 tuning failed\n", mmc_hostname(card->host)); + card->host->skip_init_tune = 1; err = 0; } } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9f1ae0af30db3..a0b120ffedfc9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -32,7 +32,6 @@ #include #include -#include "../core/host.h" #include "sdhci.h" #define DRIVER_NAME "sdhci" @@ -305,7 +304,7 @@ static void sdhci_set_default_irqs(struct sdhci_host *host) if (host->tuning_mode == SDHCI_TUNING_MODE_2 || host->tuning_mode == SDHCI_TUNING_MODE_3) - host->ier |= SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR; + host->ier |= SDHCI_INT_RETUNE; sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); @@ -2951,7 +2950,8 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) sdhci_start_tuning(host); - host->tuning_err = __sdhci_execute_tuning(host, opcode); + err = __sdhci_execute_tuning(host, opcode); + host->tuning_err = err; sdhci_end_tuning(host); out: @@ -3450,12 +3450,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->data->error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); - } else if ((intmask & SDHCI_INT_DATA_CRC) && + } else if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R) { host->data->error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); + if (intmask & SDHCI_INT_TUNING_ERROR) { + u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + + ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; + sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); + } } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), intmask); @@ -3602,24 +3608,6 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask & SDHCI_INT_RETUNE) mmc_retune_needed(host->mmc); - if (intmask & SDHCI_INT_TUNING_ERR) { - u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); - /* - * Only complain and retune if we're actually using the - * host's tuning circuits. - */ - if (ctrl2 & SDHCI_CTRL_TUNED_CLK) { - sdhci_writew(host, - ctrl2 & ~SDHCI_CTRL_TUNED_CLK, - SDHCI_HOST_CONTROL2); - mmc_retune_recheck(host->mmc); - pr_err("%s: Unrecoverable error in tuning circuit\n", - mmc_hostname(host->mmc)); - } - sdhci_writel(host, SDHCI_INT_TUNING_ERR, - SDHCI_INT_STATUS); - } - if ((intmask & SDHCI_INT_CARD_INT) && (host->ier & SDHCI_INT_CARD_INT)) { sdhci_enable_sdio_irq_nolock(host, false); @@ -3629,8 +3617,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | - SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR | - SDHCI_INT_CARD_INT); + SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); if (intmask) { unexpected |= intmask; @@ -4009,7 +3996,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, } else *cmd_error = 0; - if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) { + if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) { *data_error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 15dc3dd9c0664..a315cee698094 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -158,7 +158,7 @@ #define SDHCI_INT_BUS_POWER 0x00800000 #define SDHCI_INT_AUTO_CMD_ERR 0x01000000 #define SDHCI_INT_ADMA_ERROR 0x02000000 -#define SDHCI_INT_TUNING_ERR 0x04000000 +#define SDHCI_INT_TUNING_ERROR 0x04000000 #define SDHCI_INT_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 @@ -170,7 +170,7 @@ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \ - SDHCI_INT_BLK_GAP) + SDHCI_INT_BLK_GAP | SDHCI_INT_TUNING_ERROR) #define SDHCI_INT_ALL_MASK ((unsigned int)-1) #define SDHCI_CQE_INT_ERR_MASK ( \ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 62a6847a3b6f0..5355116f7aff5 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -450,6 +450,7 @@ struct mmc_host { unsigned int use_spi_crc:1; unsigned int claimed:1; /* host exclusively claimed */ unsigned int doing_init_tune:1; /* initial tuning in progress */ + unsigned int skip_init_tune:1; /* skip the initial tuning */ unsigned int can_retune:1; /* re-tuning can be used */ unsigned int doing_retune:1; /* re-tuning in progress */ unsigned int retune_now:1; /* do re-tuning at next req */