[PATCH] mci: imx-esdhc-pbl: clear stale INT_STATUS before first PBL transfer

Johannes Schneider johannes.schneider at leica-geosystems.com
Wed Jun 17 14:35:54 PDT 2026


PBL load_bl33 on i.MX8MM takes roughly three times longer than on
i.MX8MP for what turned out to be an asymmetric code path in this
driver rather than a hardware difference. The two PBL load wrappers
shared imx_esdhc_init() but diverged on whether they issue any
command before the bulk CMD18:

  imx8mp_esdhc_load_image() goes through esdhc_bootpart_active()
  to pick a read offset, which internally issues CMD8 (SEND_EXT_CSD).
  esdhc_send_cmd() clears SDHCI_INT_STATUS as a side effect.

  imx8m_esdhc_load_image() (i.MX8MM, 8MN, 8MQ) skips that step and
  issues CMD18 directly on whatever the BootROM left behind.

Bisect on i.MX8MM, all measurements from the same hardware/board/
eMMC, three reboots each, run-to-run variance +-1 ms:

  no probe, no clear                  ~1240 ms   (original baseline)
  CMD8 (SEND_EXT_CSD) + INT_STATUS=~0  ~770 ms
  INT_STATUS=~0 only                   ~727 ms
  production INT_STATUS=~0 only         637 ms

The 90 ms gap between the last two rows is the wall-clock cost of
the diagnostic CMD8 itself; subtracting it the INT_STATUS clear
explains the entire 8MM vs 8MP gap. SDHCI_INT_STATUS=0 both before
and after the CMD18 on the slow path: no CRC, no timeout, no
end-bit error. So the slowdown is not from retries on the data
line.

Hypothesis (unproven): the BootROM completes its last transfer
with stale CMD_COMPLETE or XFER_COMPLETE bits in INT_STATUS, and
the controller's command FSM races against those on the next
CMD18. A W1C write to the register short-circuits the race.

Linux's mmc-core does a full eMMC re-init from scratch (CMD0 +
reset + tune) after PBL, so steady-state HS400ES throughput is
unaffected.

Place the clear in the shared imx_esdhc_init() right after
esdhc_populate_sdhci() so the i.MX8MM, 8MN, and 8MQ paths all
pick it up. SDHCI_INT_STATUS is W1C, so on chips where no bits
were set (i.MX6, i.MX7, i.MX8MP after esdhc_bootpart_active)
the write is a no-op -- harmless.

Measured on two i.MX8M boards with SanDisk industrial eMMC
(manfid 0x9e, oemid 0x0100):

  i.MX8MM + IM032G (32 GiB):
                                BEFORE       AFTER       delta
    PBL load_bl33               1240 ms      637 ms      -603 ms (-49%)
    Linux read (64 MiB direct)   244 MB/s    254 MB/s    (noise)
  i.MX8MP + IM128G (128 GiB):
    PBL load_bl33                366 ms      321 ms       -45 ms (-12%)
    Linux read (64 MiB direct)   173 MB/s    182 MB/s    (noise)

Signed-off-by: Johannes Schneider <johannes.schneider at leica-geosystems.com>
---
 drivers/mci/imx-esdhc-pbl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 1040a0df..5fb89aa4 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -129,6 +129,9 @@ static void imx_esdhc_init(struct fsl_esdhc_host *host,
 	host->socdata = data;
 	esdhc_populate_sdhci(host);
 
+	/* Discard any interrupt bits the BootROM left set. */
+	sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0u);
+
 	sdhci_write32(&host->sdhci, IMX_SDHCI_WML,
 		      FIELD_PREP(WML_WR_BRST_LEN, 16)         |
 		      FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) |
-- 
2.43.0




More information about the barebox mailing list