Commit b9c532c1 authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: distinguish system from runtime suspend

Add a new flag that is set when the hardware is suspended due to a
system suspend operation, distingishing it from runtime suspend.
Use it in the SUSPEND IPA interrupt handler to determine whether to
trigger a system resume because of the event.  Define new suspend
and resume power management callback functions to set and clear the
new flag, respectively.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d430fe4b
...@@ -47,10 +47,12 @@ struct ipa_interconnect { ...@@ -47,10 +47,12 @@ struct ipa_interconnect {
/** /**
* enum ipa_power_flag - IPA power flags * enum ipa_power_flag - IPA power flags
* @IPA_POWER_FLAG_RESUMED: Whether resume from suspend has been signaled * @IPA_POWER_FLAG_RESUMED: Whether resume from suspend has been signaled
* @IPA_POWER_FLAG_SYSTEM: Hardware is system (not runtime) suspended
* @IPA_POWER_FLAG_COUNT: Number of defined power flags * @IPA_POWER_FLAG_COUNT: Number of defined power flags
*/ */
enum ipa_power_flag { enum ipa_power_flag {
IPA_POWER_FLAG_RESUMED, IPA_POWER_FLAG_RESUMED,
IPA_POWER_FLAG_SYSTEM,
IPA_POWER_FLAG_COUNT, /* Last; not a flag */ IPA_POWER_FLAG_COUNT, /* Last; not a flag */
}; };
...@@ -281,6 +283,27 @@ int ipa_clock_put(struct ipa *ipa) ...@@ -281,6 +283,27 @@ int ipa_clock_put(struct ipa *ipa)
return pm_runtime_put(&ipa->pdev->dev); return pm_runtime_put(&ipa->pdev->dev);
} }
static int ipa_suspend(struct device *dev)
{
struct ipa *ipa = dev_get_drvdata(dev);
__set_bit(IPA_POWER_FLAG_SYSTEM, ipa->clock->flags);
return pm_runtime_force_suspend(dev);
}
static int ipa_resume(struct device *dev)
{
struct ipa *ipa = dev_get_drvdata(dev);
int ret;
ret = pm_runtime_force_resume(dev);
__clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->clock->flags);
return ret;
}
/* Return the current IPA core clock rate */ /* Return the current IPA core clock rate */
u32 ipa_clock_rate(struct ipa *ipa) u32 ipa_clock_rate(struct ipa *ipa)
{ {
...@@ -299,11 +322,12 @@ u32 ipa_clock_rate(struct ipa *ipa) ...@@ -299,11 +322,12 @@ u32 ipa_clock_rate(struct ipa *ipa)
*/ */
static void ipa_suspend_handler(struct ipa *ipa, enum ipa_irq_id irq_id) static void ipa_suspend_handler(struct ipa *ipa, enum ipa_irq_id irq_id)
{ {
/* Just report the event, and let system resume handle the rest. /* To handle an IPA interrupt we will have resumed the hardware
* More than one endpoint could signal this; if so, ignore * just to handle the interrupt, so we're done. If we are in a
* all but the first. * system suspend, trigger a system resume.
*/ */
if (!test_and_set_bit(IPA_POWER_FLAG_RESUMED, ipa->clock->flags)) if (!__test_and_set_bit(IPA_POWER_FLAG_RESUMED, ipa->clock->flags))
if (test_bit(IPA_POWER_FLAG_SYSTEM, ipa->clock->flags))
pm_wakeup_dev_event(&ipa->pdev->dev, 0, true); pm_wakeup_dev_event(&ipa->pdev->dev, 0, true);
/* Acknowledge/clear the suspend interrupt on all endpoints */ /* Acknowledge/clear the suspend interrupt on all endpoints */
...@@ -390,8 +414,8 @@ void ipa_clock_exit(struct ipa_clock *clock) ...@@ -390,8 +414,8 @@ void ipa_clock_exit(struct ipa_clock *clock)
} }
const struct dev_pm_ops ipa_pm_ops = { const struct dev_pm_ops ipa_pm_ops = {
.suspend = pm_runtime_force_suspend, .suspend = ipa_suspend,
.resume = pm_runtime_force_resume, .resume = ipa_resume,
.runtime_suspend = ipa_runtime_suspend, .runtime_suspend = ipa_runtime_suspend,
.runtime_resume = ipa_runtime_resume, .runtime_resume = ipa_runtime_resume,
.runtime_idle = ipa_runtime_idle, .runtime_idle = ipa_runtime_idle,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment