Skip to content

Commit 43543e6

Browse files
SherrySun5gregkh
authored andcommitted
tty: serial: fsl_lpuart: Add runtime pm support
Add runtime pm support to manage the lpuart clock. Signed-off-by: Sherry Sun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4f5cb8c commit 43543e6

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

drivers/tty/serial/fsl_lpuart.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/of_device.h>
2020
#include <linux/of_dma.h>
2121
#include <linux/pinctrl/consumer.h>
22+
#include <linux/pm_runtime.h>
2223
#include <linux/serial_core.h>
2324
#include <linux/slab.h>
2425
#include <linux/tty_flip.h>
@@ -233,6 +234,7 @@
233234

234235
/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
235236
#define DMA_RX_TIMEOUT (10)
237+
#define UART_AUTOSUSPEND_TIMEOUT 3000
236238

237239
#define DRIVER_NAME "fsl-lpuart"
238240
#define DEV_NAME "ttyLP"
@@ -793,6 +795,20 @@ static void lpuart32_start_tx(struct uart_port *port)
793795
}
794796
}
795797

798+
static void
799+
lpuart_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
800+
{
801+
switch (state) {
802+
case UART_PM_STATE_OFF:
803+
pm_runtime_mark_last_busy(port->dev);
804+
pm_runtime_put_autosuspend(port->dev);
805+
break;
806+
default:
807+
pm_runtime_get_sync(port->dev);
808+
break;
809+
}
810+
}
811+
796812
/* return TIOCSER_TEMT when transmitter is not busy */
797813
static unsigned int lpuart_tx_empty(struct uart_port *port)
798814
{
@@ -2229,6 +2245,7 @@ static const struct uart_ops lpuart_pops = {
22292245
.startup = lpuart_startup,
22302246
.shutdown = lpuart_shutdown,
22312247
.set_termios = lpuart_set_termios,
2248+
.pm = lpuart_uart_pm,
22322249
.type = lpuart_type,
22332250
.request_port = lpuart_request_port,
22342251
.release_port = lpuart_release_port,
@@ -2253,6 +2270,7 @@ static const struct uart_ops lpuart32_pops = {
22532270
.startup = lpuart32_startup,
22542271
.shutdown = lpuart32_shutdown,
22552272
.set_termios = lpuart32_set_termios,
2273+
.pm = lpuart_uart_pm,
22562274
.type = lpuart_type,
22572275
.request_port = lpuart_request_port,
22582276
.release_port = lpuart_release_port,
@@ -2733,6 +2751,11 @@ static int lpuart_probe(struct platform_device *pdev)
27332751
handler = lpuart_int;
27342752
}
27352753

2754+
pm_runtime_use_autosuspend(&pdev->dev);
2755+
pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
2756+
pm_runtime_set_active(&pdev->dev);
2757+
pm_runtime_enable(&pdev->dev);
2758+
27362759
ret = lpuart_global_reset(sport);
27372760
if (ret)
27382761
goto failed_reset;
@@ -2757,6 +2780,9 @@ static int lpuart_probe(struct platform_device *pdev)
27572780
failed_attach_port:
27582781
failed_get_rs485:
27592782
failed_reset:
2783+
pm_runtime_disable(&pdev->dev);
2784+
pm_runtime_set_suspended(&pdev->dev);
2785+
pm_runtime_dont_use_autosuspend(&pdev->dev);
27602786
lpuart_disable_clks(sport);
27612787
return ret;
27622788
}
@@ -2775,9 +2801,30 @@ static int lpuart_remove(struct platform_device *pdev)
27752801
if (sport->dma_rx_chan)
27762802
dma_release_channel(sport->dma_rx_chan);
27772803

2804+
pm_runtime_disable(&pdev->dev);
2805+
pm_runtime_set_suspended(&pdev->dev);
2806+
pm_runtime_dont_use_autosuspend(&pdev->dev);
27782807
return 0;
27792808
}
27802809

2810+
static int __maybe_unused lpuart_runtime_suspend(struct device *dev)
2811+
{
2812+
struct platform_device *pdev = to_platform_device(dev);
2813+
struct lpuart_port *sport = platform_get_drvdata(pdev);
2814+
2815+
lpuart_disable_clks(sport);
2816+
2817+
return 0;
2818+
};
2819+
2820+
static int __maybe_unused lpuart_runtime_resume(struct device *dev)
2821+
{
2822+
struct platform_device *pdev = to_platform_device(dev);
2823+
struct lpuart_port *sport = platform_get_drvdata(pdev);
2824+
2825+
return lpuart_enable_clks(sport);
2826+
};
2827+
27812828
static void serial_lpuart_enable_wakeup(struct lpuart_port *sport, bool on)
27822829
{
27832830
unsigned int val, baud;
@@ -2923,6 +2970,10 @@ static int __maybe_unused lpuart_suspend(struct device *dev)
29232970
sport->dma_tx_in_progress = false;
29242971
dmaengine_terminate_all(sport->dma_tx_chan);
29252972
}
2973+
} else if (pm_runtime_active(sport->port.dev)) {
2974+
lpuart_disable_clks(sport);
2975+
pm_runtime_disable(sport->port.dev);
2976+
pm_runtime_set_suspended(sport->port.dev);
29262977
}
29272978

29282979
return 0;
@@ -2957,12 +3008,19 @@ static void lpuart_console_fixup(struct lpuart_port *sport)
29573008
static int __maybe_unused lpuart_resume(struct device *dev)
29583009
{
29593010
struct lpuart_port *sport = dev_get_drvdata(dev);
3011+
int ret;
29603012

29613013
if (lpuart_uport_is_active(sport)) {
29623014
if (lpuart_is_32(sport))
29633015
lpuart32_hw_setup(sport);
29643016
else
29653017
lpuart_hw_setup(sport);
3018+
} else if (pm_runtime_active(sport->port.dev)) {
3019+
ret = lpuart_enable_clks(sport);
3020+
if (ret)
3021+
return ret;
3022+
pm_runtime_set_active(sport->port.dev);
3023+
pm_runtime_enable(sport->port.dev);
29663024
}
29673025

29683026
lpuart_console_fixup(sport);
@@ -2972,6 +3030,8 @@ static int __maybe_unused lpuart_resume(struct device *dev)
29723030
}
29733031

29743032
static const struct dev_pm_ops lpuart_pm_ops = {
3033+
SET_RUNTIME_PM_OPS(lpuart_runtime_suspend,
3034+
lpuart_runtime_resume, NULL)
29753035
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(lpuart_suspend_noirq,
29763036
lpuart_resume_noirq)
29773037
SET_SYSTEM_SLEEP_PM_OPS(lpuart_suspend, lpuart_resume)

0 commit comments

Comments
 (0)