Re: [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC

From: Kathpalia, Tanmay

Date: Sun Oct 25 2026 - 16:18:07 EST


Hi Tze,

Sorry for the slow reply. I spent some time going through the tuning
path against the eMMC specification before answering.

On 09-10-2026 07:44, tze.yee.ng@xxxxxxxxxx wrote:
From: Tze Yee Ng <tze.yee.ng@xxxxxxxxxx>

On SD6HC the first command after tuning may be an R1b busy command (e.g.
the HS200->HS CMD6 during HS400 selection) that can time out on some eMMC
unless the PHY is given a brief settle after the final tap and DLL
re-lock.

Add a single 5 to 5.5 ms settle at the end of the SD6HC tuning path,
after the winning tap is applied, rather than on every set_tune_val()
call in the scan.

Signed-off-by: Tze Yee Ng <tze.yee.ng@xxxxxxxxxx>
---
Changes in v2:
- Moved the 5ms PHY settle out of the per-tap tuning loop to a single
settle after the winning tap, on the success path only.
(Adrian Hunter, Tanmay Kathpalia)
- Rewrote the comment to explain this specific call site.
(Tanmay Kathpalia)
---
drivers/mmc/host/sdhci-cadence-core.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-cadence-core.c b/drivers/mmc/host/sdhci-cadence-core.c
index 745455743b01..c25b235ee909 100644
--- a/drivers/mmc/host/sdhci-cadence-core.c
+++ b/drivers/mmc/host/sdhci-cadence-core.c
@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/module.h>
@@ -352,8 +353,11 @@ static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
return ret;
/* Block gap tuning is only required for SD4HC, not for SD6HC */
- if (host->version >= SDHCI_SPEC_420)
+ if (host->version >= SDHCI_SPEC_420) {
+ /* Let the PHY settle after the final tap and DLL re-lock. */
+ usleep_range(5000, 5500);
return 0;
+ }

Every scan step re-locks the DLL and immediately issues CMD21, which
carries an R1 response on the CMD line, with no delay. The eMMC
specification moves the card to the Data state for CMD21 and treats
any command issued from that state as illegal. If a tap fails with a
command error, the card can remain in the Data state, so the next
command - the CMD6 that mmc_select_hs400() sends straight after
tuning gets no response and the host reports a response timeout.

Adrian added mmc_abort_tuning() in commit e711f0309109 ("mmc: mmc:
Introduce mmc_abort_tuning()") for exactly this case: a timed-out
tuning command can leave the card still processing it, and the eMMC
specification allows CMD12 to stop CMD21.

This also fits with your report that SD SDR104 never fails: CMD12
isn't defined for CMD19, which is why mmc_send_abort_tuning() is a
no-op for it. So this theory is consistent with the SD/eMMC split
you observed.

I'll test aborting each CMD21 that fails with a command error, and
also a single abort after tuning completes, to see whether that
removes the CMD6 failure. If you can test the same, that would help.
I would prefer that fix over an unconditional sleep.

Regards,
Tanmay