]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
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 39c1eaaf9e0ae3b765cbe024cca5cd665ca2d739..54355295f9198bd6cf2ab9a43fe12d25ced80769 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);