[PATCH v3 1/4] mmc: sdhci-cadence: abort failed tuning command on SD6HC

From: tze . yee . ng

Date: Fri Nov 06 2026 - 01:18:27 EST


From: Tze Yee Ng <tze.yee.ng@xxxxxxxxxx>

SD6HC uses a software tuning loop that calls mmc_send_tuning() for every
tap but never aborts a command that fails. When a CMD21 fails with a
command error the eMMC can remain in the Data state and reject the next
command, so the CMD6 that mmc_select_hs400() issues right after tuning
times out. SD is not affected because CMD12 cannot abort CMD19.

Request the command error from mmc_send_tuning() and, on a command
error, abort the tuning command with mmc_send_abort_tuning(), which is a
no-op for SD. This matches the generic sdhci tuning path.

Suggested-by: Tanmay Kathpalia <tanmay.kathpalia@xxxxxxxxxx>
Signed-off-by: Tze Yee Ng <tze.yee.ng@xxxxxxxxxx>
---
Changes in v3:
- New patch replacing the v2 1/4 PHY settle: abort the failed tuning
command (mmc_send_abort_tuning(), a no-op for SD) instead of masking
the post-tuning command timeout with a settle delay. (Tanmay Kathpalia)
---
drivers/mmc/host/sdhci-cadence-core.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-cadence-core.c b/drivers/mmc/host/sdhci-cadence-core.c
index 745455743b01..a94296cebf47 100644
--- a/drivers/mmc/host/sdhci-cadence-core.c
+++ b/drivers/mmc/host/sdhci-cadence-core.c
@@ -330,9 +330,18 @@ static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
}

for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
+ int cmd_error = 0;
+
if (sdhci_cdns_set_tune_val(host, i) ||
- mmc_send_tuning(host->mmc, opcode, NULL)) { /* bad */
+ mmc_send_tuning(host->mmc, opcode, &cmd_error)) { /* bad */
cur_streak = 0;
+ /*
+ * Abort a failed tuning command so an eMMC does not
+ * stay in the Data state and reject the next command;
+ * a no-op for SD.
+ */
+ if (cmd_error)
+ mmc_send_abort_tuning(host->mmc, opcode);
} else { /* good */
cur_streak++;
if (cur_streak > max_streak) {

--
2.43.7