mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe
@ 2026-06-27 19:43 Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 2/7] mci: sdhci: bail out on ADMA/transfer errors instead of hanging Johannes Schneider
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

dma_mapping_error() dereferenced dev->dma_mask unconditionally, while the
neighbouring cpu_to_dma()/dma_to_cpu() helpers already guard with 'dev &&'.
Callers with no device (e.g. the PBL SDHCI layer, which has no mci/device
yet) thus dereferenced a NULL pointer. Guard the dereference.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 include/dma.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/dma.h b/include/dma.h
index b8016c2e89..8f8ac78cdc 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -70,7 +70,7 @@ static inline void dma_set_mask(struct device *dev, u64 dma_mask)
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	return dma_addr == DMA_ERROR_CODE ||
-		(dev->dma_mask && dma_addr > dev->dma_mask);
+		(dev && dev->dma_mask && dma_addr > dev->dma_mask);
 }
 
 static inline dma_addr_t cpu_to_dma(struct device *dev, void *cpu_addr)

base-commit: da91ab6cb505fb09415bf8df3fae552e7b37c5e1
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 2/7] mci: sdhci: bail out on ADMA/transfer errors instead of hanging
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 3/7] mci: sdhci: honor BROKEN_ADMA_ZEROLEN_DESC / NO_ENDATTR_IN_NOPDESC quirks Johannes Schneider
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

sdhci_transfer_data_dma() only watched for the completion and DMA-boundary
interrupts, so a transfer/ADMA error (SDHCI_INT_ERROR, e.g. an ADMA
descriptor fault) left it spinning until the 10s timeout. Check the error
bits and abort the transfer with -EIO, dumping the ADMA error status.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/sdhci.c | 8 ++++++++
 drivers/mci/sdhci.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c
index 3474ef129b..ccd5d4b83c 100644
--- a/drivers/mci/sdhci.c
+++ b/drivers/mci/sdhci.c
@@ -779,6 +779,14 @@ int sdhci_transfer_data_dma(struct sdhci *sdhci, struct mci_cmd *cmd,
 			goto out;
 		}
 
+		/* e.g. ADMA error: SDHCI_INT_ERROR without a data-error bit */
+		if (irqstat & SDHCI_INT_ERROR) {
+			dev_err(dev, "transfer error: int 0x%08x adma 0x%02x\n",
+				irqstat, sdhci_read8(sdhci, SDHCI_ADMA_ERROR));
+			ret = -EIO;
+			goto out;
+		}
+
 		/*
 		 * We currently don't do anything fancy with DMA
 		 * boundaries, but as we can't disable the feature
diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h
index d1f05ac968..558469e8ab 100644
--- a/drivers/mci/sdhci.h
+++ b/drivers/mci/sdhci.h
@@ -111,6 +111,7 @@
 #define  SDHCI_RESET_DATA			BIT(2)
 #define SDHCI_INT_STATUS					0x30
 #define SDHCI_INT_NORMAL_STATUS					0x30
+#define  SDHCI_INT_ADMA_ERROR			BIT(25)
 #define  SDHCI_INT_DATA_END_BIT			BIT(22)
 #define  SDHCI_INT_DATA_CRC			BIT(21)
 #define  SDHCI_INT_DATA_TIMEOUT			BIT(20)
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 3/7] mci: sdhci: honor BROKEN_ADMA_ZEROLEN_DESC / NO_ENDATTR_IN_NOPDESC quirks
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 2/7] mci: sdhci: bail out on ADMA/transfer errors instead of hanging Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 4/7] mci: imx-esdhc: mark the uSDHC ADMA2 descriptor quirks Johannes Schneider
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

The ADMA2 table builder always emitted a 64 KiB chunk as a length-0 descriptor
(the 16-bit length field encodes 65536 as 0) and terminated the table with a
separate NOP-END descriptor. Some controllers mishandle these forms; Linux
gates the workarounds behind SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (cap the
length below 64 KiB so it is never 0) and SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
(mark END on the last transfer descriptor instead of a trailing NOP-END).

Add both quirks to the shared SDHCI layer and honor them in the table builder.
Controllers that set neither keep the previous behaviour exactly, so this is a
no-op for everyone until a host driver opts in.

Assisted-by: Claude Opus 4.8 (1M context)
Assisted-by: GitHub Copilot CLI (gpt-5.5)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/sdhci.c | 35 ++++++++++++++++++++++++-----------
 drivers/mci/sdhci.h |  4 ++++
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c
index ccd5d4b83c..8ed8a59342 100644
--- a/drivers/mci/sdhci.c
+++ b/drivers/mci/sdhci.c
@@ -646,31 +646,44 @@ static int sdhci_adma_write_desc(struct sdhci *host, void **desc,
 static int sdhci_adma_build_table(struct sdhci *host, dma_addr_t addr,
 				  unsigned int len)
 {
+	unsigned int max_len = SDHCI_ADMA2_MAX_LEN;
 	void *desc = host->adma_table;
 	int ret;
 
+	/*
+	 * Some controllers (e.g. the i.MX uSDHC) cannot handle a length-0
+	 * descriptor, which the 16-bit length field uses to encode the full
+	 * SDHCI_ADMA2_MAX_LEN. Cap the chunk just below that so the length is
+	 * never 0.
+	 */
+	if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
+		max_len = SDHCI_ADMA2_MAX_LEN - 4;
+
 	while (len) {
-		unsigned int chunk = min_t(unsigned int, len,
-					   SDHCI_ADMA2_MAX_LEN);
+		unsigned int chunk = min_t(unsigned int, len, max_len);
+		unsigned int attr = ADMA2_TRAN_VALID;
 
+		len -= chunk;
 		/*
-		 * The length field is 16-bit; a length of 0 encodes
-		 * SDHCI_ADMA2_MAX_LEN bytes per the SD Host Controller
-		 * specification.
+		 * Controllers that ignore the END attribute in a trailing NOP
+		 * descriptor want END on the last transfer descriptor instead
+		 * (SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC).
 		 */
-		ret = sdhci_adma_write_desc(host, &desc, addr, chunk & 0xffff,
-					    ADMA2_TRAN_VALID);
+		if (!len && (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC))
+			attr |= ADMA2_END;
+
+		ret = sdhci_adma_write_desc(host, &desc, addr, chunk & 0xffff, attr);
 		if (ret)
 			return ret;
 
 		addr += chunk;
-		len -= chunk;
 	}
 
