Skip to content

Commit c05efd6

Browse files
bhuvanchandradvgregkh
authored andcommitted
tty: serial: fsl_lpuart: Update suspend/resume for DMA mode
When DMA mode is enabled one need to make sure the DMA channels are idle before entering suspend mode especially when UART ports which are set as wakeup source and console port with no_console_suspend is set. This patch takes care of gracefully releasing DMA channels for the above two cases and start the DMA at resume. Signed-off-by: Bhuvanchandra DV <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6250cc3 commit c05efd6

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

drivers/tty/serial/fsl_lpuart.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,30 @@ static int lpuart_suspend(struct device *dev)
19491949
}
19501950

19511951
uart_suspend_port(&lpuart_reg, &sport->port);
1952+
1953+
if (sport->lpuart_dma_rx_use) {
1954+
/*
1955+
* EDMA driver during suspend will forcefully release any
1956+
* non-idle DMA channels. If port wakeup is enabled or if port
1957+
* is console port or 'no_console_suspend' is set the Rx DMA
1958+
* cannot resume as as expected, hence gracefully release the
1959+
* Rx DMA path before suspend and start Rx DMA path on resume.
1960+
*/
1961+
if (sport->port.irq_wake) {
1962+
del_timer_sync(&sport->lpuart_timer);
1963+
lpuart_dma_rx_free(&sport->port);
1964+
}
1965+
1966+
/* Disable Rx DMA to use UART port as wakeup source */
1967+
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_RDMAS,
1968+
sport->port.membase + UARTCR5);
1969+
}
1970+
1971+
if (sport->lpuart_dma_tx_use) {
1972+
sport->dma_tx_in_progress = false;
1973+
dmaengine_terminate_all(sport->dma_tx_chan);
1974+
}
1975+
19521976
if (sport->port.suspended && !sport->port.irq_wake)
19531977
clk_disable_unprepare(sport->clk);
19541978

@@ -1976,6 +2000,26 @@ static int lpuart_resume(struct device *dev)
19762000
writeb(temp, sport->port.membase + UARTCR2);
19772001
}
19782002

2003+
if (sport->lpuart_dma_rx_use) {
2004+
if (sport->port.irq_wake) {
2005+
if (!lpuart_start_rx_dma(sport)) {
2006+
sport->lpuart_dma_rx_use = true;
2007+
rx_dma_timer_init(sport);
2008+
} else {
2009+
sport->lpuart_dma_rx_use = false;
2010+
}
2011+
}
2012+
}
2013+
2014+
if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
2015+
init_waitqueue_head(&sport->dma_wait);
2016+
sport->lpuart_dma_tx_use = true;
2017+
writeb(readb(sport->port.membase + UARTCR5) |
2018+
UARTCR5_TDMAS, sport->port.membase + UARTCR5);
2019+
} else {
2020+
sport->lpuart_dma_tx_use = false;
2021+
}
2022+
19792023
uart_resume_port(&lpuart_reg, &sport->port);
19802024

19812025
return 0;

0 commit comments

Comments
 (0)