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@xxxxxxxxxxxxxxx> Signed-off-by: Miquel Raynal <miquel.raynal@xxxxxxxxxxx> --- drivers/tty/serial/8250/8250.h | 18 ++++++++++++++++++ drivers/tty/serial/8250/8250_dma.c | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index db784ace25d8..d19f24e4d13e 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -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; @@ -301,6 +303,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) { diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index 890fa7ddaa7f..558d3a2ac65b 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -77,6 +77,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, @@ -114,6 +116,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); -- 2.27.0