diff options
author | Pradeep Kumar <pgoudagunta@nvidia.com> | 2012-01-23 15:59:04 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-02-03 05:53:09 -0800 |
commit | 944a82b32d44bae0acb56abf5fec33a1c696c362 (patch) | |
tree | d56ba3dab83defc585e5ee310239f276b767a3a1 /drivers/tty | |
parent | 1457e7d6289e88d61a8dd6265a5b1b56e01169d6 (diff) |
tty: serial: tegra: Add runtime PM support
Add runtime PM support for tegra uart high speed driver.
Bug 887359
Reviewed-on: http://git-master/r/76805
Change-Id: I3439435eb40d36d66182a19011791399b6e65655
Signed-off-by: Pradeep Kumar <pgoudagunta@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/78713
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/tegra_hsuart.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/drivers/tty/serial/tegra_hsuart.c b/drivers/tty/serial/tegra_hsuart.c index 04d007a03eb7..0d5d855f97a0 100644 --- a/drivers/tty/serial/tegra_hsuart.c +++ b/drivers/tty/serial/tegra_hsuart.c @@ -42,6 +42,7 @@ #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/tegra_uart.h> +#include <linux/pm_runtime.h> #include <mach/dma.h> #include <mach/clk.h> @@ -635,10 +636,12 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) unsigned char lsr; unsigned char msr; unsigned char mcr; + struct uart_port *u; /* Disable interrupts */ uart_writeb(t, 0, UART_IER); + u = &t->uport; lsr = uart_readb(t, UART_LSR); if ((lsr & UART_LSR_TEMT) != UART_LSR_TEMT) { msr = uart_readb(t, UART_MSR); @@ -676,7 +679,7 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) spin_unlock_irqrestore(&t->uport.lock, flags); - clk_disable(t->clk); + pm_runtime_put_sync(u->dev); } static void tegra_uart_free_rx_dma_buffer(struct tegra_uart_port *t) @@ -701,6 +704,7 @@ static void tegra_uart_free_rx_dma(struct tegra_uart_port *t) static int tegra_uart_hw_init(struct tegra_uart_port *t) { unsigned char ier; + struct uart_port *u; dev_vdbg(t->uport.dev, "+tegra_uart_hw_init\n"); @@ -709,8 +713,9 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t) t->lcr_shadow = 0; t->ier_shadow = 0; t->baud = 0; + u = &t->uport; - clk_enable(t->clk); + pm_runtime_get_sync(u->dev); /* Reset the UART controller to clear all previous status.*/ tegra_periph_reset_assert(t->clk); @@ -1394,13 +1399,39 @@ static int __devexit tegra_uart_remove(struct platform_device *pdev); static int tegra_uart_suspend(struct platform_device *pdev, pm_message_t state); static int tegra_uart_resume(struct platform_device *pdev); +#if defined(CONFIG_PM_RUNTIME) +static int tegra_uart_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_uart_port *t = platform_get_drvdata(pdev); + clk_disable(t->clk); + return 0; +} + +static int tegra_uart_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_uart_port *t = platform_get_drvdata(pdev); + clk_enable(t->clk); + return 0; +} + +static const struct dev_pm_ops tegra_uart_pm_ops = { + .runtime_suspend = tegra_uart_runtime_suspend, + .runtime_resume = tegra_uart_runtime_resume, +}; +#endif + static struct platform_driver tegra_uart_platform_driver = { .remove = tegra_uart_remove, .probe = tegra_uart_probe, .suspend = tegra_uart_suspend, .resume = tegra_uart_resume, .driver = { - .name = "tegra_uart" + .name = "tegra_uart", +#if defined(CONFIG_PM_RUNTIME) + .pm = &tegra_uart_pm_ops +#endif } }; @@ -1427,7 +1458,7 @@ static int tegra_uart_suspend(struct platform_device *pdev, pm_message_t state) /* enable clock before calling suspend so that controller register can be accessible */ if (t->uart_state == TEGRA_UART_CLOCK_OFF) { - clk_enable(t->clk); + pm_runtime_get_sync(u->dev); t->uart_state = TEGRA_UART_OPENED; } @@ -1465,6 +1496,7 @@ static int __devexit tegra_uart_remove(struct platform_device *pdev) pr_err("Invalid Uart instance (%d)\n", pdev->id); u = &t->uport; + pm_runtime_disable(u->dev); uart_remove_one_port(&tegra_uart_driver, u); tegra_uart_free_rx_dma_buffer(t); @@ -1551,8 +1583,8 @@ static int tegra_uart_probe(struct platform_device *pdev) goto rx_dma_buff_fail; } } + pm_runtime_enable(u->dev); return ret; - rx_dma_buff_fail: uart_remove_one_port(&tegra_uart_driver, u); fail: @@ -1584,7 +1616,7 @@ void tegra_uart_request_clock_off(struct uart_port *uport) spin_unlock_irqrestore(&uport->lock, flags); if (is_clk_disable) - clk_disable(t->clk); + pm_runtime_put_sync(uport->dev); return; } @@ -1608,7 +1640,7 @@ void tegra_uart_request_clock_on(struct uart_port *uport) spin_unlock_irqrestore(&uport->lock, flags); if (is_clk_enable) - clk_enable(t->clk); + pm_runtime_get_sync(uport->dev); return; } |