diff options
author | Radu Pirea <radu_nicolae.pirea@upb.ro> | 2018-11-21 13:27:30 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-11-27 14:15:11 +0000 |
commit | 96ed3ecde2c0911ffa11838050a058c2a40742f0 (patch) | |
tree | 40cfb954df980a0257a7f156f251f4cdbbbd2ad3 /drivers/spi/spi-at91-usart.c | |
parent | 1d2319efb6a970d5f5740a60828244e6c309df2b (diff) | |
download | linux-96ed3ecde2c0911ffa11838050a058c2a40742f0.tar.bz2 |
spi: at91-usart: add power management support
This patch implements power management callback function for USART as
SPI driver.
Signed-off-by: Radu Pirea <radu_nicolae.pirea@upb.ro>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-at91-usart.c')
-rw-r--r-- | drivers/spi/spi-at91-usart.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a924657642fa..0b07c746453d 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -399,6 +400,59 @@ at91_usart_spi_probe_fail: return ret; } +__maybe_unused static int at91_usart_spi_runtime_suspend(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + clk_disable_unprepare(aus->clk); + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +__maybe_unused static int at91_usart_spi_runtime_resume(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + + pinctrl_pm_select_default_state(dev); + + return clk_prepare_enable(aus->clk); +} + +__maybe_unused static int at91_usart_spi_suspend(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + int ret; + + ret = spi_controller_suspend(ctrl); + if (ret) + return ret; + + if (!pm_runtime_suspended(dev)) + at91_usart_spi_runtime_suspend(dev); + + return 0; +} + +__maybe_unused static int at91_usart_spi_resume(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + int ret; + + if (!pm_runtime_suspended(dev)) { + ret = at91_usart_spi_runtime_resume(dev); + if (ret) + return ret; + } + + at91_usart_spi_init(aus); + + return spi_controller_resume(ctrl); +} + static int at91_usart_spi_remove(struct platform_device *pdev) { struct spi_controller *ctlr = platform_get_drvdata(pdev); @@ -409,6 +463,12 @@ static int at91_usart_spi_remove(struct platform_device *pdev) return 0; } +static const struct dev_pm_ops at91_usart_spi_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(at91_usart_spi_suspend, at91_usart_spi_resume) + SET_RUNTIME_PM_OPS(at91_usart_spi_runtime_suspend, + at91_usart_spi_runtime_resume, NULL) +}; + static const struct of_device_id at91_usart_spi_dt_ids[] = { { .compatible = "microchip,at91sam9g45-usart-spi"}, { /* sentinel */} @@ -419,6 +479,7 @@ MODULE_DEVICE_TABLE(of, at91_usart_spi_dt_ids); static struct platform_driver at91_usart_spi_driver = { .driver = { .name = "at91_usart_spi", + .pm = &at91_usart_spi_pm_ops, }, .probe = at91_usart_spi_probe, .remove = at91_usart_spi_remove, |