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,  | 
