[PATCH] mmc: core: Modify the CMD1 transmission interval

From: Xiaojie Li

Date: Thu Aug 27 2026 - 05:16:45 EST


The current code's maximum udelay value is set to
64ms. Since it uses usleep_range(udelay, udelay*2),
this results in a maximum wait time of 128ms between
two consecutive CMD1 commands. For lower-performance eMMC chips,
local testing shows that compared to the old code which used
mmc_delay(10), the total time required to wait for the busy
bit in the CMD1 response to change has increased by approximately
300ms, negatively impacting the overall eMMC initialization time.

Although the current code sends the CMD1 command fewer times than
the old version, the total waiting time is significantly longer.
To address this, it's proposed to modify the CMD1 sending interval
to follow a pattern like 4ms, 6ms, 8ms, 10ms, 10ms, etc., effectively
capping the longest single wait at 10ms. Local testing confirms that
this approach can bring the total time waiting for the busy state
change very close to the performance level of the old code.

The eMMC chip used for testing: manfid= 0x00009b, name= Y0S128, mdt= 2022-10
The eMMC part number is: YMEC8B0TE2A2C3

Signed-off-by: Xiaojie Li <xiaojie.li2@xxxxxxxxxx>
---
drivers/mmc/core/mmc_ops.c | 85 ++++++++++++++++----------------------
1 file changed, 36 insertions(+), 49 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index a952cc8265af..3076666cf2ca 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -189,64 +189,51 @@ int mmc_go_idle(struct mmc_host *host)
return err;
}

-static int __mmc_send_op_cond_cb(void *cb_data, bool *busy)
-{
- struct mmc_op_cond_busy_data *data = cb_data;
- struct mmc_host *host = data->host;
- struct mmc_command *cmd = data->cmd;
- u32 ocr = data->ocr;
- int err = 0;
-
- err = mmc_wait_for_cmd(host, cmd, 0);
- if (err)
- return err;
-
- if (mmc_host_is_spi(host)) {
- if (!(cmd->resp[0] & R1_SPI_IDLE)) {
- *busy = false;
- return 0;
- }
- } else {
- if (cmd->resp[0] & MMC_CARD_BUSY) {
- *busy = false;
- return 0;
- }
- }
-
- *busy = true;
-
- /*
- * According to eMMC specification v5.1 section 6.4.3, we
- * should issue CMD1 repeatedly in the idle state until
- * the eMMC is ready. Otherwise some eMMC devices seem to enter
- * the inactive mode after mmc_init_card() issued CMD0 when
- * the eMMC device is busy.
- */
- if (!ocr && !mmc_host_is_spi(host))
- cmd->arg = cmd->resp[0] | BIT(30);
-
- return 0;
-}
-
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
{
struct mmc_command cmd = {};
+ unsigned int udelay = MMC_OP_COND_PERIOD_US;
+ unsigned int udelay_max = 10000;
+ unsigned long timeout = jiffies + msecs_to_jiffies(MMC_OP_COND_TIMEOUT_MS) + 1;
int err = 0;
- struct mmc_op_cond_busy_data cb_data = {
- .host = host,
- .ocr = ocr,
- .cmd = &cmd
- };

cmd.opcode = MMC_SEND_OP_COND;
cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;

- err = __mmc_poll_for_busy(host, MMC_OP_COND_PERIOD_US,
- MMC_OP_COND_TIMEOUT_MS,
- &__mmc_send_op_cond_cb, &cb_data);
- if (err)
- return err;
+ while (!time_after(jiffies, timeout)) {
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err)
+ break;
+
+ if (mmc_host_is_spi(host)) {
+ if (!(cmd.resp[0] & R1_SPI_IDLE))
+ break;
+ } else {
+ if (cmd.resp[0] & MMC_CARD_BUSY)
+ break;
+ }
+
+ /*
+ * According to eMMC specification v5.1 section 6.4.3, we
+ * should issue CMD1 repeatedly in the idle state until
+ * the eMMC is ready. Otherwise some eMMC devices seem to enter
+ * the inactive mode after mmc_init_card() issued CMD0 when
+ * the eMMC device is busy.
+ */
+ if (!ocr && !mmc_host_is_spi(host))
+ cmd.arg = cmd.resp[0] | BIT(30);
+
+ usleep_range(udelay, udelay + 1000);
+
+ if (udelay < udelay_max)
+ udelay += 2000;
+ else
+ udelay = udelay_max;
+ }
+
+ if (time_after(jiffies, timeout))
+ err = -ETIMEDOUT;

if (rocr && !mmc_host_is_spi(host))
*rocr = cmd.resp[0];
--
2.34.1