Commit c4fc9e5b authored by Sowjanya Komatineni's avatar Sowjanya Komatineni Committed by Mark Brown

spi: tegra114: flush fifos

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>
parent 32bd1a95
...@@ -499,22 +499,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) ...@@ -499,22 +499,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
return 0; return 0;
} }
static int tegra_spi_start_dma_based_transfer( static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
struct tegra_spi_data *tspi, struct spi_transfer *t)
{ {
u32 val; unsigned long timeout = jiffies + HZ;
unsigned int len;
int ret = 0;
u32 status; u32 status;
/* Make sure that Rx and Tx fifo are empty */
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
(unsigned)status); 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; 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); val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
tegra_spi_writel(tspi, val, SPI_DMA_BLK); tegra_spi_writel(tspi, val, SPI_DMA_BLK);
...@@ -779,6 +794,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, ...@@ -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", dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
tspi->def_command1_reg, (unsigned)command1); tspi->def_command1_reg, (unsigned)command1);
ret = tegra_spi_flush_fifos(tspi);
if (ret < 0)
return ret;
if (total_fifo_words > SPI_FIFO_DEPTH) if (total_fifo_words > SPI_FIFO_DEPTH)
ret = tegra_spi_start_dma_based_transfer(tspi, t); ret = tegra_spi_start_dma_based_transfer(tspi, t);
else else
...@@ -876,6 +894,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, ...@@ -876,6 +894,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
(tspi->cur_direction & DATA_DIR_RX)) (tspi->cur_direction & DATA_DIR_RX))
dmaengine_terminate_all(tspi->rx_dma_chan); dmaengine_terminate_all(tspi->rx_dma_chan);
ret = -EIO; ret = -EIO;
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst); reset_control_assert(tspi->rst);
udelay(2); udelay(2);
reset_control_deassert(tspi->rst); reset_control_deassert(tspi->rst);
...@@ -929,6 +948,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) ...@@ -929,6 +948,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg); tspi->status_reg);
dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg); tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst); reset_control_assert(tspi->rst);
udelay(2); udelay(2);
reset_control_deassert(tspi->rst); reset_control_deassert(tspi->rst);
...@@ -1001,6 +1021,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) ...@@ -1001,6 +1021,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg); tspi->status_reg);
dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg); tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst); reset_control_assert(tspi->rst);
udelay(2); udelay(2);
reset_control_deassert(tspi->rst); 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