Commit 262a7b66 authored by Sowjanya Komatineni's avatar Sowjanya Komatineni Committed by Greg Kroah-Hartman

spi: tegra114: flush fifos

[ Upstream commit c4fc9e5b ]

Fixes: Flush TX and RX FIFOs before start of new transfer and on FIFO
overflow or underrun errors.
Signed-off-by: default avatarSowjanya Komatineni <skomatineni@nvidia.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent d911ba66
......@@ -499,22 +499,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
return 0;
}
static int tegra_spi_start_dma_based_transfer(
struct tegra_spi_data *tspi, struct spi_transfer *t)
static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
{
u32 val;
unsigned int len;
int ret = 0;
unsigned long timeout = jiffies + HZ;
u32 status;
/* Make sure that Rx and Tx fifo are empty */
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
(unsigned)status);
return -EIO;
status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
tegra_spi_writel(tspi, status, SPI_FIFO_STATUS);
while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if (time_after(jiffies, timeout)) {
dev_err(tspi->dev,
"timeout waiting for fifo flush\n");
return -EIO;
}
udelay(1);
}
}
return 0;
}
static int tegra_spi_start_dma_based_transfer(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
u32 val;
unsigned int len;
int ret = 0;
val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
tegra_spi_writel(tspi, val, SPI_DMA_BLK);
......@@ -779,6 +794,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
tspi->def_command1_reg, (unsigned)command1);
ret = tegra_spi_flush_fifos(tspi);
if (ret < 0)
return ret;
if (total_fifo_words > SPI_FIFO_DEPTH)
ret = tegra_spi_start_dma_based_transfer(tspi, t);
else
......@@ -876,6 +894,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
(tspi->cur_direction & DATA_DIR_RX))
dmaengine_terminate_all(tspi->rx_dma_chan);
ret = -EIO;
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
......@@ -929,6 +948,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
......@@ -1001,6 +1021,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment