diff options
| author | Pramod Gurav <gpramod@codeaurora.org> | 2016-12-14 19:15:44 +0530 |
|---|---|---|
| committer | Runmin Wang <runminw@codeaurora.org> | 2016-12-16 17:21:49 -0800 |
| commit | 4ea456a12038f905c99e1878fd0d92c98b99949e (patch) | |
| tree | 0f66c537b60e5974f86d2aa4f40bd665bbad6255 | |
| parent | 64fcef1f22100bb38d270d7c49996a123a717f53 (diff) | |
tty: serial: msm: Add suspend resume support
Add suspend/resume callback support to serial msm driver.
Change-Id: I661fca45d2d762a08e331f53d8b3cb7b99117448
Signed-off-by: Pramod Gurav <gpramod@codeaurora.org>
Signed-off-by: Runmin Wang <runminw@codeaurora.org>
| -rw-r--r-- | drivers/tty/serial/msm_serial.c | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index da64f88729b8..8f68acd1d95d 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1157,15 +1157,6 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, return baud; } -static void msm_init_clock(struct uart_port *port) -{ - struct msm_port *msm_port = UART_TO_MSM(port); - - clk_prepare_enable(msm_port->clk); - clk_prepare_enable(msm_port->pclk); - msm_serial_set_mnd_regs(port); -} - static int msm_startup(struct uart_port *port) { struct msm_port *msm_port = UART_TO_MSM(port); @@ -1180,7 +1171,23 @@ static int msm_startup(struct uart_port *port) if (unlikely(ret)) return ret; - msm_init_clock(port); + /* + * UART clk must be kept enabled to + * avoid losing received character + */ + ret = clk_prepare_enable(msm_port->clk); + if (ret) { + goto err_clk; + return ret; + } + + ret = clk_prepare_enable(msm_port->pclk); + if (ret) { + goto err_pclk; + return ret; + } + + msm_serial_set_mnd_regs(port); if (likely(port->fifosize > 12)) rfr_level = port->fifosize - 12; @@ -1207,6 +1214,13 @@ static int msm_startup(struct uart_port *port) } return 0; + +err_pclk: + clk_disable_unprepare(msm_port->clk); +err_clk: + free_irq(port->irq, port); + + return ret; } static void msm_shutdown(struct uart_port *port) @@ -1219,6 +1233,7 @@ static void msm_shutdown(struct uart_port *port) if (msm_port->is_uartdm) msm_release_dma(msm_port); + clk_disable_unprepare(msm_port->pclk); clk_disable_unprepare(msm_port->clk); free_irq(port->irq, port); @@ -1385,8 +1400,16 @@ static void msm_power(struct uart_port *port, unsigned int state, switch (state) { case 0: - clk_prepare_enable(msm_port->clk); - clk_prepare_enable(msm_port->pclk); + /* + * UART clk must be kept enabled to + * avoid losing received character + */ + if (clk_prepare_enable(msm_port->clk)) + return; + if (clk_prepare_enable(msm_port->pclk)) { + clk_disable_unprepare(msm_port->clk); + return; + } break; case 3: clk_disable_unprepare(msm_port->clk); @@ -1651,7 +1674,7 @@ static int __init msm_console_setup(struct console *co, char *options) if (unlikely(!port->membase)) return -ENXIO; - msm_init_clock(port); + msm_serial_set_mnd_regs(port); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1812,12 +1835,37 @@ static const struct of_device_id msm_match_table[] = { {} }; +#ifdef CONFIG_PM_SLEEP +static int msm_serial_suspend(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + + uart_suspend_port(&msm_uart_driver, port); + + return 0; +} + +static int msm_serial_resume(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + + uart_resume_port(&msm_uart_driver, port); + + return 0; +} +#endif + +static const struct dev_pm_ops msm_serial_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(msm_serial_suspend, msm_serial_resume) +}; + static struct platform_driver msm_platform_driver = { .remove = msm_serial_remove, .probe = msm_serial_probe, .driver = { .name = "msm_serial", .of_match_table = msm_match_table, + .pm = &msm_serial_pm_ops, }, }; |
