diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-12-25 15:32:27 +0100 | 
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2010-12-25 15:32:27 +0100 | 
| commit | 3ae22e8c8ac39daf88ae32f047fb23825be7c646 (patch) | |
| tree | 20e7ed1005b39e65d99ac351776e74a9c925a6aa /drivers/spi/spi.c | |
| parent | 62bcb91573425975d6ad2389d7ab1d8feca88ab4 (diff) | |
spi / PM: Support dev_pm_ops
Allow SPI drivers to use runtime PM and other dev_pm_ops features by
implementing dev_pm_ops for the bus. The existing bus specific suspend
and resume functions will be called if a driver does not provide dev_pm_ops
allowing for transition to the new model.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/spi/spi.c')
| -rw-r--r-- | drivers/spi/spi.c | 92 | 
1 files changed, 84 insertions, 8 deletions
| diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b02d0cbce890..34bb17f03019 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -28,6 +28,7 @@  #include <linux/mod_devicetable.h>  #include <linux/spi/spi.h>  #include <linux/of_spi.h> +#include <linux/pm_runtime.h>  static void spidev_release(struct device *dev)  { @@ -100,9 +101,8 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)  	return 0;  } -#ifdef	CONFIG_PM - -static int spi_suspend(struct device *dev, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int spi_legacy_suspend(struct device *dev, pm_message_t message)  {  	int			value = 0;  	struct spi_driver	*drv = to_spi_driver(dev->driver); @@ -117,7 +117,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)  	return value;  } -static int spi_resume(struct device *dev) +static int spi_legacy_resume(struct device *dev)  {  	int			value = 0;  	struct spi_driver	*drv = to_spi_driver(dev->driver); @@ -132,18 +132,94 @@ static int spi_resume(struct device *dev)  	return value;  } +static int spi_pm_suspend(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_suspend(dev); +	else +		return spi_legacy_suspend(dev, PMSG_SUSPEND); +} + +static int spi_pm_resume(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_resume(dev); +	else +		return spi_legacy_resume(dev); +} + +static int spi_pm_freeze(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_freeze(dev); +	else +		return spi_legacy_suspend(dev, PMSG_FREEZE); +} + +static int spi_pm_thaw(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_thaw(dev); +	else +		return spi_legacy_resume(dev); +} + +static int spi_pm_poweroff(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_poweroff(dev); +	else +		return spi_legacy_suspend(dev, PMSG_HIBERNATE); +} + +static int spi_pm_restore(struct device *dev) +{ +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + +	if (pm) +		return pm_generic_restore(dev); +	else +		return spi_legacy_resume(dev); +}  #else -#define spi_suspend	NULL -#define spi_resume	NULL +#define spi_pm_suspend	NULL +#define spi_pm_resume	NULL +#define spi_pm_freeze	NULL +#define spi_pm_thaw	NULL +#define spi_pm_poweroff	NULL +#define spi_pm_restore	NULL  #endif +static const struct dev_pm_ops spi_pm = { +	.suspend = spi_pm_suspend, +	.resume = spi_pm_resume, +	.freeze = spi_pm_freeze, +	.thaw = spi_pm_thaw, +	.poweroff = spi_pm_poweroff, +	.restore = spi_pm_restore, +	SET_RUNTIME_PM_OPS( +		pm_generic_runtime_suspend, +		pm_generic_runtime_resume, +		pm_generic_runtime_idle +	) +}; +  struct bus_type spi_bus_type = {  	.name		= "spi",  	.dev_attrs	= spi_dev_attrs,  	.match		= spi_match_device,  	.uevent		= spi_uevent, -	.suspend	= spi_suspend, -	.resume		= spi_resume, +	.pm		= &spi_pm,  };  EXPORT_SYMBOL_GPL(spi_bus_type); | 
