serial: 8250: dma: Allow driver operations before starting DMA transfers
authorMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 22 Apr 2022 18:06:11 +0000 (20:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Apr 2022 11:25:47 +0000 (13:25 +0200)
One situation where this could be used is when configuring the UART
controller to be the DMA flow controller. This is a typical case where
the driver might need to program a few more registers before starting a
DMA transfer. Provide the necessary infrastructure to support this
case.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/r/20220422180615.9098-6-miquel.raynal@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_dma.c

index 39ffeb37786ff7cba0d703b795fba30e3619b963..5a4e05c0e552a5de4557b9956ce5f1cf088b4f07 100644 (file)
@@ -17,6 +17,8 @@
 struct uart_8250_dma {
        int (*tx_dma)(struct uart_8250_port *p);
        int (*rx_dma)(struct uart_8250_port *p);
+       void (*prepare_tx_dma)(struct uart_8250_port *p);
+       void (*prepare_rx_dma)(struct uart_8250_port *p);
 
        /* Filter function */
        dma_filter_fn           fn;
@@ -302,6 +304,22 @@ extern int serial8250_rx_dma(struct uart_8250_port *);
 extern void serial8250_rx_dma_flush(struct uart_8250_port *);
 extern int serial8250_request_dma(struct uart_8250_port *);
 extern void serial8250_release_dma(struct uart_8250_port *);
+
+static inline void serial8250_do_prepare_tx_dma(struct uart_8250_port *p)
+{
+       struct uart_8250_dma *dma = p->dma;
+
+       if (dma->prepare_tx_dma)
+               dma->prepare_tx_dma(p);
+}
+
+static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p)
+{
+       struct uart_8250_dma *dma = p->dma;
+
+       if (dma->prepare_rx_dma)
+               dma->prepare_rx_dma(p);
+}
 #else
 static inline int serial8250_tx_dma(struct uart_8250_port *p)
 {
index b3c3f7e5851aba3a17ccb7f80f18586c5aac4e4c..1bdc8d6432fef9e841b57886e794a6b7a506ee93 100644 (file)
@@ -86,6 +86,8 @@ int serial8250_tx_dma(struct uart_8250_port *p)
 
        dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 
+       serial8250_do_prepare_tx_dma(p);
+
        desc = dmaengine_prep_slave_single(dma->txchan,
                                           dma->tx_addr + xmit->tail,
                                           dma->tx_size, DMA_MEM_TO_DEV,
@@ -123,6 +125,8 @@ int serial8250_rx_dma(struct uart_8250_port *p)
        if (dma->rx_running)
                return 0;
 
+       serial8250_do_prepare_rx_dma(p);
+
        desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
                                           dma->rx_size, DMA_DEV_TO_MEM,
                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);