Commit e4fb03fe authored by Miquel Raynal's avatar Miquel Raynal Committed by Greg Kroah-Hartman
Browse files

serial: 8250: dma: Allow driver operations before starting DMA transfers



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: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/r/20220422180615.9098-6-miquel.raynal@bootlin.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 593dea00
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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)
{
+4 −0
Original line number Diff line number Diff line
@@ -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);