-	/* Append a terminating descriptor (nop, end, valid). */
-	ret = sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID);
+	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC)
+		return 0;
 
-	return ret;
+	/* Append a terminating descriptor (nop, end, valid). */
+	return sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID);
 }
 
 void sdhci_setup_data_dma(struct sdhci *sdhci, struct mci_data *data,
diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h
index 558469e8ab..cb3b6d2b17 100644
--- a/drivers/mci/sdhci.h
+++ b/drivers/mci/sdhci.h
@@ -315,6 +315,10 @@ struct sdhci {
 	bool v4_mode;		/* Host Version 4 Enable */
 
 	unsigned int quirks;
+/* Controller ignores the END attribute in a NOP ADMA2 descriptor */
+#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC	BIT(6)
+/* Controller cannot handle a length-0 (== 64 KiB) ADMA2 descriptor */
+#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC	BIT(11)
 #define SDHCI_QUIRK_MISSING_CAPS		BIT(27)
 	unsigned int quirks2;
 /* The system physically doesn't support 1.8v, even if the host does */
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 4/7] mci: imx-esdhc: mark the uSDHC ADMA2 descriptor quirks
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 2/7] mci: sdhci: bail out on ADMA/transfer errors instead of hanging Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 3/7] mci: sdhci: honor BROKEN_ADMA_ZEROLEN_DESC / NO_ENDATTR_IN_NOPDESC quirks Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 5/7] mci: imx-esdhc: support HS400 and HS400ES on i.MX8M Johannes Schneider
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

The i.MX uSDHC ADMA2 engine cannot handle a length-0 (64 KiB) descriptor and
ignores the END attribute in a trailing NOP descriptor; large ADMA transfers
hang otherwise. Set SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC and
SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC so the shared table builder emits a safe
descriptor shape, matching Linux sdhci-esdhc-imx. esdhc_populate_sdhci() runs
for both the PBL and the proper driver, so this covers every uSDHC ADMA path.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/imx-esdhc-common.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index eb6a71915f..d31a2ad779 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -285,6 +285,14 @@ void esdhc_populate_sdhci(struct fsl_esdhc_host *host)
 		host->sdhci.read16 = esdhc_op_read16_le_tuning;
 		host->sdhci.write16 = esdhc_op_write16_le_tuning;
 	}
+
+	/*
+	 * The uSDHC ADMA2 engine mishandles a length-0 (64 KiB) descriptor and
+	 * the END attribute in a trailing NOP descriptor.
+	 */
+	if (esdhc_is_usdhc(host))
+		host->sdhci.quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
+				      SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
 }
 
 static bool esdhc_use_pio_mode(void)
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 5/7] mci: imx-esdhc: support HS400 and HS400ES on i.MX8M
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
                   ` (2 preceding siblings ...)
  2026-06-27 19:43 ` [PATCH v1 4/7] mci: imx-esdhc: mark the uSDHC ADMA2 descriptor quirks Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 6/7] mci: imx-esdhc: make the transfer mode selectable (PIO/SDMA/ADMA2) Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader Johannes Schneider
  5 siblings, 0 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

The i.MX8M uSDHC can run HS400/HS400ES, but the barebox driver topped out at
HS200: fsl,imx8mm-usdhc was routed to usdhc_imx6sx_data (HS200 only) and the
HS400 timing/strobe-DLL path was absent.

Add a usdhc_imx8mm_data with ESDHC_FLAG_HS200 | HS400 | HS400_ES and point the
imx8mm/imx8mn/imx8mp compatibles at it. Add the strobe-DLL register block and
esdhc_set_strobe_dll() (gate the card clock, pulse reset, program the read
delay target, poll for REF/SLV lock), an HS400 case in usdhc_set_timing()
(set MIX_CTRL DDREN|HS400_EN, re-apply the clock, run the strobe DLL),
HS400ES handling, and MMC_CAP2_HS400[_ES] advertisement gated on the flags.
The MIXCTRL preserve-mask in __esdhc_send_cmd() is widened from bits 22-25 to
22-27 so the HS400 mode bits survive command writes. Strobe read delay is
configurable via the existing fsl,strobe-dll-delay-target DT binding
(default 0x7).

