mirror of https://github.com/OpenIPC/firmware.git
129 lines
2.8 KiB
Diff
129 lines
2.8 KiB
Diff
--- linux-4.9.37/drivers/spi/spi.c 2017-07-12 16:42:41.000000000 +0300
|
|
+++ linux-4.9.y/drivers/spi/spi.c 2021-06-07 13:01:34.000000000 +0300
|
|
@@ -323,11 +323,125 @@
|
|
return 0;
|
|
}
|
|
|
|
+#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);
|
|
+
|
|
+ /* suspend will stop irqs and dma; no more i/o */
|
|
+ if (drv) {
|
|
+ if (drv->suspend)
|
|
+ value = drv->suspend(to_spi_device(dev), message);
|
|
+ else
|
|
+ dev_dbg(dev, "... can't suspend\n");
|
|
+ }
|
|
+ return value;
|
|
+}
|
|
+
|
|
+static int spi_legacy_resume(struct device *dev)
|
|
+{
|
|
+ int value = 0;
|
|
+ struct spi_driver *drv = to_spi_driver(dev->driver);
|
|
+
|
|
+ /* resume may restart the i/o queue */
|
|
+ if (drv) {
|
|
+ if (drv->resume)
|
|
+ value = drv->resume(to_spi_device(dev));
|
|
+ else
|
|
+ dev_dbg(dev, "... can't resume\n");
|
|
+ }
|
|
+ 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_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,
|
|
+ NULL
|
|
+ )
|
|
+};
|
|
+
|
|
struct bus_type spi_bus_type = {
|
|
.name = "spi",
|
|
.dev_groups = spi_dev_groups,
|
|
.match = spi_match_device,
|
|
.uevent = spi_uevent,
|
|
+ .pm = &spi_pm,
|
|
};
|
|
EXPORT_SYMBOL_GPL(spi_bus_type);
|
|
|