Commit 6e8e2f82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 0fed89a9 91cf42c6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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;
}