spi: Fixes for v7.2

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmps47sACgkQJNaLcl1U
 h9DonAf/S1AkgEGMws3rJCTH+Bcb7ON9Xvsbjv2rU/CI7lINpSJzbUUJ1Z0qk8KX
 NaK8ByXBDvn06qS/6hirwuNl/lfJ69XNWSlV8MJGWXHfui2sN6ngFJy9jnTIQY72
 bq0rTEPapAFg86Loare1i1nHSomLnICoq/KveE08muiPoBtjFKzP7AF7gDmfN0ot
 g3x39WL6bLY/qrqVw1aT/tqdVl97os/e2EJIx8lxh1M5waN/kpfFoRD/dVbdO6ZU
 8iOKPzIeMco0r1JOtGq2q7JCiHN9DP8+Enyf6hkkgBS/HPEHJkO10t9PAY/ArR12
 /KNB7i/i/O35ChESDgk70mcuToLbgg==
 =g0xm
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2026-07-31 11:38:20 -07:00
commit 6269cc6f52
5 changed files with 166 additions and 36 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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 */