ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 819-uart-0009-MLK-17133-02-tty-serial-lpuart-add-runtime-pm-suppor.patch
1 From ff3d8063eed907bed728a14e1519dc659036315a Mon Sep 17 00:00:00 2001
2 From: Fugang Duan <fugang.duan@nxp.com>
3 Date: Wed, 11 Sep 2019 16:36:48 +0800
4 Subject: [PATCH] MLK-17133-02 tty: serial: lpuart: add runtime pm support
5
6 Add runtime pm support to manage lpuart clock and its power domain
7 to save power in system idle and system suspend stages.
8
9 Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
10 Reviewed-by: Robin Gong <yibin.gong@nxp.com>
11 ---
12  drivers/tty/serial/fsl_lpuart.c | 80 ++++++++++++++++++++++++++++++++++++-----
13  1 file changed, 72 insertions(+), 8 deletions(-)
14
15 --- a/drivers/tty/serial/fsl_lpuart.c
16 +++ b/drivers/tty/serial/fsl_lpuart.c
17 @@ -245,6 +245,7 @@
18  
19  /* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
20  #define DMA_RX_TIMEOUT         (10)
21 +#define UART_AUTOSUSPEND_TIMEOUT       3000
22  
23  #define DRIVER_NAME    "fsl-lpuart"
24  #define DEV_NAME       "ttyLP"
25 @@ -846,6 +847,20 @@ static void lpuart32_start_tx(struct uar
26         }
27  }
28  
29 +static void
30 +lpuart_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
31 +{
32 +       switch (state) {
33 +       case UART_PM_STATE_OFF:
34 +               pm_runtime_mark_last_busy(port->dev);
35 +               pm_runtime_put_autosuspend(port->dev);
36 +               break;
37 +       default:
38 +               pm_runtime_get_sync(port->dev);
39 +               break;
40 +       }
41 +}
42 +
43  /* return TIOCSER_TEMT when transmitter is not busy */
44  static unsigned int lpuart_tx_empty(struct uart_port *port)
45  {
46 @@ -2259,6 +2274,7 @@ static const struct uart_ops lpuart_pops
47         .break_ctl      = lpuart_break_ctl,
48         .startup        = lpuart_startup,
49         .shutdown       = lpuart_shutdown,
50 +       .pm             = lpuart_uart_pm,
51         .set_termios    = lpuart_set_termios,
52         .type           = lpuart_type,
53         .request_port   = lpuart_request_port,
54 @@ -2283,6 +2299,7 @@ static const struct uart_ops lpuart32_po
55         .break_ctl      = lpuart32_break_ctl,
56         .startup        = lpuart32_startup,
57         .shutdown       = lpuart32_shutdown,
58 +       .pm             = lpuart_uart_pm,
59         .set_termios    = lpuart32_set_termios,
60         .type           = lpuart_type,
61         .request_port   = lpuart_request_port,
62 @@ -2742,6 +2759,11 @@ static int lpuart_probe(struct platform_
63         if (ret)
64                 goto failed_irq_request;
65  
66 +       pm_runtime_use_autosuspend(&pdev->dev);
67 +       pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
68 +       pm_runtime_set_active(&pdev->dev);
69 +       pm_runtime_enable(&pdev->dev);
70 +
71         ret = uart_add_one_port(&lpuart_reg, &sport->port);
72         if (ret)
73                 goto failed_attach_port;
74 @@ -2776,6 +2798,9 @@ static int lpuart_probe(struct platform_
75  failed_reset:
76         uart_remove_one_port(&lpuart_reg, &sport->port);
77  failed_attach_port:
78 +       pm_runtime_disable(&pdev->dev);
79 +       pm_runtime_set_suspended(&pdev->dev);
80 +       pm_runtime_dont_use_autosuspend(&pdev->dev);
81  failed_irq_request:
82         lpuart_disable_clks(sport);
83  failed_clock_enable:
84 @@ -2802,15 +2827,41 @@ static int lpuart_remove(struct platform
85         if (sport->dma_rx_chan)
86                 dma_release_channel(sport->dma_rx_chan);
87  
88 +       pm_runtime_disable(&pdev->dev);
89 +       pm_runtime_set_suspended(&pdev->dev);
90 +       pm_runtime_dont_use_autosuspend(&pdev->dev);
91         return 0;
92  }
93  
94  #ifdef CONFIG_PM_SLEEP
95 +static int lpuart_runtime_suspend(struct device *dev)
96 +{
97 +       struct platform_device *pdev = to_platform_device(dev);
98 +       struct lpuart_port *sport = platform_get_drvdata(pdev);
99 +
100 +       lpuart_disable_clks(sport);
101 +
102 +       return 0;
103 +};
104 +
105 +static int lpuart_runtime_resume(struct device *dev)
106 +{
107 +       struct platform_device *pdev = to_platform_device(dev);
108 +       struct lpuart_port *sport = platform_get_drvdata(pdev);
109 +
110 +       return lpuart_enable_clks(sport);
111 +};
112 +
113  static int lpuart_suspend(struct device *dev)
114  {
115         struct lpuart_port *sport = dev_get_drvdata(dev);
116         unsigned long temp;
117         bool irq_wake;
118 +       int ret;
119 +
120 +       ret = clk_prepare_enable(sport->ipg_clk);
121 +       if (ret)
122 +               return ret;
123  
124         if (lpuart_is_32(sport)) {
125                 /* disable Rx/Tx and interrupts */
126 @@ -2824,10 +2875,14 @@ static int lpuart_suspend(struct device
127                 writeb(temp, sport->port.membase + UARTCR2);
128         }
129  
130 +       clk_disable_unprepare(sport->ipg_clk);
131 +
132         uart_suspend_port(&lpuart_reg, &sport->port);
133  
134         /* uart_suspend_port() might set wakeup flag */
135         irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
136 +       if (sport->port.suspended && !irq_wake)
137 +               return 0;
138  
139         if (sport->lpuart_dma_rx_use) {
140                 /*
141 @@ -2858,9 +2913,6 @@ static int lpuart_suspend(struct device
142                 dmaengine_terminate_all(sport->dma_tx_chan);
143         }
144  
145 -       if (sport->port.suspended && !irq_wake)
146 -               lpuart_disable_clks(sport);
147 -
148         return 0;
149  }
150  
151 @@ -2868,9 +2920,11 @@ static int lpuart_resume(struct device *
152  {
153         struct lpuart_port *sport = dev_get_drvdata(dev);
154         bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
155 +       int ret;
156  
157 -       if (sport->port.suspended && !irq_wake)
158 -               lpuart_enable_clks(sport);
159 +       ret = clk_prepare_enable(sport->ipg_clk);
160 +       if (ret)
161 +               return ret;
162  
163         if (lpuart_is_32(sport))
164                 lpuart32_setup_watermark_enable(sport);
165 @@ -2891,13 +2945,23 @@ static int lpuart_resume(struct device *
166         if (lpuart_is_32(sport))
167                 lpuart32_configure(sport);
168  
169 +       clk_disable_unprepare(sport->ipg_clk);
170 +
171         uart_resume_port(&lpuart_reg, &sport->port);
172  
173         return 0;
174  }
175 -#endif
176 +static const struct dev_pm_ops lpuart_pm_ops = {
177 +       SET_RUNTIME_PM_OPS(lpuart_runtime_suspend,
178 +                          lpuart_runtime_resume, NULL)
179 +       SET_SYSTEM_SLEEP_PM_OPS(lpuart_suspend, lpuart_resume)
180 +};
181 +#define SERIAL_LPUART_PM_OPS   (&lpuart_pm_ops)
182  
183 -static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);
184 +#else /* !CONFIG_PM_SLEEP */
185 +
186 +#define SERIAL_LPUART_PM_OPS   NULL
187 +#endif
188  
189  static struct platform_driver lpuart_driver = {
190         .probe          = lpuart_probe,
191 @@ -2905,7 +2969,7 @@ static struct platform_driver lpuart_dri
192         .driver         = {
193                 .name   = "fsl-lpuart",
194                 .of_match_table = lpuart_dt_ids,
195 -               .pm     = &lpuart_pm_ops,
196 +               .pm     = SERIAL_LPUART_PM_OPS,
197         },
198  };
199