162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drivers/base/power/generic_ops.c - Generic PM callbacks for subsystems 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/pm.h> 862306a36Sopenharmony_ci#include <linux/pm_runtime.h> 962306a36Sopenharmony_ci#include <linux/export.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifdef CONFIG_PM 1262306a36Sopenharmony_ci/** 1362306a36Sopenharmony_ci * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems. 1462306a36Sopenharmony_ci * @dev: Device to suspend. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * If PM operations are defined for the @dev's driver and they include 1762306a36Sopenharmony_ci * ->runtime_suspend(), execute it and return its error code. Otherwise, 1862306a36Sopenharmony_ci * return 0. 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ciint pm_generic_runtime_suspend(struct device *dev) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 2362306a36Sopenharmony_ci int ret; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci return ret; 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_runtime_suspend); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/** 3262306a36Sopenharmony_ci * pm_generic_runtime_resume - Generic runtime resume callback for subsystems. 3362306a36Sopenharmony_ci * @dev: Device to resume. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * If PM operations are defined for the @dev's driver and they include 3662306a36Sopenharmony_ci * ->runtime_resume(), execute it and return its error code. Otherwise, 3762306a36Sopenharmony_ci * return 0. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ciint pm_generic_runtime_resume(struct device *dev) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 4262306a36Sopenharmony_ci int ret; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return ret; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_runtime_resume); 4962306a36Sopenharmony_ci#endif /* CONFIG_PM */ 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 5262306a36Sopenharmony_ci/** 5362306a36Sopenharmony_ci * pm_generic_prepare - Generic routine preparing a device for power transition. 5462306a36Sopenharmony_ci * @dev: Device to prepare. 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * Prepare a device for a system-wide power transition. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ciint pm_generic_prepare(struct device *dev) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct device_driver *drv = dev->driver; 6162306a36Sopenharmony_ci int ret = 0; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (drv && drv->pm && drv->pm->prepare) 6462306a36Sopenharmony_ci ret = drv->pm->prepare(dev); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return ret; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/** 7062306a36Sopenharmony_ci * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems. 7162306a36Sopenharmony_ci * @dev: Device to suspend. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ciint pm_generic_suspend_noirq(struct device *dev) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return pm && pm->suspend_noirq ? pm->suspend_noirq(dev) : 0; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_suspend_noirq); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * pm_generic_suspend_late - Generic suspend_late callback for subsystems. 8362306a36Sopenharmony_ci * @dev: Device to suspend. 8462306a36Sopenharmony_ci */ 8562306a36Sopenharmony_ciint pm_generic_suspend_late(struct device *dev) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return pm && pm->suspend_late ? pm->suspend_late(dev) : 0; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_suspend_late); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/** 9462306a36Sopenharmony_ci * pm_generic_suspend - Generic suspend callback for subsystems. 9562306a36Sopenharmony_ci * @dev: Device to suspend. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ciint pm_generic_suspend(struct device *dev) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return pm && pm->suspend ? pm->suspend(dev) : 0; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_suspend); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/** 10662306a36Sopenharmony_ci * pm_generic_freeze_noirq - Generic freeze_noirq callback for subsystems. 10762306a36Sopenharmony_ci * @dev: Device to freeze. 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ciint pm_generic_freeze_noirq(struct device *dev) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return pm && pm->freeze_noirq ? pm->freeze_noirq(dev) : 0; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_freeze_noirq); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/** 11862306a36Sopenharmony_ci * pm_generic_freeze_late - Generic freeze_late callback for subsystems. 11962306a36Sopenharmony_ci * @dev: Device to freeze. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ciint pm_generic_freeze_late(struct device *dev) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci return pm && pm->freeze_late ? pm->freeze_late(dev) : 0; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_freeze_late); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/** 13062306a36Sopenharmony_ci * pm_generic_freeze - Generic freeze callback for subsystems. 13162306a36Sopenharmony_ci * @dev: Device to freeze. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ciint pm_generic_freeze(struct device *dev) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return pm && pm->freeze ? pm->freeze(dev) : 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_freeze); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/** 14262306a36Sopenharmony_ci * pm_generic_poweroff_noirq - Generic poweroff_noirq callback for subsystems. 14362306a36Sopenharmony_ci * @dev: Device to handle. 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ciint pm_generic_poweroff_noirq(struct device *dev) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return pm && pm->poweroff_noirq ? pm->poweroff_noirq(dev) : 0; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * pm_generic_poweroff_late - Generic poweroff_late callback for subsystems. 15562306a36Sopenharmony_ci * @dev: Device to handle. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ciint pm_generic_poweroff_late(struct device *dev) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return pm && pm->poweroff_late ? pm->poweroff_late(dev) : 0; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_poweroff_late); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/** 16662306a36Sopenharmony_ci * pm_generic_poweroff - Generic poweroff callback for subsystems. 16762306a36Sopenharmony_ci * @dev: Device to handle. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ciint pm_generic_poweroff(struct device *dev) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return pm && pm->poweroff ? pm->poweroff(dev) : 0; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_poweroff); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/** 17862306a36Sopenharmony_ci * pm_generic_thaw_noirq - Generic thaw_noirq callback for subsystems. 17962306a36Sopenharmony_ci * @dev: Device to thaw. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ciint pm_generic_thaw_noirq(struct device *dev) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return pm && pm->thaw_noirq ? pm->thaw_noirq(dev) : 0; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_thaw_noirq); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/** 19062306a36Sopenharmony_ci * pm_generic_thaw_early - Generic thaw_early callback for subsystems. 19162306a36Sopenharmony_ci * @dev: Device to thaw. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ciint pm_generic_thaw_early(struct device *dev) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return pm && pm->thaw_early ? pm->thaw_early(dev) : 0; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_thaw_early); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/** 20262306a36Sopenharmony_ci * pm_generic_thaw - Generic thaw callback for subsystems. 20362306a36Sopenharmony_ci * @dev: Device to thaw. 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_ciint pm_generic_thaw(struct device *dev) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci return pm && pm->thaw ? pm->thaw(dev) : 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_thaw); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/** 21462306a36Sopenharmony_ci * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems. 21562306a36Sopenharmony_ci * @dev: Device to resume. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ciint pm_generic_resume_noirq(struct device *dev) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return pm && pm->resume_noirq ? pm->resume_noirq(dev) : 0; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_resume_noirq); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/** 22662306a36Sopenharmony_ci * pm_generic_resume_early - Generic resume_early callback for subsystems. 22762306a36Sopenharmony_ci * @dev: Device to resume. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ciint pm_generic_resume_early(struct device *dev) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci return pm && pm->resume_early ? pm->resume_early(dev) : 0; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_resume_early); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * pm_generic_resume - Generic resume callback for subsystems. 23962306a36Sopenharmony_ci * @dev: Device to resume. 24062306a36Sopenharmony_ci */ 24162306a36Sopenharmony_ciint pm_generic_resume(struct device *dev) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return pm && pm->resume ? pm->resume(dev) : 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_resume); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/** 25062306a36Sopenharmony_ci * pm_generic_restore_noirq - Generic restore_noirq callback for subsystems. 25162306a36Sopenharmony_ci * @dev: Device to restore. 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ciint pm_generic_restore_noirq(struct device *dev) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci return pm && pm->restore_noirq ? pm->restore_noirq(dev) : 0; 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_restore_noirq); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/** 26262306a36Sopenharmony_ci * pm_generic_restore_early - Generic restore_early callback for subsystems. 26362306a36Sopenharmony_ci * @dev: Device to resume. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ciint pm_generic_restore_early(struct device *dev) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return pm && pm->restore_early ? pm->restore_early(dev) : 0; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_restore_early); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/** 27462306a36Sopenharmony_ci * pm_generic_restore - Generic restore callback for subsystems. 27562306a36Sopenharmony_ci * @dev: Device to restore. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ciint pm_generic_restore(struct device *dev) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci return pm && pm->restore ? pm->restore(dev) : 0; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_generic_restore); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/** 28662306a36Sopenharmony_ci * pm_generic_complete - Generic routine completing a device power transition. 28762306a36Sopenharmony_ci * @dev: Device to handle. 28862306a36Sopenharmony_ci * 28962306a36Sopenharmony_ci * Complete a device power transition during a system-wide power transition. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_civoid pm_generic_complete(struct device *dev) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci struct device_driver *drv = dev->driver; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (drv && drv->pm && drv->pm->complete) 29662306a36Sopenharmony_ci drv->pm->complete(dev); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 299