===================================================================
@@ -358,6 +358,7 @@ static int dw_i2c_plat_probe(struct plat
if (dev->pm_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
+ pdev->dev.power.driver_flags = DPM_FLAG_SAFE_SUSPEND;
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
@@ -413,31 +414,23 @@ static const struct of_device_id dw_i2c_
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif
-#ifdef CONFIG_PM_SLEEP
-static int dw_i2c_plat_prepare(struct device *dev)
-{
- return pm_runtime_suspended(dev);
-}
-
-static void dw_i2c_plat_complete(struct device *dev)
-{
- if (dev->power.direct_complete)
- pm_request_resume(dev);
-}
-#else
-#define dw_i2c_plat_prepare NULL
-#define dw_i2c_plat_complete NULL
-#endif
-
#ifdef CONFIG_PM
static int dw_i2c_plat_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
+ if (i_dev->suspended) {
+ i_dev->suspend_skipped = true;
+ return 0;
+ }
+
i_dev->disable(i_dev);
i2c_dw_plat_prepare_clk(i_dev, false);
+ i_dev->suspended = true;
+ i_dev->suspend_skipped = false;
+
return 0;
}
@@ -446,6 +439,13 @@ static int dw_i2c_plat_resume(struct dev
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
+ if (!i_dev->suspended || i_dev->suspend_skipped) {
+ i_dev->suspend_skipped = false;
+ return 0;
+ }
+
+ i_dev->suspended = false;
+
i2c_dw_plat_prepare_clk(i_dev, true);
i_dev->init(i_dev);
@@ -453,9 +453,7 @@ static int dw_i2c_plat_resume(struct dev
}
static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
- .prepare = dw_i2c_plat_prepare,
- .complete = dw_i2c_plat_complete,
- SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
};
===================================================================
@@ -280,6 +280,8 @@ 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 suspend_skipped;
void (*disable)(struct dw_i2c_dev *dev);
void (*disable_int)(struct dw_i2c_dev *dev);
int (*init)(struct dw_i2c_dev *dev);