Unverified Commit ba9b2865 authored by Carlos Song's avatar Carlos Song Committed by Mark Brown
Browse files

spi: imx: enable DMA mode for target operation



Enable DMA mode for SPI IMX in target mode. Disable the word delay feature
for target mode, because target mode should always keep high performance
to make sure it can follow the master. Target mode continues to operate in
dynamic burst mode.

Signed-off-by: default avatarCarlos Song <carlos.song@nxp.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20251203085949.2922166-7-carlos.song@nxp.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent faa8e404
Loading
Loading
Loading
Loading
+57 −20
Original line number Diff line number Diff line
@@ -264,7 +264,13 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device
	if (!controller->dma_rx)
		return false;

	if (spi_imx->target_mode)
	/*
	 * Due to Freescale errata ERR003775 "eCSPI: Burst completion by Chip
	 * Select (SS) signal in Slave mode is not functional" burst size must
	 * be set exactly to the size of the transfer. This limit SPI transaction
	 * with maximum 2^12 bits.
	 */
	if (transfer->len > MX53_MAX_TRANSFER_BYTES && spi_imx->target_mode)
		return false;

	if (transfer->len < spi_imx->devtype_data->fifo_size)
@@ -1763,6 +1769,7 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,

	transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);

	if (!spi_imx->target_mode) {
		/* Wait SDMA to finish the data transfer.*/
		time_left = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
							transfer_timeout);
@@ -1781,6 +1788,33 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,
			dmaengine_terminate_all(controller->dma_rx);
			return -ETIMEDOUT;
		}
	} else {
		spi_imx->target_aborted = false;

		if (wait_for_completion_interruptible(&spi_imx->dma_tx_completion) ||
		    READ_ONCE(spi_imx->target_aborted)) {
			dev_dbg(spi_imx->dev, "I/O Error in DMA TX interrupted\n");
			dmaengine_terminate_all(controller->dma_tx);
			dmaengine_terminate_all(controller->dma_rx);
			return -EINTR;
		}

		if (wait_for_completion_interruptible(&spi_imx->dma_rx_completion) ||
		    READ_ONCE(spi_imx->target_aborted)) {
			dev_dbg(spi_imx->dev, "I/O Error in DMA RX interrupted\n");
			dmaengine_terminate_all(controller->dma_rx);
			return -EINTR;
		}

		/*
		 * ECSPI has a HW issue when works in Target mode, after 64 words
		 * writtern to TXFIFO, even TXFIFO becomes empty, ECSPI_TXDATA keeps
		 * shift out the last word data, so we have to disable ECSPI when in
		 * target mode after the transfer completes.
		 */
		if (spi_imx->devtype_data->disable)
			spi_imx->devtype_data->disable(spi_imx);
	}

	return 0;

@@ -1902,7 +1936,7 @@ static int spi_imx_dma_package_transfer(struct spi_imx_data *spi_imx,
static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
				struct spi_transfer *transfer)
{
	bool word_delay = transfer->word_delay.value != 0;
	bool word_delay = transfer->word_delay.value != 0 && !spi_imx->target_mode;
	int ret;
	int i;

@@ -2108,7 +2142,7 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
	while (spi_imx->devtype_data->rx_available(spi_imx))
		readl(spi_imx->base + MXC_CSPIRXDATA);

	if (spi_imx->target_mode)
	if (spi_imx->target_mode && !spi_imx->usedma)
		return spi_imx_pio_transfer_target(spi, transfer);

	/*
@@ -2120,6 +2154,9 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
		ret = spi_imx_dma_transfer(spi_imx, transfer);
		if (transfer->error & SPI_TRANS_FAIL_NO_START) {
			spi_imx->usedma = false;
			if (spi_imx->target_mode)
				return spi_imx_pio_transfer_target(spi, transfer);
			else
				return spi_imx_pio_transfer(spi, transfer);
		}
		return ret;