summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-07-31 11:38:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-07-31 11:38:20 -0700
commit6269cc6f52c68f6f5474f86e94256c81d1ff24cb (patch)
tree98d35565ebcd1be4f7a899a53bc471ae2a8ef68f
parent596254ecc5b7502915feaa737f62b636b77d669a (diff)
parent9513b642d233bedb0b703ea75b5f3230eb6293a0 (diff)
Merge tag 'spi-fix-v7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "The drip of driver specific fixes, mostly from the device vendors themselves, keeps on coming in. There's more than I'd like right now but equally nothing hugely alarming" * tag 'spi-fix-v7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-nxp-fspi: propagate clock reconfig failures in nxp_fspi_select_mem() spi: spi-nxp-fspi: enter stop mode before reconfiguring MCR0 and DLL spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs spi: spi-qpic-snand: write the feature value before executing SET_FEATURE spi: spi-cadence: Move TX FIFO full busy-wait into FIFO spi: qcom-qspi: Correct max DMA length to avoid 64K boundary failure spi: spacemit: prepare both DMA descriptors before submitting
-rw-r--r--drivers/spi/spi-cadence.c26
-rw-r--r--drivers/spi/spi-nxp-fspi.c129
-rw-r--r--drivers/spi/spi-qcom-qspi.c3
-rw-r--r--drivers/spi/spi-qpic-snand.c22
-rw-r--r--drivers/spi/spi-spacemit-k1.c22
5 files changed, 166 insertions, 36 deletions
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 9b4e5b7013ae..af1a05e78492 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -388,11 +388,13 @@ static inline void cdns_spi_writer(struct cdns_spi *xspi)
/**
* cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
+ * @ctlr: Pointer to the spi_controller structure
* @xspi: Pointer to the cdns_spi structure
* @ntx: Number of bytes to pack into the TX FIFO
* @nrx: Number of bytes to drain from the RX FIFO
*/
-static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
+static void cdns_spi_process_fifo(struct spi_controller *ctlr,
+ struct cdns_spi *xspi, int ntx, int nrx)
{
ntx = clamp(ntx, 0, xspi->tx_bytes);
nrx = clamp(nrx, 0, xspi->rx_bytes);
@@ -407,6 +409,16 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
}
if (ntx) {
+ /* When xspi in busy condition, bytes may send failed,
+ * then spi control didn't work thoroughly, add one byte
+ * delay. Only in host mode; in target mode this delay
+ * causes data corruption as the target fails to prepare
+ * data in time.
+ */
+ if (!spi_controller_is_target(ctlr) &&
+ (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL))
+ udelay(10);
+
cdns_spi_writer(xspi);
ntx--;
}
@@ -460,14 +472,14 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
if (xspi->tx_bytes) {
- cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
+ cdns_spi_process_fifo(ctlr, xspi, trans_cnt, trans_cnt);
} else {
/* Fixed delay due to controller limitation with
* RX_NEMPTY incorrect status
* Xilinx AR:65885 contains more details
*/
udelay(10);
- cdns_spi_process_fifo(xspi, 0, trans_cnt);
+ cdns_spi_process_fifo(ctlr, xspi, 0, trans_cnt);
cdns_spi_write(xspi, CDNS_SPI_IDR,
CDNS_SPI_IXR_DEFAULT);
spi_finalize_current_transfer(ctlr);
@@ -520,17 +532,11 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}
- /* When xspi in busy condition, bytes may send failed,
- * then spi control didn't work thoroughly, add one byte delay
- */
- if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
- udelay(10);
-
xspi->n_bytes = cdns_spi_n_bytes(transfer);
xspi->tx_bytes = DIV_ROUND_UP(xspi->tx_bytes, xspi->n_bytes);
xspi->rx_bytes = DIV_ROUND_UP(xspi->rx_bytes, xspi->n_bytes);
- cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
+ cdns_spi_process_fifo(ctlr, xspi, xspi->tx_fifo_depth, 0);
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
return transfer->len;
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 1e36ae084dd8..4425132432ec 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -340,6 +340,18 @@ struct nxp_fspi_devtype_data {
unsigned int quirks;
unsigned int lut_num;
bool little_endian;
+ /*
+ * The max clock rate (Hz) that FlexSPI can output to the device
+ * in SDR mode (RXCLKSRC=0). Defaults to 66MHz if zero.
+ * Some SoCs (e.g. LX2160A) support up to 100MHz in SDR mode.
+ */
+ unsigned long max_sdr_rate;
+ /*
+ * The max clock rate (Hz) that FlexSPI can output to the device
+ * in DTR mode (RXCLKSRC=3). Defaults to 166MHz if zero.
+ * Some SoCs (e.g. i.MX95, i.MX8QM, i.MX8DXL) support up to 200MHz.
+ */
+ unsigned long max_dtr_rate;
};
static struct nxp_fspi_devtype_data lx2160a_data = {
@@ -349,6 +361,10 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
.quirks = FSPI_QUIRK_DISABLE_DTR,
.lut_num = 32,
.little_endian = true, /* little-endian */
+ /*
+ * LX2160ACEC: SDR RXCLKSRC=0 max 100MHz, DTR disabled via quirk.
+ */
+ .max_sdr_rate = 100000000,
};
static struct nxp_fspi_devtype_data imx8mm_data = {
@@ -358,6 +374,21 @@ static struct nxp_fspi_devtype_data imx8mm_data = {
.quirks = 0,
.lut_num = 32,
.little_endian = true, /* little-endian */
+ /* IMX8MMCEC §3.9.10: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
+ .max_sdr_rate = 66000000,
+ .max_dtr_rate = 166000000,
+};
+
+static struct nxp_fspi_devtype_data imx8mp_data = {
+ .rxfifo = SZ_512, /* (64 * 64 bits) */
+ .txfifo = SZ_1K, /* (128 * 64 bits) */
+ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
+ .quirks = 0,
+ .lut_num = 32,
+ .little_endian = true, /* little-endian */
+ /* IMX8MPCEC: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
+ .max_sdr_rate = 66000000,
+ .max_dtr_rate = 166000000,
};
static struct nxp_fspi_devtype_data imx8qxp_data = {
@@ -367,6 +398,12 @@ static struct nxp_fspi_devtype_data imx8qxp_data = {
.quirks = 0,
.lut_num = 32,
.little_endian = true, /* little-endian */
+ /*
+ * IMX8QXPCEC: SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 200MHz.
+ * i.MX8QM and i.MX8DXL share the same FlexSPI IP and limits.
+ */
+ .max_sdr_rate = 60000000,
+ .max_dtr_rate = 200000000,
};
static struct nxp_fspi_devtype_data imx8dxl_data = {
@@ -376,6 +413,12 @@ static struct nxp_fspi_devtype_data imx8dxl_data = {
.quirks = FSPI_QUIRK_USE_IP_ONLY,
.lut_num = 32,
.little_endian = true, /* little-endian */
+ /*
+ * IMX8DXLCEC (i.MX 8XLite): SDR RXCLKSRC=0 max 60MHz,
+ * DDR RXCLKSRC=3 max 200MHz.
+ */
+ .max_sdr_rate = 60000000,
+ .max_dtr_rate = 200000000,
};
static struct nxp_fspi_devtype_data imx8ulp_data = {
@@ -385,6 +428,29 @@ static struct nxp_fspi_devtype_data imx8ulp_data = {
.quirks = 0,
.lut_num = 16,
.little_endian = true, /* little-endian */
+ /*
+ * IMX8ULPCEC §7.3.1, Normal Drive (ND, 1.0V) mode:
+ * SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 166MHz.
+ * Note: Overdrive (OD, 1.05V) allows up to 180MHz DTR
+ * but is not the default use case.
+ */
+ .max_sdr_rate = 60000000,
+ .max_dtr_rate = 166000000,
+};
+
+static struct nxp_fspi_devtype_data imx95_data = {
+ .rxfifo = SZ_512, /* (64 * 64 bits) */
+ .txfifo = SZ_1K, /* (128 * 64 bits) */
+ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
+ .quirks = 0,
+ .lut_num = 32,
+ .little_endian = true, /* little-endian */
+ /*
+ * IMX95CEC Rev.8 §4.11.7: SDR RXCLKSRC=0 max 66MHz,
+ * DDR RXCLKSRC=3 max 200MHz (Nominal/Overdrive mode).
+ */
+ .max_sdr_rate = 66000000,
+ .max_dtr_rate = 200000000,
};
struct nxp_fspi {
@@ -691,10 +757,20 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
if (op_is_dtr) {
reg |= FSPI_MCR0_RXCLKSRC(3);
- f->max_rate = 166000000;
+ /*
+ * Use the SoC-specific DTR max rate if provided, otherwise
+ * fall back to 166MHz (limit from IMX8MN datasheet §3.9.9).
+ */
+ f->max_rate = f->devtype_data->max_dtr_rate ?
+ f->devtype_data->max_dtr_rate : 166000000;
} else { /*select mode 0 */
reg &= ~FSPI_MCR0_RXCLKSRC(3);
- f->max_rate = 66000000;
+ /*
+ * Use the SoC-specific SDR max rate if provided, otherwise
+ * fall back to 66MHz (limit from IMX8MN datasheet §3.9.9).
+ */
+ f->max_rate = f->devtype_data->max_sdr_rate ?
+ f->devtype_data->max_sdr_rate : 66000000;
}
fspi_writel(f, reg, f->iobase + FSPI_MCR0);
}
@@ -783,14 +859,15 @@ static void nxp_fspi_dll_override(struct nxp_fspi *f)
* Value for rest of the CS FLSHxxCR0 register would be zero.
*
*/
-static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
- const struct spi_mem_op *op)
+static int nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
+ const struct spi_mem_op *op)
{
/* flexspi only support one DTR mode: 8D-8D-8D */
bool op_is_dtr = op->cmd.dtr && op->addr.dtr && op->dummy.dtr && op->data.dtr;
unsigned long rate = op->max_freq;
int ret;
uint64_t size_kb;
+ u32 reg;
/*
* Return when following condition all meet,
@@ -804,7 +881,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
if ((f->selected == spi_get_chipselect(spi, 0)) &&
(!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) &&
(f->pre_op_rate == op->max_freq))
- return;
+ return 0;
/* Reset FLSHxxCR0 registers */
fspi_writel(f, 0, f->iobase + FSPI_FLSHA1CR0);
@@ -820,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);
@@ -836,12 +922,19 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
nxp_fspi_clk_disable_unprep(f);
ret = clk_set_rate(f->clk, rate);
- if (ret)
- return;
+ if (ret) {
+ /*
+ * clk_set_rate() failed with the clocks already disabled.
+ * Re-enable them so the enable count matches what the caller's
+ * pm_runtime_put() (runtime_suspend) will drop.
+ */
+ nxp_fspi_clk_prep_enable(f);
+ return ret;
+ }
ret = nxp_fspi_clk_prep_enable(f);
if (ret)
- return;
+ return ret;
/*
* If clock rate > 100MHz, then switch from DLL override mode to
@@ -852,9 +945,15 @@ 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);
+
+ return 0;
}
static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
@@ -1042,7 +1141,16 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true);
WARN_ON(err);
- nxp_fspi_select_mem(f, mem->spi, op);
+ err = nxp_fspi_select_mem(f, mem->spi, op);
+ if (err) {
+ /*
+ * On failure the FlexSPI clock may be left disabled, so avoid
+ * any further register access (which would trigger a synchronous
+ * external abort) and bail out.
+ */
+ pm_runtime_put_autosuspend(f->dev);
+ return err;
+ }
nxp_fspi_prepare_lut(f, op);
/*
@@ -1444,10 +1552,11 @@ static const struct dev_pm_ops nxp_fspi_pm_ops = {
static const struct of_device_id nxp_fspi_dt_ids[] = {
{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
- { .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, },
+ { .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mp_data, },
{ .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, },
{ .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, },
{ .compatible = "nxp,imx8ulp-fspi", .data = (void *)&imx8ulp_data, },
+ { .compatible = "nxp,imx95-fspi", .data = (void *)&imx95_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);
diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index caf55a6f70b3..e9fdefa9d65d 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -775,7 +775,8 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "could not set DMA mask\n");
host->max_speed_hz = 300000000;
- host->max_dma_len = 65536; /* as per HPG */
+ /* as per HPG, it is 64KB, limit to 60KB to avoid boundary condition failures */
+ host->max_dma_len = 0xf000;
host->dma_alignment = QSPI_ALIGN_REQ;
host->num_chipselect = QSPI_NUM_CS;
host->bus_num = -1;
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c
index 66f2d1b78ade..b6c58d9cfe14 100644
--- a/drivers/spi/spi-qpic-snand.c
+++ b/drivers/spi/spi-qpic-snand.c
@@ -1358,6 +1358,22 @@ static int qcom_spi_send_cmdaddr(struct qcom_nand_controller *snandc,
snandc->regs->addr0 = cpu_to_le32(op->addr.val);
snandc->regs->addr1 = cpu_to_le32(0);
+ /*
+ * The feature value has to reach NAND_FLASH_FEATURES before the
+ * command is executed, otherwise the controller programs the chip
+ * with whatever the register happened to hold from a previous
+ * operation.
+ */
+ if (opcode == SPINAND_SET_FEATURE) {
+ u32 ftr = 0;
+
+ memcpy(&ftr, op->data.buf.out,
+ min_t(size_t, op->data.nbytes, sizeof(ftr)));
+ snandc->regs->flash_feature = cpu_to_le32(ftr);
+ qcom_write_reg_dma(snandc, &snandc->regs->flash_feature,
+ NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL);
+ }
+
qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL);
qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
@@ -1395,10 +1411,8 @@ static int qcom_spi_io_op(struct qcom_nand_controller *snandc, const struct spi_
copy_ftr = true;
break;
case SPINAND_SET_FEATURE:
- snandc->regs->flash_feature = cpu_to_le32(*(u32 *)op->data.buf.out);
- qcom_write_reg_dma(snandc, &snandc->regs->flash_feature,
- NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL);
- break;
+ /* fully handled by qcom_spi_send_cmdaddr() */
+ return 0;
case SPINAND_PROGRAM_EXECUTE:
case SPINAND_WRITE_EN:
case SPINAND_RESET:
diff --git a/drivers/spi/spi-spacemit-k1.c b/drivers/spi/spi-spacemit-k1.c
index 0faf7ffed676..fd5893a92e59 100644
--- a/drivers/spi/spi-spacemit-k1.c
+++ b/drivers/spi/spi-spacemit-k1.c
@@ -278,25 +278,25 @@ static int k1_spi_dma_one(struct spi_controller *host, struct spi_device *spi,
struct spi_transfer *transfer)
{
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
- struct dma_async_tx_descriptor *desc;
+ struct dma_async_tx_descriptor *txdesc, *rxdesc;
u32 val;
- /* Prepare the TX descriptor and submit it */
- desc = k1_spi_dma_prep(drv_data, transfer, true);
- if (!desc)
+ /* Prepare the TX descriptor */
+ txdesc = k1_spi_dma_prep(drv_data, transfer, true);
+ if (!txdesc)
goto fallback;
- dmaengine_submit(desc);
- /* Prepare the RX descriptor and submit it */
- desc = k1_spi_dma_prep(drv_data, transfer, false);
- if (!desc)
+ /* Prepare the RX descriptor */
+ rxdesc = k1_spi_dma_prep(drv_data, transfer, false);
+ if (!rxdesc)
goto fallback;
/* When RX is complete we also know TX has completed */
- desc->callback = k1_spi_dma_callback;
- desc->callback_param = drv_data;
+ rxdesc->callback = k1_spi_dma_callback;
+ rxdesc->callback_param = drv_data;
- dmaengine_submit(desc);
+ dmaengine_submit(txdesc);
+ dmaengine_submit(rxdesc);
val = readl(drv_data->base + SSP_TOP_CTRL);
val |= TOP_TRAIL; /* Trailing bytes handled by DMA */