summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorPradeep Kumar <pgoudagunta@nvidia.com>2012-01-23 15:59:04 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-02-03 05:53:09 -0800
commit944a82b32d44bae0acb56abf5fec33a1c696c362 (patch)
treed56ba3dab83defc585e5ee310239f276b767a3a1 /drivers/tty
parent1457e7d6289e88d61a8dd6265a5b1b56e01169d6 (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.c46
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;
}