dmaengine: stm32-dma: add alternate REQ/ACK protocol management
authorAmelie Delaunay <amelie.delaunay@foss.st.com>
Thu, 24 Jun 2021 09:39:59 +0000 (11:39 +0200)
committerVinod Koul <vkoul@kernel.org>
Wed, 28 Jul 2021 07:09:48 +0000 (12:39 +0530)
STM32 USART/UART is not managing correctly the default DMA REQ/ACK protocol
leading to possibly lock the DMA stream.
Default protocol consists in maintaining ACK signal up to the removal of
REQuest and the transfer completion.
In case of alternative REQ/ACK protocol, ACK de-assertion does not wait the
removal of the REQuest, but only the transfer completion.

This patch retrieves the need of the alternative protocol through the
device tree, and sets the protocol accordingly.
It also unwrap STM32_DMA_DIRECT_MODE_GET macro definition for consistency
with new STM32_DMA_ALT_ACK_MODE_GET macro definition.

Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
Link: https://lore.kernel.org/r/20210624093959.142265-3-amelie.delaunay@foss.st.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/stm32-dma.c

index f54ecb1..d3aa34b 100644 (file)
@@ -60,6 +60,7 @@
 #define STM32_DMA_SCR_PSIZE_GET(n)     ((n & STM32_DMA_SCR_PSIZE_MASK) >> 11)
 #define STM32_DMA_SCR_DIR_MASK         GENMASK(7, 6)
 #define STM32_DMA_SCR_DIR(n)           ((n & 0x3) << 6)
+#define STM32_DMA_SCR_TRBUFF           BIT(20) /* Bufferable transfer for USART/UART */
 #define STM32_DMA_SCR_CT               BIT(19) /* Target in double buffer */
 #define STM32_DMA_SCR_DBM              BIT(18) /* Double Buffer Mode */
 #define STM32_DMA_SCR_PINCOS           BIT(15) /* Peripheral inc offset size */
 #define STM32_DMA_THRESHOLD_FTR_MASK   GENMASK(1, 0)
 #define STM32_DMA_THRESHOLD_FTR_GET(n) ((n) & STM32_DMA_THRESHOLD_FTR_MASK)
 #define STM32_DMA_DIRECT_MODE_MASK     BIT(2)
-#define STM32_DMA_DIRECT_MODE_GET(n)   (((n) & STM32_DMA_DIRECT_MODE_MASK) \
-                                        >> 2)
+#define STM32_DMA_DIRECT_MODE_GET(n)   (((n) & STM32_DMA_DIRECT_MODE_MASK) >> 2)
+#define STM32_DMA_ALT_ACK_MODE_MASK    BIT(4)
+#define STM32_DMA_ALT_ACK_MODE_GET(n)  (((n) & STM32_DMA_ALT_ACK_MODE_MASK) >> 4)
 
 enum stm32_dma_width {
        STM32_DMA_BYTE,
@@ -1252,6 +1254,8 @@ static void stm32_dma_set_config(struct stm32_dma_chan *chan,
        chan->threshold = STM32_DMA_THRESHOLD_FTR_GET(cfg->features);
        if (STM32_DMA_DIRECT_MODE_GET(cfg->features))
                chan->threshold = STM32_DMA_FIFO_THRESHOLD_NONE;
+       if (STM32_DMA_ALT_ACK_MODE_GET(cfg->features))
+               chan->chan_reg.dma_scr |= STM32_DMA_SCR_TRBUFF;
 }
 
 static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,