summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorAshwini Ghuge <aghuge@nvidia.com>2012-01-12 10:50:44 +0530
committerVarun Colbert <vcolbert@nvidia.com>2012-01-13 14:08:30 -0800
commitfcbd75c6b179b717b074d0cb7490e42ae728fb2d (patch)
treef537864c297070f614b94ca702d350cc37b3f374 /drivers/spi
parentd522b6dab159e4d22c3fcd48d5038fc6aed2ce20 (diff)
drivers: spi: tegra: Add runtime PM support
Bug 886806 Original commit: http://git-master/r/59905 Change-Id: Ia8d64f3810d6157c6029180cd9a3cf98c2d3cb4c Signed-off-by: Ashwini Ghuge <aghuge@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/74896 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-tegra.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index 38cb8d11562d..c6ec3d0e384b 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/kthread.h>
+#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/spi-tegra.h>
@@ -695,7 +696,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
if (is_first_of_msg) {
if (!tspi->is_clkon_always) {
if (!tspi->clk_state) {
- clk_enable(tspi->clk);
+ pm_runtime_get_sync(&tspi->pdev->dev);
tspi->clk_state = 1;
}
}
@@ -820,7 +821,7 @@ static int spi_tegra_setup(struct spi_device *spi)
if (!tspi->is_clkon_always && !tspi->clk_state) {
spin_unlock_irqrestore(&tspi->lock, flags);
- clk_enable(tspi->clk);
+ pm_runtime_get_sync(&tspi->pdev->dev);
spin_lock_irqsave(&tspi->lock, flags);
tspi->clk_state = 1;
}
@@ -828,7 +829,7 @@ static int spi_tegra_setup(struct spi_device *spi)
if (!tspi->is_clkon_always && tspi->clk_state) {
tspi->clk_state = 0;
spin_unlock_irqrestore(&tspi->lock, flags);
- clk_disable(tspi->clk);
+ pm_runtime_put_sync(&tspi->pdev->dev);
} else
spin_unlock_irqrestore(&tspi->lock, flags);
return 0;
@@ -979,7 +980,7 @@ static void spi_tegra_curr_transfer_complete(struct spi_tegra_data *tspi,
spin_unlock_irqrestore(&tspi->lock,
*irq_flags);
udelay(10);
- clk_disable(tspi->clk);
+ pm_runtime_put_sync(&tspi->pdev->dev);
spin_lock_irqsave(&tspi->lock,
*irq_flags);
tspi->clk_state = 0;
@@ -1344,7 +1345,8 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
tspi->def_command2_reg = SLINK_CS_ACTIVE_BETWEEN;
skip_dma_alloc:
- clk_enable(tspi->clk);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
tspi->clk_state = 1;
master->dev.of_node = pdev->dev.of_node;
ret = spi_register_master(master);
@@ -1391,7 +1393,7 @@ fail_rx_buf_alloc:
if (tspi->rx_dma)
tegra_dma_free_channel(tspi->rx_dma);
fail_rx_dma_alloc:
- clk_put(tspi->clk);
+ pm_runtime_disable(&pdev->dev);
fail_clk_get:
free_irq(tspi->irq, tspi);
fail_irq_req:
@@ -1425,10 +1427,11 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
tegra_dma_free_channel(tspi->rx_dma);
if (tspi->is_clkon_always) {
- clk_disable(tspi->clk);
+ pm_runtime_put_sync(&pdev->dev);
tspi->clk_state = 0;
}
+ pm_runtime_disable(&pdev->dev);
clk_put(tspi->clk);
iounmap(tspi->base);
@@ -1488,7 +1491,7 @@ static int spi_tegra_suspend(struct platform_device *pdev, pm_message_t state)
spin_unlock_irqrestore(&tspi->lock, flags);
if (tspi->is_clkon_always) {
- clk_disable(tspi->clk);
+ pm_runtime_put_sync(&pdev->dev);
tspi->clk_state = 0;
}
return 0;
@@ -1507,11 +1510,11 @@ static int spi_tegra_resume(struct platform_device *pdev)
master = dev_get_drvdata(&pdev->dev);
tspi = spi_master_get_devdata(master);
- clk_enable(tspi->clk);
+ pm_runtime_get_sync(&pdev->dev);
tspi->clk_state = 1;
spi_tegra_writel(tspi, tspi->command_reg, SLINK_COMMAND);
if (!tspi->is_clkon_always) {
- clk_disable(tspi->clk);
+ pm_runtime_put_sync(&pdev->dev);
tspi->clk_state = 0;
}
spin_lock_irqsave(&tspi->lock, flags);
@@ -1535,6 +1538,37 @@ static int spi_tegra_resume(struct platform_device *pdev)
}
#endif
+#if defined(CONFIG_PM_RUNTIME)
+
+static int tegra_spi_runtime_idle(struct device *dev)
+{
+ struct spi_master *master;
+ struct spi_tegra_data *tspi;
+ master = dev_get_drvdata(dev);
+ tspi = spi_master_get_devdata(master);
+
+ clk_disable(tspi->clk);
+ return 0;
+}
+
+static int tegra_spi_runtime_resume(struct device *dev)
+{
+ struct spi_master *master;
+ struct spi_tegra_data *tspi;
+ master = dev_get_drvdata(dev);
+ tspi = spi_master_get_devdata(master);
+
+ clk_enable(tspi->clk);
+ return 0;
+}
+
+static const struct dev_pm_ops tegra_spi_dev_pm_ops = {
+ .runtime_idle = tegra_spi_runtime_idle,
+ .runtime_resume = tegra_spi_runtime_resume,
+};
+
+#endif
+
MODULE_ALIAS("platform:spi_tegra");
#ifdef CONFIG_OF
@@ -1551,6 +1585,9 @@ static struct platform_driver spi_tegra_driver = {
.driver = {
.name = "spi_tegra",
.owner = THIS_MODULE,
+#if defined(CONFIG_PM_RUNTIME)
+ .pm = &tegra_spi_dev_pm_ops,
+#endif
.of_match_table = spi_tegra_of_match_table,
},
.remove = __devexit_p(spi_tegra_remove),