[PATCH] spi: spi-nxp-fspi: exit stop mode before waiting for DLL lock
From: haibo . chen
Date: Mon Sep 28 2026 - 08:09:28 EST
From: Haibo Chen <haibo.chen@xxxxxxx>
For 8D-8D-8D (octal DTR) mode the FlexSPI samples read data using
MCR0[RXCLKSRC] = 3 (flash-memory-provided read strobe on the DQS pad),
which requires the DLL to be locked. Per the i.MX95 Reference Manual
(FlexSPI chapter, "DLL configuration for sampling"), when the serial
root clock is above 100 MHz the DLL is enabled (DLLxCR[DLLEN] = 1,
OVRDEN = 0) and software must then wait for STS2[xREFLOCK] and
STS2[xSLVLOCK] to be asserted before starting a read or write. This DLL
lock is relative to the serial root clock.
While the module is in stop mode (MCR0[MDIS] = 1) the AHB and serial
clocks are gated off internally, so the serial root clock the DLL locks
against is not running. nxp_fspi_dll_calibration() both programs DLLxCR
and then polls STS2 for lock. When it runs entirely in stop mode the
STS2 REF/SLV lock bits never assert (observed as "DLL lock failed" with
STS2 = 0).
The MCR0 bit fields (RXCLKSRC) and the serial root clock rate still have
to be reconfigured in stop mode, so keep entering stop mode around that.
Only move the exit from stop mode (clearing MCR0[MDIS]) ahead of the DLL
calibration/override step, so that the serial root clock is running when
the DLL is calibrated and STS2 can report lock.
Fixes: b4bde5cfff8e ("spi: spi-nxp-fspi: enter stop mode before reconfiguring MCR0 and DLL")
Signed-off-by: Haibo Chen <haibo.chen@xxxxxxx>
---
drivers/spi/spi-nxp-fspi.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 67d991dd249d283e5a7b777c3ef4a70a9af3f065..66cb58f95fdb1ce5dcd0288bbf0d473de7f9f371 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -898,10 +898,10 @@ static int nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
/*
- * Per the FlexSPI reference manual (initialization sequence), MCR0 and
- * the DLL control registers should be configured while the module is in
- * stop mode (MCR0[MDIS] = 1). Enter stop mode before reconfiguring the
- * RX sample clock source and the DLL, then exit stop mode afterwards.
+ * Per the FlexSPI reference manual (initialization sequence), MCR0
+ * should be configured while the module is in stop mode (MCR0[MDIS] = 1).
+ * Enter stop mode before reconfiguring the RX sample clock source, then
+ * exit stop mode afterwards.
*/
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
fspi_writel(f, reg | FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
@@ -936,6 +936,16 @@ static int nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
if (ret)
return ret;
+ /*
+ * Exit stop mode before running the DLL calibration. The DLL
+ * reference clock is derived from the module clock domain, which is
+ * gated while MCR0[MDIS] = 1. Calibrating the DLL in stop mode leaves
+ * the STS2 lock bits stuck at 0 (the DLL never runs), so clear MDIS
+ * first and let the module and reference clock run.
+ */
+ reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+ fspi_writel(f, reg & ~FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
+
/*
* If clock rate > 100MHz, then switch from DLL override mode to
* DLL calibration mode.
@@ -945,10 +955,6 @@ static int nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
else
nxp_fspi_dll_override(f);
- /* Exit stop mode now that MCR0 and the DLL have been reconfigured. */
- reg = fspi_readl(f, f->iobase + FSPI_MCR0);
- fspi_writel(f, reg & ~FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
-
f->pre_op_rate = op->max_freq;
f->selected = spi_get_chipselect(spi, 0);
---
base-commit: ba52b770f89bd2f3771b98edb92c4fde68ca8cc4
change-id: 20260928-fspi-fix-fff612e82f84
Best regards,
--
Haibo Chen <haibo.chen@xxxxxxx>