diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-31 11:38:20 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-31 11:38:20 -0700 |
| commit | 6269cc6f52c68f6f5474f86e94256c81d1ff24cb (patch) | |
| tree | 98d35565ebcd1be4f7a899a53bc471ae2a8ef68f | |
| parent | 596254ecc5b7502915feaa737f62b636b77d669a (diff) | |
| parent | 9513b642d233bedb0b703ea75b5f3230eb6293a0 (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.c | 26 | ||||
| -rw-r--r-- | drivers/spi/spi-nxp-fspi.c | 129 | ||||
| -rw-r--r-- | drivers/spi/spi-qcom-qspi.c | 3 | ||||
| -rw-r--r-- | drivers/spi/spi-qpic-snand.c | 22 | ||||
| -rw-r--r-- | drivers/spi/spi-spacemit-k1.c | 22 |
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 */ |
