123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- From ff3d8063eed907bed728a14e1519dc659036315a Mon Sep 17 00:00:00 2001
- From: Fugang Duan <[email protected]>
- Date: Wed, 11 Sep 2019 16:36:48 +0800
- Subject: [PATCH] MLK-17133-02 tty: serial: lpuart: add runtime pm support
- Add runtime pm support to manage lpuart clock and its power domain
- to save power in system idle and system suspend stages.
- Signed-off-by: Fugang Duan <[email protected]>
- Reviewed-by: Robin Gong <[email protected]>
- ---
- drivers/tty/serial/fsl_lpuart.c | 80 ++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 72 insertions(+), 8 deletions(-)
- --- a/drivers/tty/serial/fsl_lpuart.c
- +++ b/drivers/tty/serial/fsl_lpuart.c
- @@ -245,6 +245,7 @@
-
- /* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
- #define DMA_RX_TIMEOUT (10)
- +#define UART_AUTOSUSPEND_TIMEOUT 3000
-
- #define DRIVER_NAME "fsl-lpuart"
- #define DEV_NAME "ttyLP"
- @@ -844,6 +845,20 @@ static void lpuart32_start_tx(struct uar
- }
- }
-
- +static void
- +lpuart_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
- +{
- + switch (state) {
- + case UART_PM_STATE_OFF:
- + pm_runtime_mark_last_busy(port->dev);
- + pm_runtime_put_autosuspend(port->dev);
- + break;
- + default:
- + pm_runtime_get_sync(port->dev);
- + break;
- + }
- +}
- +
- /* return TIOCSER_TEMT when transmitter is not busy */
- static unsigned int lpuart_tx_empty(struct uart_port *port)
- {
- @@ -2257,6 +2272,7 @@ static const struct uart_ops lpuart_pops
- .break_ctl = lpuart_break_ctl,
- .startup = lpuart_startup,
- .shutdown = lpuart_shutdown,
- + .pm = lpuart_uart_pm,
- .set_termios = lpuart_set_termios,
- .type = lpuart_type,
- .request_port = lpuart_request_port,
- @@ -2281,6 +2297,7 @@ static const struct uart_ops lpuart32_po
- .break_ctl = lpuart32_break_ctl,
- .startup = lpuart32_startup,
- .shutdown = lpuart32_shutdown,
- + .pm = lpuart_uart_pm,
- .set_termios = lpuart32_set_termios,
- .type = lpuart_type,
- .request_port = lpuart_request_port,
- @@ -2740,6 +2757,11 @@ static int lpuart_probe(struct platform_
- if (ret)
- goto failed_irq_request;
-
- + pm_runtime_use_autosuspend(&pdev->dev);
- + pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
- + pm_runtime_set_active(&pdev->dev);
- + pm_runtime_enable(&pdev->dev);
- +
- ret = uart_add_one_port(&lpuart_reg, &sport->port);
- if (ret)
- goto failed_attach_port;
- @@ -2774,6 +2796,9 @@ static int lpuart_probe(struct platform_
- failed_reset:
- uart_remove_one_port(&lpuart_reg, &sport->port);
- failed_attach_port:
- + pm_runtime_disable(&pdev->dev);
- + pm_runtime_set_suspended(&pdev->dev);
- + pm_runtime_dont_use_autosuspend(&pdev->dev);
- failed_irq_request:
- lpuart_disable_clks(sport);
- failed_clock_enable:
- @@ -2800,15 +2825,41 @@ static int lpuart_remove(struct platform
- if (sport->dma_rx_chan)
- dma_release_channel(sport->dma_rx_chan);
-
- + pm_runtime_disable(&pdev->dev);
- + pm_runtime_set_suspended(&pdev->dev);
- + pm_runtime_dont_use_autosuspend(&pdev->dev);
- return 0;
- }
-
- #ifdef CONFIG_PM_SLEEP
- +static int lpuart_runtime_suspend(struct device *dev)
- +{
- + struct platform_device *pdev = to_platform_device(dev);
- + struct lpuart_port *sport = platform_get_drvdata(pdev);
- +
- + lpuart_disable_clks(sport);
- +
- + return 0;
- +};
- +
- +static int lpuart_runtime_resume(struct device *dev)
- +{
- + struct platform_device *pdev = to_platform_device(dev);
- + struct lpuart_port *sport = platform_get_drvdata(pdev);
- +
- + return lpuart_enable_clks(sport);
- +};
- +
- static int lpuart_suspend(struct device *dev)
- {
- struct lpuart_port *sport = dev_get_drvdata(dev);
- unsigned long temp;
- bool irq_wake;
- + int ret;
- +
- + ret = clk_prepare_enable(sport->ipg_clk);
- + if (ret)
- + return ret;
-
- if (lpuart_is_32(sport)) {
- /* disable Rx/Tx and interrupts */
- @@ -2822,10 +2873,14 @@ static int lpuart_suspend(struct device
- writeb(temp, sport->port.membase + UARTCR2);
- }
-
- + clk_disable_unprepare(sport->ipg_clk);
- +
- uart_suspend_port(&lpuart_reg, &sport->port);
-
- /* uart_suspend_port() might set wakeup flag */
- irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
- + if (sport->port.suspended && !irq_wake)
- + return 0;
-
- if (sport->lpuart_dma_rx_use) {
- /*
- @@ -2856,9 +2911,6 @@ static int lpuart_suspend(struct device
- dmaengine_terminate_all(sport->dma_tx_chan);
- }
-
- - if (sport->port.suspended && !irq_wake)
- - lpuart_disable_clks(sport);
- -
- return 0;
- }
-
- @@ -2866,9 +2918,11 @@ static int lpuart_resume(struct device *
- {
- struct lpuart_port *sport = dev_get_drvdata(dev);
- bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
- + int ret;
-
- - if (sport->port.suspended && !irq_wake)
- - lpuart_enable_clks(sport);
- + ret = clk_prepare_enable(sport->ipg_clk);
- + if (ret)
- + return ret;
-
- if (lpuart_is_32(sport))
- lpuart32_setup_watermark_enable(sport);
- @@ -2889,13 +2943,23 @@ static int lpuart_resume(struct device *
- if (lpuart_is_32(sport))
- lpuart32_configure(sport);
-
- + clk_disable_unprepare(sport->ipg_clk);
- +
- uart_resume_port(&lpuart_reg, &sport->port);
-
- return 0;
- }
- -#endif
- +static const struct dev_pm_ops lpuart_pm_ops = {
- + SET_RUNTIME_PM_OPS(lpuart_runtime_suspend,
- + lpuart_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(lpuart_suspend, lpuart_resume)
- +};
- +#define SERIAL_LPUART_PM_OPS (&lpuart_pm_ops)
-
- -static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);
- +#else /* !CONFIG_PM_SLEEP */
- +
- +#define SERIAL_LPUART_PM_OPS NULL
- +#endif
-
- static struct platform_driver lpuart_driver = {
- .probe = lpuart_probe,
- @@ -2903,7 +2967,7 @@ static struct platform_driver lpuart_dri
- .driver = {
- .name = "fsl-lpuart",
- .of_match_table = lpuart_dt_ids,
- - .pm = &lpuart_pm_ops,
- + .pm = SERIAL_LPUART_PM_OPS,
- },
- };
-
|