usdhc_imx8mm_data keeps ESDHC_FLAG_STD_TUNING: barebox already drove these
parts (fsl,imx8mm-usdhc) at HS200 with standard tuning, and U-Boot uses it for
the i.MX8M family too. (Linux uses manual tuning for imx8mm; moving barebox to
manual tuning would be a separate, separately-tested change.)

Register sequence mirrors Linux sdhci-esdhc-imx.c; the barebox idiom follows
the Rockchip dwcmshc HS400 support.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/imx-esdhc-common.c |  4 +-
 drivers/mci/imx-esdhc.c        | 91 ++++++++++++++++++++++++++++++++--
 drivers/mci/imx-esdhc.h        | 14 ++++++
 3 files changed, 103 insertions(+), 6 deletions(-)

diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index d31a2ad779..a0c2dee32d 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -360,8 +360,8 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
 	if (esdhc_is_usdhc(host)) {
 		/* write lower-half of xfertyp to mixctrl */
 		mixctrl = xfertyp;
-		/* Keep the bits 22-25 of the register as is */
-		mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
+		/* keep tuning bits (22-25) and HS400 mode bits (26-27) as is */
+		mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0x3F << 22));
 		mixctrl |= mci_timing_is_ddr(host->sdhci.timing) ? MIX_CTRL_DDREN : 0;
 		sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
 	}
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index ba33daffc4..e123bd3ede 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -274,12 +274,51 @@ static int esdhc_change_pinstate(struct fsl_esdhc_host *host,
 }
 
 
+/* Ported from Linux esdhc_set_strobe_dll() in drivers/mmc/host/sdhci-esdhc-imx.c */
+static void esdhc_set_strobe_dll(struct fsl_esdhc_host *host)
+{
+	u32 strobe_delay, v;
+	int ret;
+
+	/* disable the card clock before (re)programming the strobe DLL */
+	sdhci_write32(&host->sdhci, ESDHC_VENDOR_SPEC,
+		      sdhci_read32(&host->sdhci, ESDHC_VENDOR_SPEC) &
+		      ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON);
+	ret = esdhc_poll(host, ESDHC_PRSSTAT, v, (v & ESDHC_CLOCK_GATE_OFF),
+			 100 * USECOND);
+	if (ret)
+		dev_warn(host->dev, "card clock not gated off before strobe DLL\n");
+
+	/* force a reset on the strobe DLL, then clear it before any setting */
+	sdhci_write32(&host->sdhci, ESDHC_STROBE_DLL_CTRL,
+		      ESDHC_STROBE_DLL_CTRL_RESET);
+	sdhci_write32(&host->sdhci, ESDHC_STROBE_DLL_CTRL, 0);
+
+	if (host->boarddata.strobe_dll_delay_target)
+		strobe_delay = host->boarddata.strobe_dll_delay_target;
+	else
+		strobe_delay = ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT;
+
+	v = ESDHC_STROBE_DLL_CTRL_ENABLE |
+	    ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT |
+	    (strobe_delay << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
+	sdhci_write32(&host->sdhci, ESDHC_STROBE_DLL_CTRL, v);
+
+	ret = esdhc_poll(host, ESDHC_STROBE_DLL_STATUS, v,
+			 (v & ESDHC_STROBE_DLL_STS_REF_LOCK) &&
+			 (v & ESDHC_STROBE_DLL_STS_SLV_LOCK),
+			 50 * USECOND);
+	if (ret)
+		dev_warn(host->dev,
+			 "HS400 strobe DLL not locked in 50us, status 0x%08x\n", v);
+}
+
 static void usdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing)
 {
 	u32 mixctrl;
 
 	mixctrl = sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL);
-	mixctrl &= ~MIX_CTRL_DDREN;
+	mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN);
 
 	switch (timing) {
 	case MMC_TIMING_UHS_DDR50:
@@ -296,6 +335,14 @@ static void usdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing
 			sdhci_write32(&host->sdhci, IMX_SDHCI_DLL_CTRL, v);
 		}
 		break;
+	case MMC_TIMING_MMC_HS400:
+		/*
+		 * HS400 is a DDR mode; the strobe DLL is set up later from
+		 * esdhc_set_ios() once the HS400 clock is running.
+		 */
+		mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN;
+		sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
+		break;
 	case MMC_TIMING_UHS_SDR12:
 	case MMC_TIMING_UHS_SDR25:
 	case MMC_TIMING_UHS_SDR50:
@@ -339,6 +386,19 @@ static void layerscape_set_timing(struct fsl_esdhc_host *host, enum mci_timing t
 	host->sdhci.timing = timing;
 }
 
+static void esdhc_hs400_enhanced_strobe(struct mci_host *mci, struct mci_ios *ios)
+{
+	struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+	u32 m;
+
+	m = sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL);
+	if (ios->enhanced_strobe)
+		m |= MIX_CTRL_HS400_ES;
+	else
+		m &= ~MIX_CTRL_HS400_ES;
+	sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, m);
+}
+
 static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios)
 {
 	struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
@@ -386,6 +446,13 @@ static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios)
 		return;
 	}
 
+	/*
+	 * (Re)program the strobe DLL on every HS400 set_ios(): mci-core selects
+	 * HS400 timing while still at the old clock and only raises the clock on
+	 * a later set_ios(), so the DLL must lock against the final read clock.
+	 */
+	if (ios->timing == MMC_TIMING_MMC_HS400 && ios->clock)
+		esdhc_set_strobe_dll(host);
 }
 
 static int esdhc_card_present(struct mci_host *mci)
