Merge tag 'spi-fix-v6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A couple of driver specific fixes, an error handling fix for the Atmel
  QuadSPI driver and a fix for a nasty synchronisation issue in the data
  path for the Microchip driver which affects larger transfers.

  There's also a MAINTAINERS update for the Samsung driver"

* tag 'spi-fix-v6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: microchip-core: prevent RX overflows when transmit size > FIFO size
  MAINTAINERS: add tambarus as R for Samsung SPI
  spi: atmel-quadspi: remove references to runtime PM on error path
This commit is contained in:
Linus Torvalds
2025-03-12 11:47:24 -10:00
3 changed files with 20 additions and 27 deletions
+1
View File
@@ -21089,6 +21089,7 @@ F: include/linux/clk/samsung.h
SAMSUNG SPI DRIVERS
M: Andi Shyti <andi.shyti@kernel.org>
R: Tudor Ambarus <tudor.ambarus@linaro.org>
L: linux-spi@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Maintained
+1 -4
View File
@@ -930,11 +930,8 @@ static int atmel_qspi_sama7g5_transfer(struct spi_mem *mem,
/* Release the chip-select. */
ret = atmel_qspi_reg_sync(aq);
if (ret) {
pm_runtime_mark_last_busy(&aq->pdev->dev);
pm_runtime_put_autosuspend(&aq->pdev->dev);
if (ret)
return ret;
}
atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
return atmel_qspi_wait_for_completion(aq, QSPI_SR_CSRA);
+18 -23
View File
@@ -70,8 +70,7 @@
#define INT_RX_CHANNEL_OVERFLOW BIT(2)
#define INT_TX_CHANNEL_UNDERRUN BIT(3)
#define INT_ENABLE_MASK (CONTROL_RX_DATA_INT | CONTROL_TX_DATA_INT | \
CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT)
#define INT_ENABLE_MASK (CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT)
#define REG_CONTROL (0x00)
#define REG_FRAME_SIZE (0x04)
@@ -133,10 +132,15 @@ static inline void mchp_corespi_disable(struct mchp_corespi *spi)
mchp_corespi_write(spi, REG_CONTROL, control);
}
static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi)
static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi, int fifo_max)
{
while (spi->rx_len >= spi->n_bytes && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) {
u32 data = mchp_corespi_read(spi, REG_RX_DATA);
for (int i = 0; i < fifo_max; i++) {
u32 data;
while (mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)
;
data = mchp_corespi_read(spi, REG_RX_DATA);
spi->rx_len -= spi->n_bytes;
@@ -211,11 +215,10 @@ static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len)
mchp_corespi_write(spi, REG_FRAMESUP, len);
}
static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi)
static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi, int fifo_max)
{
int fifo_max, i = 0;
int i = 0;
fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes);
mchp_corespi_set_xfer_size(spi, fifo_max);
while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) {
@@ -413,19 +416,6 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
if (intfield == 0)
return IRQ_NONE;
if (intfield & INT_TXDONE)
mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE);
if (intfield & INT_RXRDY) {
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY);
if (spi->rx_len)
mchp_corespi_read_fifo(spi);
}
if (!spi->rx_len && !spi->tx_len)
finalise = true;
if (intfield & INT_RX_CHANNEL_OVERFLOW) {
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW);
finalise = true;
@@ -512,9 +502,14 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select);
while (spi->tx_len)
mchp_corespi_write_fifo(spi);
while (spi->tx_len) {
int fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes);
mchp_corespi_write_fifo(spi, fifo_max);
mchp_corespi_read_fifo(spi, fifo_max);
}
spi_finalize_current_transfer(host);
return 1;
}