diff options
Diffstat (limited to 'drivers/spi/spi-at91-usart.c')
-rw-r--r-- | drivers/spi/spi-at91-usart.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a924657642fa..a694d702e574 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -12,7 +12,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of_gpio.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -399,6 +401,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 +464,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 +480,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, |