@@ -511,6 +578,7 @@ static const struct mci_ops fsl_esdhc_ops = {
 	.set_ios = esdhc_set_ios,
 	.init = esdhc_init,
 	.card_present = esdhc_card_present,
+	.hs400_enhanced_strobe = esdhc_hs400_enhanced_strobe,
 };
 
 static void fsl_esdhc_probe_dt(struct device *dev, struct fsl_esdhc_host *host)
@@ -528,6 +596,9 @@ static void fsl_esdhc_probe_dt(struct device *dev, struct fsl_esdhc_host *host)
 		boarddata->tuning_start_tap = ESDHC_TUNING_START_TAP_DEFAULT;
 	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
 		boarddata->delay_line = 0;
+	if (of_property_read_u32(np, "fsl,strobe-dll-delay-target",
+			     &boarddata->strobe_dll_delay_target))
+		boarddata->strobe_dll_delay_target = 0;
 
 	if (esdhc_is_usdhc(host) && !IS_ERR(host->pinctrl)) {
 		host->pins_100mhz = pinctrl_lookup_state(host->pinctrl,
@@ -567,6 +638,11 @@ static bool usdhc_setup_tuning(struct fsl_esdhc_host *host)
 	mci->ops.execute_tuning = usdhc_execute_tuning;
 	mci->caps2 |= MMC_CAP2_HS200;
 
+	if (host->socdata->flags & ESDHC_FLAG_HS400)
+		mci->caps2 |= MMC_CAP2_HS400_1_8V;
+	if (host->socdata->flags & ESDHC_FLAG_HS400_ES)
+		mci->caps2 |= MMC_CAP2_HS400_ES;
+
 	return true;
 }
 
@@ -684,6 +760,13 @@ static struct esdhc_soc_data usdhc_imx6sx_data = {
 	.clkidx = "per",
 };
 
+static struct esdhc_soc_data usdhc_imx8mm_data = {
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+	       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+	       | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES,
+	.clkidx = "per",
+};
+
 static struct esdhc_soc_data esdhc_ls_be_data = {
 	.flags = ESDHC_FLAG_MULTIBLK_NO_INT | ESDHC_FLAG_BIGENDIAN |
 		 ESDHC_FLAG_LAYERSCAPE,
@@ -702,9 +785,9 @@ static __maybe_unused struct of_device_id fsl_esdhc_compatible[] = {
 	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data },
 	{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data },
 	{ .compatible = "fsl,imx8mq-usdhc", .data = &usdhc_imx6sx_data },
-	{ .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx6sx_data },
-	{ .compatible = "fsl,imx8mn-usdhc", .data = &usdhc_imx6sx_data },
-	{ .compatible = "fsl,imx8mp-usdhc", .data = &usdhc_imx6sx_data },
+	{ .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data },
+	{ .compatible = "fsl,imx8mn-usdhc", .data = &usdhc_imx8mm_data },
+	{ .compatible = "fsl,imx8mp-usdhc", .data = &usdhc_imx8mm_data },
 	{ .compatible = "fsl,ls1028a-esdhc",.data = &esdhc_ls_le_data  },
 	{ .compatible = "fsl,ls1046a-esdhc",.data = &esdhc_ls_be_data  },
 	{ /* sentinel */ }
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index df8aca18ad..5562371652 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -66,6 +66,17 @@
 #define  IMX_SDHCI_DLL_CTRL_OVERRIDE_EN_SHIFT	8
 #define IMX_SDHCI_MIX_CTRL_FBCLK_SEL	BIT(25)
 
+/* HS400 data strobe line delay-locked loop (read clock) */
+#define ESDHC_STROBE_DLL_CTRL				0x70
+#define  ESDHC_STROBE_DLL_CTRL_ENABLE			BIT(0)
+#define  ESDHC_STROBE_DLL_CTRL_RESET			BIT(1)
+#define  ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT	3
+#define  ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT	0x7
+#define  ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT	(4 << 20)
+#define ESDHC_STROBE_DLL_STATUS				0x74
+#define  ESDHC_STROBE_DLL_STS_REF_LOCK			BIT(1)
+#define  ESDHC_STROBE_DLL_STS_SLV_LOCK			BIT(0)
+
 /* pltfm-specific */
 #define ESDHC_HOST_CONTROL_LE	0x20
 
@@ -163,6 +174,8 @@
 #define ESDHC_FLAG_BIGENDIAN		BIT(10)
 /* Layerscape variant ls1046a, ls1028a, ls1088a, revisit for ls1012a */
 #define ESDHC_FLAG_LAYERSCAPE		BIT(11)
+/* The IP supports HS400ES mode */
+#define ESDHC_FLAG_HS400_ES		BIT(12)
 
 struct esdhc_soc_data {
 	u32 flags;
@@ -177,6 +190,7 @@ struct esdhc_platform_data {
 	unsigned int delay_line;
 	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
 	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
+	unsigned int strobe_dll_delay_target;	/* HS400 strobe read-clock delay cell */
 };
 
 struct fsl_esdhc_host {
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 6/7] mci: imx-esdhc: make the transfer mode selectable (PIO/SDMA/ADMA2)
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
                   ` (3 preceding siblings ...)
  2026-06-27 19:43 ` [PATCH v1 5/7] mci: imx-esdhc: support HS400 and HS400ES on i.MX8M Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-27 19:43 ` [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader Johannes Schneider
  5 siblings, 0 replies; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

The driver only offered a PIO-or-DMA toggle (CONFIG_MCI_IMX_ESDHC_PIO) and
never called sdhci_setup_adma(), so the controller-resident ADMA2 engine was
unreachable and DMA always meant SDMA.

Replace the single bool with a choice of PIO/SDMA/ADMA2, defaulting to SDMA so
existing configs keep their current behaviour, and call sdhci_setup_adma() in
probe under the ADMA2 option (mirroring the Rockchip dwcmshc driver). It
returns -ENOTSUPP and cleanly falls back to SDMA on controllers without ADMA2
capability, so the new option is safe on all i.MX/Layerscape variants.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/Kconfig     | 19 ++++++++++++++++---
 drivers/mci/imx-esdhc.c |  7 +++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index b38f7a3bdf..cd8862722c 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -169,11 +169,24 @@ config MCI_IMX_ESDHC
 	  Enable this entry to add support to read and write SD cards on a
 	  Freescale i.MX25/35/51 based system.
 
-config MCI_IMX_ESDHC_PIO
-	bool "use PIO mode"
+choice
+	prompt "i.MX esdhc transfer mode"
+	default MCI_IMX_ESDHC_SDMA
 	depends on MCI_IMX_ESDHC
 	help
-	  mostly useful for debugging. Normally you should use DMA.
+	  How the driver moves data words to/from the controller. SDMA and
+	  ADMA2 use the controller's DMA engine; PIO is CPU-driven and slow.
+
+config MCI_IMX_ESDHC_PIO
+	bool "PIO"
+
+config MCI_IMX_ESDHC_SDMA
+	bool "SDMA"
+
+config MCI_IMX_ESDHC_ADMA2
+	bool "ADMA2"
+
+endchoice
 
 config MCI_OMAP_HSMMC
 	bool "OMAP HSMMC"
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index e123bd3ede..3536ebd6b8 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -698,6 +698,13 @@ static int fsl_esdhc_probe(struct device *dev)
 	if (ret)
 		goto err_clk_disable;
 
+	if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_ADMA2)) {
+		ret = sdhci_setup_adma(&host->sdhci);
+		if (ret && ret != -ENOTSUPP)
+			dev_warn(dev, "ADMA setup failed (%pe), falling back to SDMA\n",
+				 ERR_PTR(ret));
+	}
+
 	if (esdhc_is_usdhc(host) || esdhc_is_layerscape(host))
 		mci->host_caps |= MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR;
 
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader
  2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
                   ` (4 preceding siblings ...)
  2026-06-27 19:43 ` [PATCH v1 6/7] mci: imx-esdhc: make the transfer mode selectable (PIO/SDMA/ADMA2) Johannes Schneider
@ 2026-06-27 19:43 ` Johannes Schneider
  2026-06-29 13:40   ` Sascha Hauer
  5 siblings, 1 reply; 11+ messages in thread
From: Johannes Schneider @ 2026-06-27 19:43 UTC (permalink / raw)
  To: barebox; +Cc: Johannes Schneider

The PBL eMMC loader was hardwired to PIO via esdhc_use_pio_mode(): IN_PBL
forced PIO unconditionally. PIO is slow -- on an i.MX8MM board loading the
~1.6 MB next stage took ~559 ms; SDMA/ADMA2 do it in ~21 ms.

Let esdhc_use_pio_mode() in the PBL honour the SDHCI DMA flags, add a
transfer-mode choice for the loader (PIO default / SDMA / ADMA2), and route
both the imx8m and imx8mp/imx8mn loaders through shared helpers. The PBL has
no mci and runs before BL31, so host.sdhci.version is set by hand (no
__sdhci_read_caps()) and the ADMA2 descriptor table lives in a static buffer
(the PBL has no allocator), compiled in only for the ADMA2 option.

On the imx8mp loader the DMA mode is set up *before* the bootpart EXT_CSD
read so that read also goes through ADMA: a PIO transfer preceding the first
ADMA transfer wedges the uSDHC ADMA engine. Either way the loader retries in
PIO if the DMA attempt fails, so a misconfigured board still boots.

SDMA and ADMA2 perform identically here (the transfer is bus-bound), and SDMA
needs no descriptor table, so it is the simpler default for boards that just
want the speedup.

Assisted-by: Claude Opus 4.8 (1M context)
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 drivers/mci/Kconfig            | 21 +++++++++++
 drivers/mci/imx-esdhc-common.c | 16 ++++++--
 drivers/mci/imx-esdhc-pbl.c    | 68 +++++++++++++++++++++++++++++++---
 3 files changed, 96 insertions(+), 9 deletions(-)

diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index cd8862722c..e071bb5650 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -288,6 +288,27 @@ config MCI_IMX_ESDHC_PBL
 	bool
 	select MCI_SDHCI
 
+choice
+	prompt "i.MX8M PBL eMMC loader transfer mode"
+	default MCI_IMX_ESDHC_PBL_PIO
+	depends on MCI_IMX_ESDHC_PBL
+	help
+	  How the i.MX8M PBL reads the next boot stage from eMMC. DMA is much
+	  faster than PIO; on failure the loader falls back to PIO so the board
+	  still boots. ADMA2 additionally needs the board PBL to set up an early
+	  malloc pool (pbl_malloc_init) for the descriptor table; SDMA does not.
+
+config MCI_IMX_ESDHC_PBL_PIO
+	bool "PIO"
+
+config MCI_IMX_ESDHC_PBL_SDMA
+	bool "SDMA"
+
+config MCI_IMX_ESDHC_PBL_ADMA2
+	bool "ADMA2"
+
+endchoice
+
 config MCI_ATMEL_PBL
 	bool
 	select MCI_ATMEL
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index a0c2dee32d..1bf70d4e65 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -295,9 +295,17 @@ void esdhc_populate_sdhci(struct fsl_esdhc_host *host)
 				      SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
 }
 
-static bool esdhc_use_pio_mode(void)
+static bool esdhc_use_pio_mode(struct fsl_esdhc_host *host)
 {
-	return IN_PBL || IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO);
+	/*
+	 * In the PBL default to PIO, unless a caller explicitly opted into
+	 * ADMA2 (SDHCI_USE_ADMA, descriptor table set up) or SDMA
+	 * (SDHCI_USE_SDMA).
+	 */
+	if (IN_PBL)
+		return !(host->sdhci.flags & (SDHCI_USE_ADMA | SDHCI_USE_SDMA));
+
+	return IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO);
 }
 
 static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
@@ -317,7 +325,7 @@ static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
 
 	host->sdhci.sdma_boundary = 0;
 
-	if (esdhc_use_pio_mode())
+	if (esdhc_use_pio_mode(host))
 		sdhci_setup_data_pio(&host->sdhci, data);
 	else
 		sdhci_setup_data_dma(&host->sdhci, data, dma);
@@ -411,7 +419,7 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
 
 	/* Wait until all of the blocks are transferred */
 	if (data) {
-		if (esdhc_use_pio_mode())
+		if (esdhc_use_pio_mode(host))
 			ret = sdhci_transfer_data_pio(&host->sdhci, cmd, data);
 		else
 			ret = sdhci_transfer_data_dma(&host->sdhci, cmd, data, dma);
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index fe06d418b0..80e80b24a0 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -33,6 +33,12 @@
 
 static u8 ext_csd[512] __aligned(64);
 
+#ifdef CONFIG_MCI_IMX_ESDHC_PBL_ADMA2
+/* ADMA2 descriptor table for the PBL eMMC loader (the PBL has no allocator). */
+static u8 esdhc_adma_table[SDHCI_DEFAULT_ADMA_DESCS * SDHCI_ADMA2_32_DESC_SZ]
+	__aligned(8);
+#endif
+
 static int esdhc_send_ext_csd(struct fsl_esdhc_host *host)
 {
 	struct mci_cmd cmd = {};
@@ -252,6 +258,51 @@ int imx7_esdhc_start_image(int instance)
  * Return: If image successfully loaded, returns 0.
  * A negative error code is returned when this function fails.
  */
+/*
+ * Configure the PBL eMMC loader's DMA mode (ADMA2 or SDMA per Kconfig). The
+ * PBL has no mci, so host->sdhci.version is set by hand because
+ * __sdhci_read_caps() cannot run.
+ */
+static void imx8m_esdhc_pbl_setup_dma(struct fsl_esdhc_host *host)
+{
+	if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PBL_SDMA)) {
+		host->sdhci.version = SDHCI_SPEC_300;
+		host->sdhci.flags |= SDHCI_USE_SDMA;
+	}
+
+#ifdef CONFIG_MCI_IMX_ESDHC_PBL_ADMA2
+	host->sdhci.version = SDHCI_SPEC_300;
+	host->sdhci.adma_table = esdhc_adma_table;
+	host->sdhci.adma_addr = virt_to_phys(esdhc_adma_table);
+	host->sdhci.desc_sz = SDHCI_ADMA2_32_DESC_SZ;
+	host->sdhci.adma_table_cnt = SDHCI_DEFAULT_ADMA_DESCS;
+	host->sdhci.adma_table_sz = sizeof(esdhc_adma_table);
+	host->sdhci.flags |= SDHCI_USE_ADMA;
+#endif
+}
+
+static int imx8m_esdhc_load_image_dma(struct fsl_esdhc_host *host,
+				      struct esdhc_soc_data *data, int instance,
+				      void *bl33, u32 offset, u32 ivt_offset)
+{
+	int ret;
+
+	ret = esdhc_load_image(host, MX8M_DDR_CSD1_BASE_ADDR,
+			       (ptrdiff_t)bl33, offset, ivt_offset, false);
+	if (!ret)
+		return 0;
+
+	/* Fall back to PIO so a failed DMA attempt still boots. */
+	if (host->sdhci.flags & (SDHCI_USE_ADMA | SDHCI_USE_SDMA)) {
+		host->sdhci.flags &= ~(SDHCI_USE_ADMA | SDHCI_USE_SDMA);
+		imx8m_esdhc_init(host, data, instance);
+		ret = esdhc_load_image(host, MX8M_DDR_CSD1_BASE_ADDR,
+				       (ptrdiff_t)bl33, offset, ivt_offset, false);
+	}
+
+	return ret;
+}
+
 int imx8m_esdhc_load_image(int instance, void *bl33)
 {
 	struct esdhc_soc_data data;
@@ -262,9 +313,10 @@ int imx8m_esdhc_load_image(int instance, void *bl33)
 	if (ret)
 		return ret;
 
-	return esdhc_load_image(&host, MX8M_DDR_CSD1_BASE_ADDR,
-				(ptrdiff_t)bl33, SZ_32K, SZ_1K,
-				false);
+	imx8m_esdhc_pbl_setup_dma(&host);
+
+	return imx8m_esdhc_load_image_dma(&host, &data, instance, bl33,
+					  SZ_32K, SZ_1K);
 }
 
 /**
@@ -291,10 +343,16 @@ int imx8mp_esdhc_load_image(int instance, void *bl33)
 	if (ret)
 		return ret;
 
+	/*
+	 * Set up DMA first so the EXT_CSD read below also goes through ADMA --
+	 * a PIO transfer before the first ADMA transfer wedges the 8MP uSDHC.
+	 */
+	imx8m_esdhc_pbl_setup_dma(&host);
+
 	offset = esdhc_bootpart_active(&host)? 0 : SZ_32K;
 
-	return esdhc_load_image(&host, MX8M_DDR_CSD1_BASE_ADDR,
-				(ptrdiff_t)bl33, offset, 0, false);
+	return imx8m_esdhc_load_image_dma(&host, &data, instance, bl33,
+					  offset, 0);
 }
 
 int imx8mn_esdhc_load_image(int instance, void *bl33)
-- 
2.43.0




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader
  2026-06-27 19:43 ` [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader Johannes Schneider
@ 2026-06-29 13:40   ` Sascha Hauer
  2026-06-30  9:22     ` SCHNEIDER Johannes
  0 siblings, 1 reply; 11+ messages in thread
From: Sascha Hauer @ 2026-06-29 13:40 UTC (permalink / raw)
  To: Johannes Schneider; +Cc: barebox, Johannes Schneider

On 2026-06-27 19:43, Johannes Schneider wrote:
> The PBL eMMC loader was hardwired to PIO via esdhc_use_pio_mode(): IN_PBL
> forced PIO unconditionally. PIO is slow -- on an i.MX8MM board loading the
> ~1.6 MB next stage took ~559 ms; SDMA/ADMA2 do it in ~21 ms.

For proper DMA support you'll need memory synchronization in form of dma_map_*
or dma_sync_* helpers which we do not have in PBL. Without them it won't
work with MMU enabled. Have you tried enabling the MMU in the mean time? This
should give you decent performance even with PIO.

Sascha

--
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader
  2026-06-29 13:40   ` Sascha Hauer
@ 2026-06-30  9:22     ` SCHNEIDER Johannes
  2026-07-02  7:54       ` Sascha Hauer
  0 siblings, 1 reply; 11+ messages in thread
From: SCHNEIDER Johannes @ 2026-06-30  9:22 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Hoi Sascha,


> On 2026-06-27 19:43, Johannes Schneider wrote:
> > The PBL eMMC loader was hardwired to PIO via esdhc_use_pio_mode(): IN_PBL
> > forced PIO unconditionally. PIO is slow -- on an i.MX8MM board loading the
> > ~1.6 MB next stage took ~559 ms; SDMA/ADMA2 do it in ~21 ms.
>
> For proper DMA support you'll need memory synchronization in form of dma_map_*
> or dma_sync_* helpers which we do not have in PBL. Without them it won't
> work with MMU enabled.

Noted. So since the MMU is still left as it is = off were still good wtih the
current sdma/adma implementation. But maybe worth a comment in the code/commit?

> Have you tried enabling the MMU in the mean time? This
> should give you decent performance even with PIO.
>
> Sascha
>

Thanks for the hint/idea!
I've let the AI draft a PIO+MMU-on change and ran a round of measurements,
(Caveat: sample size is one) there is some gain - but we get more with SDMA or ADMA
And interestingly "the same" with the later two.:

 Phase                  PIO   PIO+MMU   SDMA   ADMA2
--------------------------------------------------------------------
 BootROM                  1       1       1        2
 PBL-init                 3       3       3        3
 DDR-training           265     265     262      269
 PBL-load (total)       884     413     257      258
   PBL-pre-load         165     170     166      167
   load_bl33            713     241      86       85
   PBL-post-load          5       1       5        5
 BL31-early             114     114     114      114
 BL31-platform           16      15      15       15
 BL31-runtime            98      98      98       98
--------------------------------------------------------------------
 time-to-barebox       1393     921     763      770


If you want i can brush up that PIO+MMU code and send it out too.


gruß
Johannes



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader
  2026-06-30  9:22     ` SCHNEIDER Johannes
@ 2026-07-02  7:54       ` Sascha Hauer
  2026-07-04 12:42         ` SCHNEIDER Johannes
  0 siblings, 1 reply; 11+ messages in thread
From: Sascha Hauer @ 2026-07-02  7:54 UTC (permalink / raw)
  To: SCHNEIDER Johannes; +Cc: barebox

On 2026-06-30 09:22, SCHNEIDER Johannes wrote:
> Hoi Sascha,
> 
> 
> > On 2026-06-27 19:43, Johannes Schneider wrote:
> > > The PBL eMMC loader was hardwired to PIO via esdhc_use_pio_mode(): IN_PBL
> > > forced PIO unconditionally. PIO is slow -- on an i.MX8MM board loading the
> > > ~1.6 MB next stage took ~559 ms; SDMA/ADMA2 do it in ~21 ms.
> >
> > For proper DMA support you'll need memory synchronization in form of dma_map_*
> > or dma_sync_* helpers which we do not have in PBL. Without them it won't
> > work with MMU enabled.
> 
> Noted. So since the MMU is still left as it is = off were still good wtih the
> current sdma/adma implementation. But maybe worth a comment in the code/commit?
> 
> > Have you tried enabling the MMU in the mean time? This
> > should give you decent performance even with PIO.
> >
> > Sascha
> >
> 
> Thanks for the hint/idea!
> I've let the AI draft a PIO+MMU-on change and ran a round of measurements,
> (Caveat: sample size is one) there is some gain - but we get more with SDMA or ADMA
> And interestingly "the same" with the later two.:
> 
>  Phase                  PIO   PIO+MMU   SDMA   ADMA2
> --------------------------------------------------------------------
>  BootROM                  1       1       1        2
>  PBL-init                 3       3       3        3
>  DDR-training           265     265     262      269
>  PBL-load (total)       884     413     257      258
>    PBL-pre-load         165     170     166      167
>    load_bl33            713     241      86       85
>    PBL-post-load          5       1       5        5
>  BL31-early             114     114     114      114
>  BL31-platform           16      15      15       15
>  BL31-runtime            98      98      98       98
> --------------------------------------------------------------------
>  time-to-barebox       1393     921     763      770
> 
> 
> If you want i can brush up that PIO+MMU code and send it out too.

Let's concentrate on the MMU stuff first as that's something you want to
have anyway for faster sha256 support.

Sascha

--
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader
  2026-07-02  7:54       ` Sascha Hauer
@ 2026-07-04 12:42         ` SCHNEIDER Johannes
  0 siblings, 0 replies; 11+ messages in thread
From: SCHNEIDER Johannes @ 2026-07-04 12:42 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Hoi Sascha,


> >
> > > On 2026-06-27 19:43, Johannes Schneider wrote:
> > > > The PBL eMMC loader was hardwired to PIO via esdhc_use_pio_mode(): IN_PBL
> > > > forced PIO unconditionally. PIO is slow -- on an i.MX8MM board loading the
> > > > ~1.6 MB next stage took ~559 ms; SDMA/ADMA2 do it in ~21 ms.
> > >
> > > For proper DMA support you'll need memory synchronization in form of dma_map_*
> > > or dma_sync_* helpers which we do not have in PBL. Without them it won't
> > > work with MMU enabled.
> >
> > Noted. So since the MMU is still left as it is = off were still good wtih the
> > current sdma/adma implementation. But maybe worth a comment in the code/commit?
> >
> > > Have you tried enabling the MMU in the mean time? This
> > > should give you decent performance even with PIO.
> > >
> > > Sascha
> > >
> >
> > Thanks for the hint/idea!
> > I've let the AI draft a PIO+MMU-on change and ran a round of measurements,
> > (Caveat: sample size is one) there is some gain - but we get more with SDMA or ADMA
> > And interestingly "the same" with the later two.:
> >
> >  Phase                  PIO   PIO+MMU   SDMA   ADMA2
> > --------------------------------------------------------------------
> >  BootROM                  1       1       1        2
> >  PBL-init                 3       3       3        3
> >  DDR-training           265     265     262      269
> >  PBL-load (total)       884     413     257      258
> >    PBL-pre-load         165     170     166      167
> >    load_bl33            713     241      86       85
> >    PBL-post-load          5       1       5        5
> >  BL31-early             114     114     114      114
> >  BL31-platform           16      15      15       15
> >  BL31-runtime            98      98      98       98
> > --------------------------------------------------------------------
> >  time-to-barebox       1393     921     763      770
> >
> >
> > If you want i can brush up that PIO+MMU code and send it out too.
> 
> Let's concentrate on the MMU stuff first as that's something you want to
> have anyway for faster sha256 support.
> 
> Sascha
> 

Ok, i've sent out a v2 with the "MMU first", and sorted it in a way that you can
"cut here" if you want to pick up only the first part before the SDMA/ADMA

The combined series his here:
https://lists.infradead.org/pipermail/barebox/2026-July/056903.html

gruß
Johannes


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-07-04 12:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-27 19:43 [PATCH v1 1/7] dma: make dma_mapping_error() NULL-safe Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 2/7] mci: sdhci: bail out on ADMA/transfer errors instead of hanging Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 3/7] mci: sdhci: honor BROKEN_ADMA_ZEROLEN_DESC / NO_ENDATTR_IN_NOPDESC quirks Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 4/7] mci: imx-esdhc: mark the uSDHC ADMA2 descriptor quirks Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 5/7] mci: imx-esdhc: support HS400 and HS400ES on i.MX8M Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 6/7] mci: imx-esdhc: make the transfer mode selectable (PIO/SDMA/ADMA2) Johannes Schneider
2026-06-27 19:43 ` [PATCH v1 7/7] mci: imx-esdhc: support DMA in the i.MX8M PBL eMMC loader Johannes Schneider
2026-06-29 13:40   ` Sascha Hauer
2026-06-30  9:22     ` SCHNEIDER Johannes
2026-07-02  7:54       ` Sascha Hauer
2026-07-04 12:42         ` SCHNEIDER Johannes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox