mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
spi: tegra210-quad: Refactor error handling into helper functions
Extract common cleanup code into dedicated helper functions to simplify the code and improve readability. This refactoring includes: - tegra_qspi_reset(): Device reset and interrupt cleanup - tegra_qspi_dma_stop(): DMA termination and disable - tegra_qspi_pio_stop(): PIO mode disable No functional changes. This is purely a code reorganization to prepare for improved timeout handling in subsequent patches. Signed-off-by: Vishwaroop A <va@nvidia.com> Acked-by: Thierry Reding <treding@nvidia.com> Link: https://patch.msgid.link/20251028155703.4151791-3-va@nvidia.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
@@ -1019,15 +1019,20 @@ static void tegra_qspi_dump_regs(struct tegra_qspi *tqspi)
|
||||
tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS));
|
||||
}
|
||||
|
||||
static void tegra_qspi_reset(struct tegra_qspi *tqspi)
|
||||
{
|
||||
if (device_reset(tqspi->dev) < 0) {
|
||||
dev_warn_once(tqspi->dev, "device reset failed\n");
|
||||
tegra_qspi_mask_clear_irq(tqspi);
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_qspi_handle_error(struct tegra_qspi *tqspi)
|
||||
{
|
||||
dev_err(tqspi->dev, "error in transfer, fifo status 0x%08x\n", tqspi->status_reg);
|
||||
tegra_qspi_dump_regs(tqspi);
|
||||
tegra_qspi_flush_fifos(tqspi, true);
|
||||
if (device_reset(tqspi->dev) < 0) {
|
||||
dev_warn_once(tqspi->dev, "device reset failed\n");
|
||||
tegra_qspi_mask_clear_irq(tqspi);
|
||||
}
|
||||
tegra_qspi_reset(tqspi);
|
||||
}
|
||||
|
||||
static void tegra_qspi_transfer_end(struct spi_device *spi)
|
||||
@@ -1074,6 +1079,30 @@ static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len)
|
||||
return addr_config;
|
||||
}
|
||||
|
||||
static void tegra_qspi_dma_stop(struct tegra_qspi *tqspi)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if ((tqspi->cur_direction & DATA_DIR_TX) && tqspi->tx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->tx_dma_chan);
|
||||
|
||||
if ((tqspi->cur_direction & DATA_DIR_RX) && tqspi->rx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->rx_dma_chan);
|
||||
|
||||
value = tegra_qspi_readl(tqspi, QSPI_DMA_CTL);
|
||||
value &= ~QSPI_DMA_EN;
|
||||
tegra_qspi_writel(tqspi, value, QSPI_DMA_CTL);
|
||||
}
|
||||
|
||||
static void tegra_qspi_pio_stop(struct tegra_qspi *tqspi)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = tegra_qspi_readl(tqspi, QSPI_COMMAND1);
|
||||
value &= ~QSPI_PIO;
|
||||
tegra_qspi_writel(tqspi, value, QSPI_COMMAND1);
|
||||
}
|
||||
|
||||
static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
@@ -1081,7 +1110,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
|
||||
struct spi_transfer *xfer;
|
||||
struct spi_device *spi = msg->spi;
|
||||
u8 transfer_phase = 0;
|
||||
u32 cmd1 = 0, dma_ctl = 0;
|
||||
u32 cmd1 = 0;
|
||||
int ret = 0;
|
||||
u32 address_value = 0;
|
||||
u32 cmd_config = 0, addr_config = 0;
|
||||
@@ -1150,39 +1179,16 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
|
||||
if (WARN_ON_ONCE(ret == 0)) {
|
||||
dev_err_ratelimited(tqspi->dev,
|
||||
"QSPI Transfer failed with timeout\n");
|
||||
if (tqspi->is_curr_dma_xfer) {
|
||||
if ((tqspi->cur_direction & DATA_DIR_TX) &&
|
||||
tqspi->tx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->tx_dma_chan);
|
||||
if ((tqspi->cur_direction & DATA_DIR_RX) &&
|
||||
tqspi->rx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->rx_dma_chan);
|
||||
}
|
||||
|
||||
/* Abort transfer by resetting pio/dma bit */
|
||||
if (!tqspi->is_curr_dma_xfer) {
|
||||
cmd1 = tegra_qspi_readl
|
||||
(tqspi,
|
||||
QSPI_COMMAND1);
|
||||
cmd1 &= ~QSPI_PIO;
|
||||
tegra_qspi_writel
|
||||
(tqspi, cmd1,
|
||||
QSPI_COMMAND1);
|
||||
} else {
|
||||
dma_ctl = tegra_qspi_readl
|
||||
(tqspi,
|
||||
QSPI_DMA_CTL);
|
||||
dma_ctl &= ~QSPI_DMA_EN;
|
||||
tegra_qspi_writel(tqspi, dma_ctl,
|
||||
QSPI_DMA_CTL);
|
||||
}
|
||||
if (tqspi->is_curr_dma_xfer)
|
||||
tegra_qspi_dma_stop(tqspi);
|
||||
else
|
||||
tegra_qspi_pio_stop(tqspi);
|
||||
|
||||
/* Reset controller if timeout happens */
|
||||
if (device_reset(tqspi->dev) < 0) {
|
||||
dev_warn_once(tqspi->dev,
|
||||
"device reset failed\n");
|
||||
tegra_qspi_mask_clear_irq(tqspi);
|
||||
}
|
||||
tegra_qspi_reset(tqspi);
|
||||
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
@@ -1276,12 +1282,10 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,
|
||||
QSPI_DMA_TIMEOUT);
|
||||
if (WARN_ON(ret == 0)) {
|
||||
dev_err(tqspi->dev, "transfer timeout\n");
|
||||
if (tqspi->is_curr_dma_xfer) {
|
||||
if ((tqspi->cur_direction & DATA_DIR_TX) && tqspi->tx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->tx_dma_chan);
|
||||
if ((tqspi->cur_direction & DATA_DIR_RX) && tqspi->rx_dma_chan)
|
||||
dmaengine_terminate_all(tqspi->rx_dma_chan);
|
||||
}
|
||||
|
||||
if (tqspi->is_curr_dma_xfer)
|
||||
tegra_qspi_dma_stop(tqspi);
|
||||
|
||||
tegra_qspi_handle_error(tqspi);
|
||||
ret = -EIO;
|
||||
goto complete_xfer;
|
||||
|
||||
Reference in New Issue
Block a user