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>
This commit is contained in:
committed by
Rafael J. Wysocki
parent
62bcb91573
commit
3ae22e8c8a
@@ -28,6 +28,7 @@
|
|||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/of_spi.h>
|
#include <linux/of_spi.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
static void spidev_release(struct device *dev)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int spi_legacy_suspend(struct device *dev, pm_message_t message)
|
||||||
static int spi_suspend(struct device *dev, pm_message_t message)
|
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
struct spi_driver *drv = to_spi_driver(dev->driver);
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spi_resume(struct device *dev)
|
static int spi_legacy_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
struct spi_driver *drv = to_spi_driver(dev->driver);
|
struct spi_driver *drv = to_spi_driver(dev->driver);
|
||||||
@@ -132,18 +132,94 @@ static int spi_resume(struct device *dev)
|
|||||||
return value;
|
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
|
#else
|
||||||
#define spi_suspend NULL
|
#define spi_pm_suspend NULL
|
||||||
#define spi_resume 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
|
#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 = {
|
struct bus_type spi_bus_type = {
|
||||||
.name = "spi",
|
.name = "spi",
|
||||||
.dev_attrs = spi_dev_attrs,
|
.dev_attrs = spi_dev_attrs,
|
||||||
.match = spi_match_device,
|
.match = spi_match_device,
|
||||||
.uevent = spi_uevent,
|
.uevent = spi_uevent,
|
||||||
.suspend = spi_suspend,
|
.pm = &spi_pm,
|
||||||
.resume = spi_resume,
|
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(spi_bus_type);
|
EXPORT_SYMBOL_GPL(spi_bus_type);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user