spi: fsl-qspi: Reprogram the clock rate when the operation frequency changes

fsl_qspi_select_mem() returns early when the chip select has not changed,
which happens before it reaches clk_set_rate(). Since the rate is now
taken from the spi-mem operation rather than from the SPI device, the
controller honours op->max_freq exactly once per chip select and ignores
it for every operation after that.

q->selected is only reset to -1 in fsl_qspi_default_setup(), i.e. at probe
and on resume, so on the common single chip select board the very first
operation latches a rate that all subsequent operations inherit, whatever
frequency they asked for.

This results in operations being issued with the wrong frequency.

Cache the operation frequency the clock was programmed for next to the
selected chip select, and redo the clock setup when either changes.

Fixes: 2438db5253 ("spi: fsl-qspi: Support per spi-mem operation frequency switches")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Acked-by: Han Xu <han.xu@nxp.com>
Link: https://patch.msgid.link/20260917-fsl-qspi-freq-op-fix-v1-1-5fbe6b02f738@kontron.de
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Frieder Schrempf 2026-09-17 16:10:15 +02:00 committed by Mark Brown
parent e922bad8b2
commit 3d743adf09
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -289,6 +289,7 @@ struct fsl_qspi {
struct pm_qos_request pm_qos_req;
struct device *dev;
int selected;
u32 selected_freq;
u32 memmap_phy;
};
@ -551,7 +552,8 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi,
unsigned long rate = op->max_freq;
int ret;
if (q->selected == spi_get_chipselect(spi, 0))
if (q->selected == spi_get_chipselect(spi, 0) &&
q->selected_freq == op->max_freq)
return;
if (needs_4x_clock(q))
@ -571,6 +573,7 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi,
}
q->selected = spi_get_chipselect(spi, 0);
q->selected_freq = op->max_freq;
fsl_qspi_invalidate(q);
}