|
@@ -1032,15 +1032,12 @@ static int genpd_prepare(struct device *dev)
|
|
static int genpd_finish_suspend(struct device *dev, bool poweroff)
|
|
static int genpd_finish_suspend(struct device *dev, bool poweroff)
|
|
{
|
|
{
|
|
struct generic_pm_domain *genpd;
|
|
struct generic_pm_domain *genpd;
|
|
- int ret;
|
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
genpd = dev_to_genpd(dev);
|
|
genpd = dev_to_genpd(dev);
|
|
if (IS_ERR(genpd))
|
|
if (IS_ERR(genpd))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
if (poweroff)
|
|
if (poweroff)
|
|
ret = pm_generic_poweroff_noirq(dev);
|
|
ret = pm_generic_poweroff_noirq(dev);
|
|
else
|
|
else
|
|
@@ -1048,10 +1045,19 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff)
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
|
- ret = pm_runtime_force_suspend(dev);
|
|
|
|
- if (ret)
|
|
|
|
|
|
+ if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start &&
|
|
|
|
+ !pm_runtime_status_suspended(dev)) {
|
|
|
|
+ ret = genpd_stop_dev(genpd, dev);
|
|
|
|
+ if (ret) {
|
|
|
|
+ if (poweroff)
|
|
|
|
+ pm_generic_restore_noirq(dev);
|
|
|
|
+ else
|
|
|
|
+ pm_generic_resume_noirq(dev);
|
|
return ret;
|
|
return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
genpd_lock(genpd);
|
|
genpd_lock(genpd);
|
|
@@ -1085,7 +1091,7 @@ static int genpd_suspend_noirq(struct device *dev)
|
|
static int genpd_resume_noirq(struct device *dev)
|
|
static int genpd_resume_noirq(struct device *dev)
|
|
{
|
|
{
|
|
struct generic_pm_domain *genpd;
|
|
struct generic_pm_domain *genpd;
|
|
- int ret = 0;
|
|
|
|
|
|
+ int ret;
|
|
|
|
|
|
dev_dbg(dev, "%s()\n", __func__);
|
|
dev_dbg(dev, "%s()\n", __func__);
|
|
|
|
|
|
@@ -1094,21 +1100,21 @@ static int genpd_resume_noirq(struct device *dev)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd))
|
|
if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd))
|
|
- return 0;
|
|
|
|
|
|
+ return pm_generic_resume_noirq(dev);
|
|
|
|
|
|
genpd_lock(genpd);
|
|
genpd_lock(genpd);
|
|
genpd_sync_power_on(genpd, true, 0);
|
|
genpd_sync_power_on(genpd, true, 0);
|
|
genpd->suspended_count--;
|
|
genpd->suspended_count--;
|
|
genpd_unlock(genpd);
|
|
genpd_unlock(genpd);
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
|
- ret = pm_runtime_force_resume(dev);
|
|
|
|
-
|
|
|
|
- ret = pm_generic_resume_noirq(dev);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start &&
|
|
|
|
+ !pm_runtime_status_suspended(dev)) {
|
|
|
|
+ ret = genpd_start_dev(genpd, dev);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
+ return pm_generic_resume_noirq(dev);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1135,8 +1141,9 @@ static int genpd_freeze_noirq(struct device *dev)
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
|
- ret = pm_runtime_force_suspend(dev);
|
|
|
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start &&
|
|
|
|
+ !pm_runtime_status_suspended(dev))
|
|
|
|
+ ret = genpd_stop_dev(genpd, dev);
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -1159,8 +1166,9 @@ static int genpd_thaw_noirq(struct device *dev)
|
|
if (IS_ERR(genpd))
|
|
if (IS_ERR(genpd))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
|
- ret = pm_runtime_force_resume(dev);
|
|
|
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start &&
|
|
|
|
+ !pm_runtime_status_suspended(dev)) {
|
|
|
|
+ ret = genpd_start_dev(genpd, dev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -1217,8 +1225,9 @@ static int genpd_restore_noirq(struct device *dev)
|
|
genpd_sync_power_on(genpd, true, 0);
|
|
genpd_sync_power_on(genpd, true, 0);
|
|
genpd_unlock(genpd);
|
|
genpd_unlock(genpd);
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
|
- ret = pm_runtime_force_resume(dev);
|
|
|
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start &&
|
|
|
|
+ !pm_runtime_status_suspended(dev)) {
|
|
|
|
+ ret = genpd_start_dev(genpd, dev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -2199,20 +2208,8 @@ int genpd_dev_pm_attach(struct device *dev)
|
|
|
|
|
|
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
|
|
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
|
|
"#power-domain-cells", 0, &pd_args);
|
|
"#power-domain-cells", 0, &pd_args);
|
|
- if (ret < 0) {
|
|
|
|
- if (ret != -ENOENT)
|
|
|
|
- return ret;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Try legacy Samsung-specific bindings
|
|
|
|
- * (for backwards compatibility of DT ABI)
|
|
|
|
- */
|
|
|
|
- pd_args.args_count = 0;
|
|
|
|
- pd_args.np = of_parse_phandle(dev->of_node,
|
|
|
|
- "samsung,power-domain", 0);
|
|
|
|
- if (!pd_args.np)
|
|
|
|
- return -ENOENT;
|
|
|
|
- }
|
|
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
|
|
mutex_lock(&gpd_list_lock);
|
|
mutex_lock(&gpd_list_lock);
|
|
pd = genpd_get_from_provider(&pd_args);
|
|
pd = genpd_get_from_provider(&pd_args);
|