[PATCH v2 2/3] mmc: meson-gx: honour the busy timeout for R1b commands

From: Igor Velkov via B4 Relay

Date: Thu Oct 08 2026 - 10:36:07 EST


From: Igor Velkov <iav@xxxxxx>

For a command without data the driver programs a fixed 1024 ms into the
CMD_CFG timeout field, and for R1b the controller waits for the card to
release busy within that time. The core sends erase and cache flush as
R1b with busy timeouts of up to 60 s and 30 s, and the controller gives
up after one second:

mmc_erase: erase error -110, status 0x0
mmc1: cache flush error -110

Program the timeout from cmd->busy_timeout, rounded up to a power of
two and kept within 1024..32768 ms, the range the field holds. sdhci
takes its command timeout from cmd->busy_timeout in the same way.

Fixes: 51c5d8447bd7 ("MMC: meson: initial support for GX platforms")
Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@xxxxxx>
---
drivers/mmc/host/meson-gx-mmc.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 06479ba38525..dd7d3d67f029 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -216,6 +216,20 @@ static unsigned int meson_mmc_get_timeout_msecs(struct mmc_data *data)
return min_t(unsigned int, timeout, SD_EMMC_CMD_TIMEOUT_MAX);
}

+/* For R1b the controller waits for busy to be released within this timeout. */
+static unsigned int meson_mmc_get_cmd_timeout_msecs(struct mmc_command *cmd)
+{
+ unsigned int timeout = cmd->busy_timeout;
+
+ if (!timeout)
+ return SD_EMMC_CMD_TIMEOUT;
+
+ timeout = roundup_pow_of_two(timeout);
+
+ return clamp_t(unsigned int, timeout, SD_EMMC_CMD_TIMEOUT,
+ SD_EMMC_CMD_TIMEOUT_MAX);
+}
+
static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd)
{
if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error)
@@ -842,7 +856,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
} else {
cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK,
- ilog2(SD_EMMC_CMD_TIMEOUT));
+ ilog2(meson_mmc_get_cmd_timeout_msecs(cmd)));
}

/* Last descriptor */

--
2.43.0