summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-12 11:06:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-12 11:06:16 -0700
commit28608283615e5e7e92ea79c8ea13507f4b5e0cbe (patch)
treeeea3e0785303e33f3bcba976cd211084b128add4
parent880b719ca0da9d2470fd2652e8ed959ca5143280 (diff)
parent3c60184e39b57e5efe664fe8540cdbc1bc7ea899 (diff)
Merge tag 'spi-fix-v7.1-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A couple of driver specific fixes: a small targeted fix for hardware error handling on DesignWare controllers and another for handling of custom chip select management on Qualcomm GENI controllers" * tag 'spi-fix-v7.1-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: dw: fix race between IRQ handler and error handler on SMP spi: qcom-geni: Fix cs_change handling on the last transfer
-rw-r--r--drivers/spi/spi-dw-core.c2
-rw-r--r--drivers/spi/spi-geni-qcom.c27
2 files changed, 21 insertions, 8 deletions
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index b47637888c5c..4672bc2a873a 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -472,7 +472,9 @@ static inline void dw_spi_abort(struct spi_controller *ctlr)
if (dws->dma_mapped)
dws->dma_ops->dma_stop(dws);
+ disable_irq(dws->irq);
dw_spi_reset_chip(dws);
+ enable_irq(dws->irq);
}
static void dw_spi_handle_err(struct spi_controller *ctlr,
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index d5fb0edc8e0c..23c6d3a37341 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -440,10 +440,15 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return ret;
}
- if (!xfer->cs_change) {
- if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
- peripheral.fragmentation = FRAGMENTATION;
- }
+ /*
+ * Set fragmentation to keep CS asserted after this transfer when:
+ * - non-last transfer with cs_change=0: keep CS asserted between chained transfers
+ * - last transfer with cs_change=1: keep CS asserted after the message
+ * (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
+ * keep CS asserted across header, wait-state and data phases)
+ */
+ peripheral.fragmentation = list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
+ xfer->cs_change : !xfer->cs_change;
if (peripheral.cmd & SPI_RX) {
dmaengine_slave_config(mas->rx, &config);
@@ -849,10 +854,16 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
- if (!xfer->cs_change) {
- if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
- m_params = FRAGMENTATION;
- }
+ /*
+ * Set FRAGMENTATION to keep CS asserted after this transfer when:
+ * - non-last transfer with cs_change=0: keep CS asserted between chained transfers
+ * - last transfer with cs_change=1: keep CS asserted after the message
+ * (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
+ * keep CS asserted across header, wait-state and data phases)
+ */
+ if (list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
+ xfer->cs_change : !xfer->cs_change)
+ m_params = FRAGMENTATION;
/*
* Lock around right before we start the transfer since our