From f6400004a0871a884f2c965e5ad166b8c32be3d7 Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Mon, 27 Jan 2025 12:07:38 -0600 Subject: [PATCH 1/4] Revert "mmc: sdhci: Handle tuning error interrupts" This reverts commit 13dc7b7f158917dec94d79bdd4abea66f4f7e6ae. Signed-off-by: Erick Shepherd --- drivers/mmc/host/sdhci.c | 24 ++---------------------- drivers/mmc/host/sdhci.h | 1 - 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9f1ae0af30db3..6b8de165c8990 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); @@ -3602,24 +3601,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 +3610,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; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 15dc3dd9c0664..f219bdea8f280 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -158,7 +158,6 @@ #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_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 From 116cbed9fdcf8f7ee1b3bc340852690e7bdd277b Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Mon, 27 Jan 2025 12:15:02 -0600 Subject: [PATCH 2/4] Reapply "mmc: sdhci: Add support for "Tuning Error" interrupts" This reverts commit ffa0743bba605ca08ce44f6e7a24c306279c1b3f. Signed-off-by: Erick Shepherd --- drivers/mmc/host/sdhci.c | 10 ++++++++-- drivers/mmc/host/sdhci.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6b8de165c8990..535537cd86cb4 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3449,12 +3449,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); @@ -3989,7 +3995,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 f219bdea8f280..a315cee698094 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -158,6 +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_ERROR 0x04000000 #define SDHCI_INT_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 @@ -169,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 ( \ From b2ce17bb38f63f6e98234766e84aa1211d529b37 Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Mon, 27 Jan 2025 12:27:34 -0600 Subject: [PATCH 3/4] mmc: Update sdhci tune function to return errors Updates the sdhci_execute_tuning function to return the error code that was returned by the __sdhci_execute_tuning function. Previously this code was only stored in host->tuning_err and not actually returned. Signed-off-by: Erick Shepherd --- drivers/mmc/host/sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 535537cd86cb4..a0b120ffedfc9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2950,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: From 77f91798006af4c457115260977b276e651e83cf Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Mon, 27 Jan 2025 12:39:32 -0600 Subject: [PATCH 4/4] mmc: Allow tuning to be skipped during card init Add a new field to the mmc_host struct to track when the card should skip the initial tuning and use it to conditionally stop tuning in the mmc_sd_init_uhs_card function. Currently the new field only gets set when a DDR50 card fails to tune, which indicates the card does not support tuning. Signed-off-by: Erick Shepherd --- drivers/mmc/core/sd.c | 4 +++- include/linux/mmc/host.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) 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/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 */