diff options
author | Stefan Agner <stefan@agner.ch> | 2014-11-27 21:52:45 +0100 |
---|---|---|
committer | Stefan Agner <stefan@agner.ch> | 2016-02-10 18:42:34 -0800 |
commit | 2ebcbac5a22ac1f423b912af6957b8fa060380a4 (patch) | |
tree | d778e840f108772bccf149c53f0651ed06210831 /drivers/tty/serial/fsl_lpuart.c | |
parent | e30f9ce480d0d4ed69e49e11ee95eafc81cca949 (diff) |
tty: serial: fsl_lpuart: support suspend/resume
In order to allow wake support in STOP sleep mode, clocks are
needed. Use imx_clk_gate2_cgr to disable automatic clock gating
in low power mode STOP. This allows to enable wake by UART using:
echo enabled > /sys/class/tty/ttyLP0/power/wakeup
However, if wake is not enabled, the driver should disable the
clocks explicitly to save power.
Diffstat (limited to 'drivers/tty/serial/fsl_lpuart.c')
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 3d790033744e..94e29bac4392 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -483,9 +483,8 @@ static void lpuart_dma_rx_complete(void *arg) spin_unlock_irqrestore(&sport->port.lock, flags); } -static void lpuart_timer_func(unsigned long data) +static void lpuart_dma_rx_terminate(struct lpuart_port *sport) { - struct lpuart_port *sport = (struct lpuart_port *)data; struct tty_port *port = &sport->port.state->port; struct dma_tx_state state; unsigned long flags; @@ -510,6 +509,11 @@ static void lpuart_timer_func(unsigned long data) spin_unlock_irqrestore(&sport->port.lock, flags); } +static void lpuart_timer_func(unsigned long data) +{ + lpuart_dma_rx_terminate((struct lpuart_port *)data); +} + static inline void lpuart_prepare_rx(struct lpuart_port *sport) { unsigned long flags; @@ -1915,7 +1919,12 @@ static int lpuart_suspend(struct device *dev) writeb(temp, sport->port.membase + UARTCR2); } + if (sport->dma_rx_in_progress) + lpuart_dma_rx_terminate(sport); + uart_suspend_port(&lpuart_reg, &sport->port); + if (sport->port.suspended && !sport->port.irq_wake) + clk_disable_unprepare(sport->clk); return 0; } @@ -1925,6 +1934,9 @@ static int lpuart_resume(struct device *dev) struct lpuart_port *sport = dev_get_drvdata(dev); unsigned long temp; + if (sport->port.suspended && !sport->port.irq_wake) + clk_prepare_enable(sport->clk); + if (sport->lpuart32) { lpuart32_setup_watermark(sport); temp = lpuart32_read(sport->port.membase + UARTCTRL); |