mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
spi: spi-orion: add runtime PM support
Add trivial runtime PM support. This will only be of benefit on SoCs where the clock to the SPI interface can be shut down. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
parent
c85012addd
commit
5c6786945b
1 changed files with 50 additions and 9 deletions
|
@ -16,6 +16,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/sizes.h>
|
||||
|
@ -23,6 +24,9 @@
|
|||
|
||||
#define DRIVER_NAME "orion_spi"
|
||||
|
||||
/* Runtime PM autosuspend timeout: PM is fairly light on this driver */
|
||||
#define SPI_AUTOSUSPEND_TIMEOUT 200
|
||||
|
||||
#define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/
|
||||
#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
|
||||
|
||||
|
@ -277,7 +281,6 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
return xfer->len - count;
|
||||
}
|
||||
|
||||
|
||||
static int orion_spi_transfer_one_message(struct spi_master *master,
|
||||
struct spi_message *m)
|
||||
{
|
||||
|
@ -370,6 +373,7 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
master->transfer_one_message = orion_spi_transfer_one_message;
|
||||
master->num_chipselect = ORION_NUM_CHIPSELECTS;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
|
||||
master->auto_runtime_pm = true;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
|
||||
|
@ -397,16 +401,26 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
goto out_rel_clk;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (orion_spi_reset(spi) < 0)
|
||||
goto out_rel_clk;
|
||||
goto out_rel_pm;
|
||||
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
status = devm_spi_register_master(&pdev->dev, master);
|
||||
status = spi_register_master(master);
|
||||
if (status < 0)
|
||||
goto out_rel_clk;
|
||||
goto out_rel_pm;
|
||||
|
||||
return status;
|
||||
|
||||
out_rel_pm:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
out_rel_clk:
|
||||
clk_disable_unprepare(spi->clk);
|
||||
out:
|
||||
|
@ -417,19 +431,45 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
|
||||
static int orion_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct orion_spi *spi;
|
||||
|
||||
master = platform_get_drvdata(pdev);
|
||||
spi = spi_master_get_devdata(master);
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct orion_spi *spi = spi_master_get_devdata(master);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
clk_disable_unprepare(spi->clk);
|
||||
|
||||
spi_unregister_master(master);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int orion_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct orion_spi *spi = spi_master_get_devdata(master);
|
||||
|
||||
clk_disable_unprepare(spi->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int orion_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct orion_spi *spi = spi_master_get_devdata(master);
|
||||
|
||||
return clk_prepare_enable(spi->clk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops orion_spi_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend,
|
||||
orion_spi_runtime_resume,
|
||||
NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id orion_spi_of_match_table[] = {
|
||||
{ .compatible = "marvell,orion-spi", },
|
||||
{}
|
||||
|
@ -440,6 +480,7 @@ static struct platform_driver orion_spi_driver = {
|
|||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &orion_spi_pm_ops,
|
||||
.of_match_table = of_match_ptr(orion_spi_of_match_table),
|
||||
},
|
||||
.probe = orion_spi_probe,
|
||||
|
|
Loading…
Reference in a new issue