summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMustafa Yigit Bilgen <mbilgen@nvidia.com>2017-03-31 19:10:37 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-06-22 21:34:32 -0400
commitd9e7472f4c8bec5f2b9d5092b11b098af7b2c206 (patch)
tree31db259284fa615818195f37c86f8ab0b5ec03f7
parentf3c0ba942b56212234fb22a4769d6d7eece25ba2 (diff)
serial: combined uart: add pm ops
Add support for suspend/resume. This is necessary to ensure that RX interrupts are received after resuming from suspend. Bug 1527617 Bug 1817040 Change-Id: Ic54af7a916fb99fc0017524a11cad9acf0424008 Signed-off-by: Mustafa Yigit Bilgen <mbilgen@nvidia.com> Reviewed-on: http://git-master/r/1503302 Reviewed-by: Liang Cheng (SW) <licheng@nvidia.com> Reviewed-by: Akhilesh Khumbum <akhumbum@nvidia.com> Reviewed-by: Robert Collins <rcollins@nvidia.com> GVS: Gerrit_Virtual_Submit
-rw-r--r--drivers/tty/serial/tegra-combined-uart.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/tty/serial/tegra-combined-uart.c b/drivers/tty/serial/tegra-combined-uart.c
index 76435e150..3f19319ed 100644
--- a/drivers/tty/serial/tegra-combined-uart.c
+++ b/drivers/tty/serial/tegra-combined-uart.c
@@ -59,16 +59,45 @@ static int uart_null_func(struct uart_port *port)
59 return 0; 59 return 0;
60} 60}
61 61
62static int uart_shutdown(struct uart_port *port) 62static void tegra_combined_uart_disable_sm_irq(void)
63{ 63{
64 u32 reg_val; 64 u32 reg_val;
65 /* 65 /*
66 * disable interrupt
67 * WARNING: HSP_INT_IE_0 is not protected for RMW. 66 * WARNING: HSP_INT_IE_0 is not protected for RMW.
68 */ 67 */
69 reg_val = readl(top0_cmn_base + HSP_INT_IE_0); 68 reg_val = readl(top0_cmn_base + HSP_INT_IE_0);
70 reg_val &= ~(1 << MBOX0_FULL_BIT); 69 reg_val &= ~(1 << MBOX0_FULL_BIT);
71 writel(reg_val, top0_cmn_base + HSP_INT_IE_0); 70 writel(reg_val, top0_cmn_base + HSP_INT_IE_0);
71}
72
73static void tegra_combined_uart_enable_sm_irq(void)
74{
75 u32 reg_val;
76 /*
77 * WARNING: HSP_INT_IE_0 is not protected for RMW.
78 */
79 reg_val = readl(top0_cmn_base + HSP_INT_IE_0);
80 reg_val |= (1 << MBOX0_FULL_BIT);
81 writel(reg_val, top0_cmn_base + HSP_INT_IE_0);
82}
83
84static int tegra_combined_uart_suspend(struct device *dev)
85{
86 tegra_combined_uart_disable_sm_irq();
87
88 return 0;
89}
90
91static int tegra_combined_uart_resume(struct device *dev)
92{
93 tegra_combined_uart_enable_sm_irq();
94
95 return 0;
96}
97
98static int uart_shutdown(struct uart_port *port)
99{
100 tegra_combined_uart_disable_sm_irq();
72 /* free IRQ */ 101 /* free IRQ */
73 free_irq(tegra_combined_uart_port.irq, port); 102 free_irq(tegra_combined_uart_port.irq, port);
74 103
@@ -222,13 +251,13 @@ static irqreturn_t tegra_combined_uart_rx(int irq, void *dev_id)
222 251
223 tegra_combined_uart_handle_rx_msg(reg_val); 252 tegra_combined_uart_handle_rx_msg(reg_val);
224 spin_unlock_irqrestore(&mbox_lock, flags); 253 spin_unlock_irqrestore(&mbox_lock, flags);
254
225 return IRQ_HANDLED; 255 return IRQ_HANDLED;
226} 256}
227 257
228static int tegra_combined_uart_startup(struct uart_port *port) 258static int tegra_combined_uart_startup(struct uart_port *port)
229{ 259{
230 int ret; 260 int ret;
231 u32 reg_val;
232 /* allocate IRQ */ 261 /* allocate IRQ */
233 ret = request_irq(tegra_combined_uart_port.irq, tegra_combined_uart_rx, 262 ret = request_irq(tegra_combined_uart_port.irq, tegra_combined_uart_rx,
234 0, "combined_uart rx", port); 263 0, "combined_uart rx", port);
@@ -236,13 +265,9 @@ static int tegra_combined_uart_startup(struct uart_port *port)
236 pr_err("%s: request_irq error\n", __func__); 265 pr_err("%s: request_irq error\n", __func__);
237 return ret; 266 return ret;
238 } 267 }
239 /* 268
240 * enable interrupt 269 tegra_combined_uart_enable_sm_irq();
241 * WARNING: HSP_INT_IE_0 is not protected for RMW. 270
242 */
243 reg_val = readl(top0_cmn_base + HSP_INT_IE_0);
244 reg_val |= (1 << MBOX0_FULL_BIT);
245 writel(reg_val, top0_cmn_base + HSP_INT_IE_0);
246 return ret; 271 return ret;
247} 272}
248 273
@@ -306,6 +331,7 @@ err_mapping:
306 iounmap(top0_mbox01_base); 331 iounmap(top0_mbox01_base);
307 if (top0_cmn_base != NULL && !IS_ERR(top0_cmn_base)) 332 if (top0_cmn_base != NULL && !IS_ERR(top0_cmn_base))
308 iounmap(top0_cmn_base); 333 iounmap(top0_cmn_base);
334
309 return ret; 335 return ret;
310} 336}
311 337
@@ -317,6 +343,7 @@ static int tegra_combined_uart_remove(struct platform_device *pdev)
317 iounmap(spe_mbox_reg); 343 iounmap(spe_mbox_reg);
318 iounmap(top0_mbox01_base); 344 iounmap(top0_mbox01_base);
319 iounmap(top0_cmn_base); 345 iounmap(top0_cmn_base);
346
320 return 0; 347 return 0;
321} 348}
322 349
@@ -398,12 +425,22 @@ static struct uart_driver tegra_combined_uart_driver = {
398 .nr = 1, 425 .nr = 1,
399}; 426};
400 427
428#ifdef CONFIG_PM
429static const struct dev_pm_ops tegra_combined_uart_pm_ops = {
430 .suspend = tegra_combined_uart_suspend,
431 .resume = tegra_combined_uart_resume,
432};
433#endif
434
401static struct platform_driver tegra_combined_uart_platform_driver = { 435static struct platform_driver tegra_combined_uart_platform_driver = {
402 .probe = tegra_combined_uart_probe, 436 .probe = tegra_combined_uart_probe,
403 .remove = tegra_combined_uart_remove, 437 .remove = tegra_combined_uart_remove,
404 .driver = { 438 .driver = {
405 .name = "tegra-combined-uart", 439 .name = "tegra-combined-uart",
406 .of_match_table = of_match_ptr(tegra_combined_uart_of_match), 440 .of_match_table = of_match_ptr(tegra_combined_uart_of_match),
441#ifdef CONFIG_PM
442 .pm = &tegra_combined_uart_pm_ops,
443#endif
407 }, 444 },
408}; 445};
409 446