diff options
author | Ashwini Ghuge <aghuge@nvidia.com> | 2012-01-12 10:50:44 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-01-13 14:08:30 -0800 |
commit | fcbd75c6b179b717b074d0cb7490e42ae728fb2d (patch) | |
tree | f537864c297070f614b94ca702d350cc37b3f374 /drivers/spi | |
parent | d522b6dab159e4d22c3fcd48d5038fc6aed2ce20 (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.c | 57 |
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), |