spi: spi-nxp-fspi: enter stop mode before reconfiguring MCR0 and DLL
authorHaibo Chen <haibo.chen@nxp.com>
Tue, 28 Jul 2026 10:18:09 +0000 (18:18 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 30 Jul 2026 12:13:49 +0000 (13:13 +0100)
In nxp_fspi_select_mem() the RX sample clock source (MCR0[RXCLKSRC])
and the DLL control registers (DLLxCR) are reconfigured while the
FlexSPI module is still enabled. According to the FlexSPI reference
manual initialization sequence, MCR0 and the DLL control registers
should be programmed while the module is in stop mode, i.e. with
MCR0[MDIS] set to 1, and the module re-enabled (MCR0[MDIS] = 0)
afterwards.

Wrap the RX sample clock source selection and the DLL calibration/
override reconfiguration in a stop-mode window to align with the RM
and avoid reconfiguring timing-critical registers while the module is
active.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260728-fspi-clock-v2-2-dbe786a4a6eb@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-nxp-fspi.c

index 39c1eaa..5435529 100644 (file)
@@ -867,6 +867,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
        unsigned long rate = op->max_freq;
        int ret;
        uint64_t size_kb;
+       u32 reg;
 
        /*
         * Return when following condition all meet,
@@ -896,6 +897,15 @@ static void 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.
+        */
+       reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+       fspi_writel(f, reg | FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
+
        nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
        rate = min(f->max_rate, op->max_freq);
 
@@ -928,6 +938,10 @@ static void 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);