Merge branch 'pm-core'
* pm-core: (29 commits) dmaengine: rcar-dmac: Make DMAC reinit during system resume explicit PM / runtime: Allow no callbacks in pm_runtime_force_suspend|resume() PM / runtime: Check ignore_children in pm_runtime_need_not_resume() PM / runtime: Rework pm_runtime_force_suspend/resume() PM / wakeup: Print warn if device gets enabled as wakeup source during sleep PM / core: Propagate wakeup_path status flag in __device_suspend_late() PM / core: Re-structure code for clearing the direct_complete flag PM: i2c-designware-platdrv: Optimize power management PM: i2c-designware-platdrv: Use DPM_FLAG_SMART_PREPARE PM / mfd: intel-lpss: Use DPM_FLAG_SMART_SUSPEND PCI / PM: Use SMART_SUSPEND and LEAVE_SUSPENDED flags for PCIe ports PM / wakeup: Add device_set_wakeup_path() helper to control wakeup path PM / core: Assign the wakeup_path status flag in __device_prepare() PM / wakeup: Do not fail dev_pm_attach_wake_irq() unnecessarily PM / core: Direct DPM_FLAG_LEAVE_SUSPENDED handling PM / core: Direct DPM_FLAG_SMART_SUSPEND optimization PM / core: Add helpers for subsystem callback selection PM / wakeup: Drop redundant check from device_init_wakeup() PM / wakeup: Drop redundant check from device_set_wakeup_enable() PM / wakeup: only recommend "call"ing device_init_wakeup() once ...
This commit is contained in:
@@ -280,8 +280,6 @@ struct dw_i2c_dev {
|
||||
int (*acquire_lock)(struct dw_i2c_dev *dev);
|
||||
void (*release_lock)(struct dw_i2c_dev *dev);
|
||||
bool pm_disabled;
|
||||
bool suspended;
|
||||
bool skip_resume;
|
||||
void (*disable)(struct dw_i2c_dev *dev);
|
||||
void (*disable_int)(struct dw_i2c_dev *dev);
|
||||
int (*init)(struct dw_i2c_dev *dev);
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include <linux/reset.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "i2c-designware-core.h"
|
||||
|
||||
@@ -372,6 +373,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
||||
ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
dev_pm_set_driver_flags(&pdev->dev,
|
||||
DPM_FLAG_SMART_PREPARE |
|
||||
DPM_FLAG_SMART_SUSPEND |
|
||||
DPM_FLAG_LEAVE_SUSPENDED);
|
||||
|
||||
/* The code below assumes runtime PM to be disabled. */
|
||||
WARN_ON(pm_runtime_enabled(&pdev->dev));
|
||||
|
||||
@@ -435,12 +441,24 @@ MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int dw_i2c_plat_prepare(struct device *dev)
|
||||
{
|
||||
return pm_runtime_suspended(dev);
|
||||
/*
|
||||
* If the ACPI companion device object is present for this device, it
|
||||
* may be accessed during suspend and resume of other devices via I2C
|
||||
* operation regions, so tell the PM core and middle layers to avoid
|
||||
* skipping system suspend/resume callbacks for it in that case.
|
||||
*/
|
||||
return !has_acpi_companion(dev);
|
||||
}
|
||||
|
||||
static void dw_i2c_plat_complete(struct device *dev)
|
||||
{
|
||||
if (dev->power.direct_complete)
|
||||
/*
|
||||
* The device can only be in runtime suspend at this point if it has not
|
||||
* been resumed throughout the ending system suspend/resume cycle, so if
|
||||
* the platform firmware might mess up with it, request the runtime PM
|
||||
* framework to resume it.
|
||||
*/
|
||||
if (pm_runtime_suspended(dev) && pm_resume_via_firmware())
|
||||
pm_request_resume(dev);
|
||||
}
|
||||
#else
|
||||
@@ -453,16 +471,9 @@ static int dw_i2c_plat_suspend(struct device *dev)
|
||||
{
|
||||
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (i_dev->suspended) {
|
||||
i_dev->skip_resume = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i_dev->disable(i_dev);
|
||||
i2c_dw_plat_prepare_clk(i_dev, false);
|
||||
|
||||
i_dev->suspended = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -470,19 +481,9 @@ static int dw_i2c_plat_resume(struct device *dev)
|
||||
{
|
||||
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (!i_dev->suspended)
|
||||
return 0;
|
||||
|
||||
if (i_dev->skip_resume) {
|
||||
i_dev->skip_resume = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i2c_dw_plat_prepare_clk(i_dev, true);
|
||||
i_dev->init(i_dev);
|
||||
|
||||
i_dev->suspended = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user