From 43dba9f3f98c2b184a19f856f06fe22817bfd9e0 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 22 May 2020 03:07:51 +0300 Subject: [PATCH 1/4] spi: dw: Enable interrupts in accordance with DMA xfer mode It's pointless to track the Tx overrun interrupts if Rx-only SPI transfer is issued. Similarly there is no need in handling the Rx overrun/underrun interrupts if Tx-only SPI transfer is executed. So lets unmask the interrupts only if corresponding SPI transactions are implied. Co-developed-by: Georgy Vlasov Signed-off-by: Georgy Vlasov Signed-off-by: Serge Semin Cc: Ramil Zaripov Cc: Alexey Malahov Cc: Thomas Bogendoerfer Cc: Paul Burton Cc: Ralf Baechle Cc: Arnd Bergmann Cc: Andy Shevchenko Cc: Rob Herring Cc: linux-mips@vger.kernel.org Cc: devicetree@vger.kernel.org Link: https://lore.kernel.org/r/20200522000806.7381-3-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mid.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index f9757a370699..1578dfebc92b 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -243,19 +243,23 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws, static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer) { - u16 dma_ctrl = 0; + u16 imr = 0, dma_ctrl = 0; dw_writel(dws, DW_SPI_DMARDLR, 0xf); dw_writel(dws, DW_SPI_DMATDLR, 0x10); - if (xfer->tx_buf) + if (xfer->tx_buf) { dma_ctrl |= SPI_DMA_TDMAE; - if (xfer->rx_buf) + imr |= SPI_INT_TXOI; + } + if (xfer->rx_buf) { dma_ctrl |= SPI_DMA_RDMAE; + imr |= SPI_INT_RXUI | SPI_INT_RXOI; + } dw_writel(dws, DW_SPI_DMACR, dma_ctrl); /* Set the interrupt mask */ - spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI); + spi_umask_intr(dws, imr); dws->transfer_handler = dma_transfer; From 2afccbd283ae63072391ea17ac1d772ed9d33749 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 22 May 2020 03:07:52 +0300 Subject: [PATCH 2/4] spi: dw: Discard static DW DMA slave structures Having them declared is redundant since each struct dw_dma_chan has the same structure embedded and the structure from the passed dma_chan private pointer will be copied there as a result of the next calls chain: dma_request_channel() -> find_candidate() -> dma_chan_get() -> device_alloc_chan_resources() = dwc_alloc_chan_resources() -> dw_dma_filter(). So just remove the static dw_dma_chan structures and use a locally declared data instance with dst_id/src_id set to the same values as the static copies used to have. Co-developed-by: Georgy Vlasov Signed-off-by: Georgy Vlasov Co-developed-by: Ramil Zaripov Signed-off-by: Ramil Zaripov Signed-off-by: Serge Semin Cc: Alexey Malahov Cc: Thomas Bogendoerfer Cc: Paul Burton Cc: Ralf Baechle Cc: Andy Shevchenko Cc: Arnd Bergmann Cc: Rob Herring Cc: linux-mips@vger.kernel.org Cc: devicetree@vger.kernel.org Link: https://lore.kernel.org/r/20200522000806.7381-4-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mid.c | 19 ++++++++----------- drivers/spi/spi-dw.h | 2 -- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 1578dfebc92b..a39bde9996a4 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -20,9 +20,6 @@ #define RX_BUSY 0 #define TX_BUSY 1 -static struct dw_dma_slave mid_dma_tx = { .dst_id = 1 }; -static struct dw_dma_slave mid_dma_rx = { .src_id = 0 }; - static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param) { struct dw_dma_slave *s = param; @@ -36,9 +33,11 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param) static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) { + struct dw_dma_slave slave = { + .src_id = 0, + .dst_id = 0 + }; struct pci_dev *dma_dev; - struct dw_dma_slave *tx = dws->dma_tx; - struct dw_dma_slave *rx = dws->dma_rx; dma_cap_mask_t mask; /* @@ -53,14 +52,14 @@ static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) dma_cap_set(DMA_SLAVE, mask); /* 1. Init rx channel */ - rx->dma_dev = &dma_dev->dev; - dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, rx); + slave.dma_dev = &dma_dev->dev; + dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, &slave); if (!dws->rxchan) goto err_exit; /* 2. Init tx channel */ - tx->dma_dev = &dma_dev->dev; - dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, tx); + slave.dst_id = 1; + dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, &slave); if (!dws->txchan) goto free_rxchan; @@ -317,8 +316,6 @@ static const struct dw_spi_dma_ops mfld_dma_ops = { static void dw_spi_mid_setup_dma_mfld(struct dw_spi *dws) { - dws->dma_tx = &mid_dma_tx; - dws->dma_rx = &mid_dma_rx; dws->dma_ops = &mfld_dma_ops; } diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index e92d43b9a9e6..e1b565438f23 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -146,8 +146,6 @@ struct dw_spi { unsigned long dma_chan_busy; dma_addr_t dma_addr; /* phy address of the Data register */ const struct dw_spi_dma_ops *dma_ops; - void *dma_tx; - void *dma_rx; /* Bus interface info */ void *priv; From 595c19d4543fed18384fd7d1edf6f381d4eed34e Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 22 May 2020 03:07:53 +0300 Subject: [PATCH 3/4] spi: dw: Discard unused void priv pointer Seeing the "void *priv" member of the dw_spi data structure is unused let's remove it. The glue-layers can embed the DW APB SSI controller descriptor into their private data object. MMIO driver for instance already utilizes that design pattern. Signed-off-by: Serge Semin Reviewed-by: Andy Shevchenko Cc: Georgy Vlasov Cc: Ramil Zaripov Cc: Alexey Malahov Cc: Thomas Bogendoerfer Cc: Paul Burton Cc: Ralf Baechle Cc: Andy Shevchenko Cc: Arnd Bergmann Cc: Rob Herring Cc: linux-mips@vger.kernel.org Cc: devicetree@vger.kernel.org Link: https://lore.kernel.org/r/20200522000806.7381-5-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown --- drivers/spi/spi-dw.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index e1b565438f23..0aa3a4be1046 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -147,8 +147,6 @@ struct dw_spi { dma_addr_t dma_addr; /* phy address of the Data register */ const struct dw_spi_dma_ops *dma_ops; - /* Bus interface info */ - void *priv; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif From 4fdc03a9bc47b6cf35a8821e545075d9f5f24906 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 22 May 2020 03:07:54 +0300 Subject: [PATCH 4/4] spi: dw: Discard dma_width member of the dw_spi structure This member has exactly the same value as n_bytes of the DW SPI private data object, it's calculated at the same point of the transfer method, n_bytes isn't changed during the whole transfer, and they even serve for the same purpose - keep number of bytes per transfer word, though the dma_width is used only to calculate the DMA source/destination addresses width, which n_bytes could be also utilized for. Taking all of these into account let's replace the dma_width member usage with n_bytes one and remove the former. Signed-off-by: Serge Semin Reviewed-by: Andy Shevchenko Cc: Georgy Vlasov Cc: Ramil Zaripov Cc: Alexey Malahov Cc: Thomas Bogendoerfer Cc: Paul Burton Cc: Ralf Baechle Cc: Andy Shevchenko Cc: Arnd Bergmann Cc: Rob Herring Cc: linux-mips@vger.kernel.org Cc: devicetree@vger.kernel.org Link: https://lore.kernel.org/r/20200522000806.7381-6-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mid.c | 10 +++++----- drivers/spi/spi-dw.c | 1 - drivers/spi/spi-dw.h | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index a39bde9996a4..b1710132b7b2 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -133,10 +133,10 @@ static bool mid_spi_can_dma(struct spi_controller *master, return xfer->len > dws->fifo_len; } -static enum dma_slave_buswidth convert_dma_width(u32 dma_width) { - if (dma_width == 1) +static enum dma_slave_buswidth convert_dma_width(u8 n_bytes) { + if (n_bytes == 1) return DMA_SLAVE_BUSWIDTH_1_BYTE; - else if (dma_width == 2) + else if (n_bytes == 2) return DMA_SLAVE_BUSWIDTH_2_BYTES; return DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -172,7 +172,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws, txconf.dst_addr = dws->dma_addr; txconf.dst_maxburst = 16; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - txconf.dst_addr_width = convert_dma_width(dws->dma_width); + txconf.dst_addr_width = convert_dma_width(dws->n_bytes); txconf.device_fc = false; dmaengine_slave_config(dws->txchan, &txconf); @@ -221,7 +221,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws, rxconf.src_addr = dws->dma_addr; rxconf.src_maxburst = 16; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - rxconf.src_addr_width = convert_dma_width(dws->dma_width); + rxconf.src_addr_width = convert_dma_width(dws->n_bytes); rxconf.device_fc = false; dmaengine_slave_config(dws->rxchan, &rxconf); diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 450c8218caeb..1edb8cdd11ee 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -353,7 +353,6 @@ static int dw_spi_transfer_one(struct spi_controller *master, } dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); - dws->dma_width = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); cr0 = dws->update_cr0(master, spi, transfer); dw_writel(dws, DW_SPI_CTRLR0, cr0); diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 0aa3a4be1046..79782e93eb12 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -136,7 +136,6 @@ struct dw_spi { void *rx_end; int dma_mapped; u8 n_bytes; /* current is a 1/2 bytes op */ - u32 dma_width; irqreturn_t (*transfer_handler)(struct dw_spi *dws); u32 current_freq; /* frequency in hz */